diff options
author | Ian Lance Taylor <iant@golang.org> | 2021-07-30 14:28:58 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2021-08-12 20:23:07 -0700 |
commit | c5b21c3f4c17b0649155035d2f9aa97b2da8a813 (patch) | |
tree | c6d3a68b503ba5b16182acbb958e3e5dbc95a43b /libgo/go | |
parent | 72be20e20299ec57b4bc9ba03d5b7d6bf10e97cc (diff) | |
download | gcc-c5b21c3f4c17b0649155035d2f9aa97b2da8a813.zip gcc-c5b21c3f4c17b0649155035d2f9aa97b2da8a813.tar.gz gcc-c5b21c3f4c17b0649155035d2f9aa97b2da8a813.tar.bz2 |
libgo: update to Go1.17rc2
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/341629
Diffstat (limited to 'libgo/go')
1944 files changed, 73883 insertions, 22608 deletions
diff --git a/libgo/go/archive/tar/stat_actime1.go b/libgo/go/archive/tar/stat_actime1.go index 2a7f7f3..71cece5 100644 --- a/libgo/go/archive/tar/stat_actime1.go +++ b/libgo/go/archive/tar/stat_actime1.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || hurd || linux || dragonfly || openbsd || solaris // +build aix hurd linux dragonfly openbsd solaris package tar diff --git a/libgo/go/archive/tar/stat_actime2.go b/libgo/go/archive/tar/stat_actime2.go index 6f17dbe..5a9a35c 100644 --- a/libgo/go/archive/tar/stat_actime2.go +++ b/libgo/go/archive/tar/stat_actime2.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || freebsd || netbsd // +build darwin freebsd netbsd package tar diff --git a/libgo/go/archive/tar/stat_unix.go b/libgo/go/archive/tar/stat_unix.go index 93a3fcd..f27df67 100644 --- a/libgo/go/archive/tar/stat_unix.go +++ b/libgo/go/archive/tar/stat_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || hurd || linux || darwin || dragonfly || freebsd || openbsd || netbsd || solaris // +build aix hurd linux darwin dragonfly freebsd openbsd netbsd solaris package tar diff --git a/libgo/go/archive/tar/tar_test.go b/libgo/go/archive/tar/tar_test.go index 91b3840..e9fafc7 100644 --- a/libgo/go/archive/tar/tar_test.go +++ b/libgo/go/archive/tar/tar_test.go @@ -262,16 +262,11 @@ func TestFileInfoHeaderDir(t *testing.T) { func TestFileInfoHeaderSymlink(t *testing.T) { testenv.MustHaveSymlink(t) - tmpdir, err := os.MkdirTemp("", "TestFileInfoHeaderSymlink") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) + tmpdir := t.TempDir() link := filepath.Join(tmpdir, "link") target := tmpdir - err = os.Symlink(target, link) - if err != nil { + if err := os.Symlink(target, link); err != nil { t.Fatal(err) } fi, err := os.Lstat(link) diff --git a/libgo/go/archive/zip/reader.go b/libgo/go/archive/zip/reader.go index ddef2b7..2d53f4c 100644 --- a/libgo/go/archive/zip/reader.go +++ b/libgo/go/archive/zip/reader.go @@ -52,12 +52,9 @@ type File struct { FileHeader zip *Reader zipr io.ReaderAt - zipsize int64 headerOffset int64 -} - -func (f *File) hasDataDescriptor() bool { - return f.Flags&0x8 != 0 + zip64 bool // zip64 extended information extra field presence + descErr error // error reading the data descriptor during init } // OpenReader will open the Zip file specified by name and return a ReadCloser. @@ -120,7 +117,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error { // a bad one, and then only report an ErrFormat or UnexpectedEOF if // the file count modulo 65536 is incorrect. for { - f := &File{zip: z, zipr: r, zipsize: size} + f := &File{zip: z, zipr: r} err = readDirectoryHeader(f, buf) if err == ErrFormat || err == io.ErrUnexpectedEOF { break @@ -128,6 +125,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error { if err != nil { return err } + f.readDataDescriptor() z.File = append(z.File, f) } if uint16(len(z.File)) != uint16(end.directoryRecords) { // only compare 16 bits here @@ -188,26 +186,68 @@ func (f *File) Open() (io.ReadCloser, error) { return nil, ErrAlgorithm } var rc io.ReadCloser = dcomp(r) - var desr io.Reader - if f.hasDataDescriptor() { - desr = io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, dataDescriptorLen) - } rc = &checksumReader{ rc: rc, hash: crc32.NewIEEE(), f: f, - desr: desr, } return rc, nil } +// OpenRaw returns a Reader that provides access to the File's contents without +// decompression. +func (f *File) OpenRaw() (io.Reader, error) { + bodyOffset, err := f.findBodyOffset() + if err != nil { + return nil, err + } + r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset, int64(f.CompressedSize64)) + return r, nil +} + +func (f *File) readDataDescriptor() { + if !f.hasDataDescriptor() { + return + } + + bodyOffset, err := f.findBodyOffset() + if err != nil { + f.descErr = err + return + } + + // In section 4.3.9.2 of the spec: "However ZIP64 format MAY be used + // regardless of the size of a file. When extracting, if the zip64 + // extended information extra field is present for the file the + // compressed and uncompressed sizes will be 8 byte values." + // + // Historically, this package has used the compressed and uncompressed + // sizes from the central directory to determine if the package is + // zip64. + // + // For this case we allow either the extra field or sizes to determine + // the data descriptor length. + zip64 := f.zip64 || f.isZip64() + n := int64(dataDescriptorLen) + if zip64 { + n = dataDescriptor64Len + } + size := int64(f.CompressedSize64) + r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, n) + dd, err := readDataDescriptor(r, zip64) + if err != nil { + f.descErr = err + return + } + f.CRC32 = dd.crc32 +} + type checksumReader struct { rc io.ReadCloser hash hash.Hash32 nread uint64 // number of bytes read so far f *File - desr io.Reader // if non-nil, where to read the data descriptor - err error // sticky error + err error // sticky error } func (r *checksumReader) Stat() (fs.FileInfo, error) { @@ -228,12 +268,12 @@ func (r *checksumReader) Read(b []byte) (n int, err error) { if r.nread != r.f.UncompressedSize64 { return 0, io.ErrUnexpectedEOF } - if r.desr != nil { - if err1 := readDataDescriptor(r.desr, r.f); err1 != nil { - if err1 == io.EOF { + if r.f.hasDataDescriptor() { + if r.f.descErr != nil { + if r.f.descErr == io.EOF { err = io.ErrUnexpectedEOF } else { - err = err1 + err = r.f.descErr } } else if r.hash.Sum32() != r.f.CRC32 { err = ErrChecksum @@ -344,6 +384,8 @@ parseExtras: switch fieldTag { case zip64ExtraID: + f.zip64 = true + // update directory values from the zip64 extra block. // They should only be consulted if the sizes read earlier // are maxed out. @@ -443,8 +485,9 @@ parseExtras: return nil } -func readDataDescriptor(r io.Reader, f *File) error { - var buf [dataDescriptorLen]byte +func readDataDescriptor(r io.Reader, zip64 bool) (*dataDescriptor, error) { + // Create enough space for the largest possible size + var buf [dataDescriptor64Len]byte // The spec says: "Although not originally assigned a // signature, the value 0x08074b50 has commonly been adopted @@ -454,10 +497,9 @@ func readDataDescriptor(r io.Reader, f *File) error { // descriptors and should account for either case when reading // ZIP files to ensure compatibility." // - // dataDescriptorLen includes the size of the signature but - // first read just those 4 bytes to see if it exists. + // First read just those 4 bytes to see if the signature exists. if _, err := io.ReadFull(r, buf[:4]); err != nil { - return err + return nil, err } off := 0 maybeSig := readBuf(buf[:4]) @@ -466,21 +508,28 @@ func readDataDescriptor(r io.Reader, f *File) error { // bytes. off += 4 } - if _, err := io.ReadFull(r, buf[off:12]); err != nil { - return err + + end := dataDescriptorLen - 4 + if zip64 { + end = dataDescriptor64Len - 4 } - b := readBuf(buf[:12]) - if b.uint32() != f.CRC32 { - return ErrChecksum + if _, err := io.ReadFull(r, buf[off:end]); err != nil { + return nil, err } + b := readBuf(buf[:end]) - // The two sizes that follow here can be either 32 bits or 64 bits - // but the spec is not very clear on this and different - // interpretations has been made causing incompatibilities. We - // already have the sizes from the central directory so we can - // just ignore these. + out := &dataDescriptor{ + crc32: b.uint32(), + } - return nil + if zip64 { + out.compressedSize = b.uint64() + out.uncompressedSize = b.uint64() + } else { + out.compressedSize = uint64(b.uint32()) + out.uncompressedSize = uint64(b.uint32()) + } + return out, nil } func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error) { diff --git a/libgo/go/archive/zip/reader_test.go b/libgo/go/archive/zip/reader_test.go index 471be27..37dafe6 100644 --- a/libgo/go/archive/zip/reader_test.go +++ b/libgo/go/archive/zip/reader_test.go @@ -499,9 +499,15 @@ func TestReader(t *testing.T) { func readTestZip(t *testing.T, zt ZipTest) { var z *Reader var err error + var raw []byte if zt.Source != nil { rat, size := zt.Source() z, err = NewReader(rat, size) + raw = make([]byte, size) + if _, err := rat.ReadAt(raw, 0); err != nil { + t.Errorf("ReadAt error=%v", err) + return + } } else { path := filepath.Join("testdata", zt.Name) if zt.Obscured { @@ -519,6 +525,12 @@ func readTestZip(t *testing.T, zt ZipTest) { defer rc.Close() z = &rc.Reader } + var err2 error + raw, err2 = os.ReadFile(path) + if err2 != nil { + t.Errorf("ReadFile(%s) error=%v", path, err2) + return + } } if err != zt.Error { t.Errorf("error=%v, want %v", err, zt.Error) @@ -545,7 +557,7 @@ func readTestZip(t *testing.T, zt ZipTest) { // test read of each file for i, ft := range zt.File { - readTestFile(t, zt, ft, z.File[i]) + readTestFile(t, zt, ft, z.File[i], raw) } if t.Failed() { return @@ -557,7 +569,7 @@ func readTestZip(t *testing.T, zt ZipTest) { for i := 0; i < 5; i++ { for j, ft := range zt.File { go func(j int, ft ZipTestFile) { - readTestFile(t, zt, ft, z.File[j]) + readTestFile(t, zt, ft, z.File[j], raw) done <- true }(j, ft) n++ @@ -574,7 +586,7 @@ func equalTimeAndZone(t1, t2 time.Time) bool { return t1.Equal(t2) && name1 == name2 && offset1 == offset2 } -func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) { +func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File, raw []byte) { if f.Name != ft.Name { t.Errorf("name=%q, want %q", f.Name, ft.Name) } @@ -594,6 +606,31 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) { t.Errorf("%v: UncompressedSize=%#x does not match UncompressedSize64=%#x", f.Name, size, f.UncompressedSize64) } + // Check that OpenRaw returns the correct byte segment + rw, err := f.OpenRaw() + if err != nil { + t.Errorf("%v: OpenRaw error=%v", f.Name, err) + return + } + start, err := f.DataOffset() + if err != nil { + t.Errorf("%v: DataOffset error=%v", f.Name, err) + return + } + got, err := io.ReadAll(rw) + if err != nil { + t.Errorf("%v: OpenRaw ReadAll error=%v", f.Name, err) + return + } + end := uint64(start) + f.CompressedSize64 + want := raw[start:end] + if !bytes.Equal(got, want) { + t.Logf("got %q", got) + t.Logf("want %q", want) + t.Errorf("%v: OpenRaw returned unexpected bytes", f.Name) + return + } + r, err := f.Open() if err != nil { t.Errorf("%v", err) @@ -776,8 +813,8 @@ func returnRecursiveZip() (r io.ReaderAt, size int64) { // "archive/zip" // "bytes" // "io" -// "io/ioutil" // "log" +// "os" // ) // // type zeros struct{} @@ -1167,6 +1204,128 @@ func TestCVE202127919(t *testing.T) { } } +func TestReadDataDescriptor(t *testing.T) { + tests := []struct { + desc string + in []byte + zip64 bool + want *dataDescriptor + wantErr error + }{{ + desc: "valid 32 bit with signature", + in: []byte{ + 0x50, 0x4b, 0x07, 0x08, // signature + 0x00, 0x01, 0x02, 0x03, // crc32 + 0x04, 0x05, 0x06, 0x07, // compressed size + 0x08, 0x09, 0x0a, 0x0b, // uncompressed size + }, + want: &dataDescriptor{ + crc32: 0x03020100, + compressedSize: 0x07060504, + uncompressedSize: 0x0b0a0908, + }, + }, { + desc: "valid 32 bit without signature", + in: []byte{ + 0x00, 0x01, 0x02, 0x03, // crc32 + 0x04, 0x05, 0x06, 0x07, // compressed size + 0x08, 0x09, 0x0a, 0x0b, // uncompressed size + }, + want: &dataDescriptor{ + crc32: 0x03020100, + compressedSize: 0x07060504, + uncompressedSize: 0x0b0a0908, + }, + }, { + desc: "valid 64 bit with signature", + in: []byte{ + 0x50, 0x4b, 0x07, 0x08, // signature + 0x00, 0x01, 0x02, 0x03, // crc32 + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, // uncompressed size + }, + zip64: true, + want: &dataDescriptor{ + crc32: 0x03020100, + compressedSize: 0x0b0a090807060504, + uncompressedSize: 0x131211100f0e0d0c, + }, + }, { + desc: "valid 64 bit without signature", + in: []byte{ + 0x00, 0x01, 0x02, 0x03, // crc32 + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, // uncompressed size + }, + zip64: true, + want: &dataDescriptor{ + crc32: 0x03020100, + compressedSize: 0x0b0a090807060504, + uncompressedSize: 0x131211100f0e0d0c, + }, + }, { + desc: "invalid 32 bit with signature", + in: []byte{ + 0x50, 0x4b, 0x07, 0x08, // signature + 0x00, 0x01, 0x02, 0x03, // crc32 + 0x04, 0x05, // unexpected end + }, + wantErr: io.ErrUnexpectedEOF, + }, { + desc: "invalid 32 bit without signature", + in: []byte{ + 0x00, 0x01, 0x02, 0x03, // crc32 + 0x04, 0x05, // unexpected end + }, + wantErr: io.ErrUnexpectedEOF, + }, { + desc: "invalid 64 bit with signature", + in: []byte{ + 0x50, 0x4b, 0x07, 0x08, // signature + 0x00, 0x01, 0x02, 0x03, // crc32 + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, // unexpected end + }, + zip64: true, + wantErr: io.ErrUnexpectedEOF, + }, { + desc: "invalid 64 bit without signature", + in: []byte{ + 0x00, 0x01, 0x02, 0x03, // crc32 + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, // unexpected end + }, + zip64: true, + wantErr: io.ErrUnexpectedEOF, + }} + + for _, test := range tests { + t.Run(test.desc, func(t *testing.T) { + r := bytes.NewReader(test.in) + + desc, err := readDataDescriptor(r, test.zip64) + if err != test.wantErr { + t.Fatalf("got err %v; want nil", err) + } + if test.want == nil { + return + } + if desc == nil { + t.Fatalf("got nil DataDescriptor; want non-nil") + } + if desc.crc32 != test.want.crc32 { + t.Errorf("got CRC32 %#x; want %#x", desc.crc32, test.want.crc32) + } + if desc.compressedSize != test.want.compressedSize { + t.Errorf("got CompressedSize %#x; want %#x", desc.compressedSize, test.want.compressedSize) + } + if desc.uncompressedSize != test.want.uncompressedSize { + t.Errorf("got UncompressedSize %#x; want %#x", desc.uncompressedSize, test.want.uncompressedSize) + } + }) + } +} + func TestCVE202133196(t *testing.T) { // Archive that indicates it has 1 << 128 -1 files, // this would previously cause a panic due to attempting diff --git a/libgo/go/archive/zip/struct.go b/libgo/go/archive/zip/struct.go index 4dd29f3..ff9f605 100644 --- a/libgo/go/archive/zip/struct.go +++ b/libgo/go/archive/zip/struct.go @@ -42,7 +42,7 @@ const ( directoryHeaderLen = 46 // + filename + extra + comment directoryEndLen = 22 // + comment dataDescriptorLen = 16 // four uint32: descriptor signature, crc32, compressed size, size - dataDescriptor64Len = 24 // descriptor with 8 byte sizes + dataDescriptor64Len = 24 // two uint32: signature, crc32 | two uint64: compressed size, size directory64LocLen = 20 // directory64EndLen = 56 // + extra @@ -315,6 +315,10 @@ func (h *FileHeader) isZip64() bool { return h.CompressedSize64 >= uint32max || h.UncompressedSize64 >= uint32max } +func (f *FileHeader) hasDataDescriptor() bool { + return f.Flags&0x8 != 0 +} + func msdosModeToFileMode(m uint32) (mode fs.FileMode) { if m&msdosDir != 0 { mode = fs.ModeDir | 0777 @@ -341,11 +345,9 @@ func fileModeToUnixMode(mode fs.FileMode) uint32 { case fs.ModeSocket: m = s_IFSOCK case fs.ModeDevice: - if mode&fs.ModeCharDevice != 0 { - m = s_IFCHR - } else { - m = s_IFBLK - } + m = s_IFBLK + case fs.ModeDevice | fs.ModeCharDevice: + m = s_IFCHR } if mode&fs.ModeSetuid != 0 { m |= s_ISUID @@ -388,3 +390,11 @@ func unixModeToFileMode(m uint32) fs.FileMode { } return mode } + +// dataDescriptor holds the data descriptor that optionally follows the file +// contents in the zip file. +type dataDescriptor struct { + crc32 uint32 + compressedSize uint64 + uncompressedSize uint64 +} diff --git a/libgo/go/archive/zip/writer.go b/libgo/go/archive/zip/writer.go index cdc534e..3b23cc3 100644 --- a/libgo/go/archive/zip/writer.go +++ b/libgo/go/archive/zip/writer.go @@ -37,6 +37,7 @@ type Writer struct { type header struct { *FileHeader offset uint64 + raw bool } // NewWriter returns a new Writer writing a zip file to w. @@ -245,22 +246,31 @@ func detectUTF8(s string) (valid, require bool) { return true, require } +// prepare performs the bookkeeping operations required at the start of +// CreateHeader and CreateRaw. +func (w *Writer) prepare(fh *FileHeader) error { + if w.last != nil && !w.last.closed { + if err := w.last.close(); err != nil { + return err + } + } + if len(w.dir) > 0 && w.dir[len(w.dir)-1].FileHeader == fh { + // See https://golang.org/issue/11144 confusion. + return errors.New("archive/zip: invalid duplicate FileHeader") + } + return nil +} + // CreateHeader adds a file to the zip archive using the provided FileHeader // for the file metadata. Writer takes ownership of fh and may mutate // its fields. The caller must not modify fh after calling CreateHeader. // // This returns a Writer to which the file contents should be written. // The file's contents must be written to the io.Writer before the next -// call to Create, CreateHeader, or Close. +// call to Create, CreateHeader, CreateRaw, or Close. func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) { - if w.last != nil && !w.last.closed { - if err := w.last.close(); err != nil { - return nil, err - } - } - if len(w.dir) > 0 && w.dir[len(w.dir)-1].FileHeader == fh { - // See https://golang.org/issue/11144 confusion. - return nil, errors.New("archive/zip: invalid duplicate FileHeader") + if err := w.prepare(fh); err != nil { + return nil, err } // The ZIP format has a sad state of affairs regarding character encoding. @@ -365,7 +375,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) { ow = fw } w.dir = append(w.dir, h) - if err := writeHeader(w.cw, fh); err != nil { + if err := writeHeader(w.cw, h); err != nil { return nil, err } // If we're creating a directory, fw is nil. @@ -373,7 +383,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) { return ow, nil } -func writeHeader(w io.Writer, h *FileHeader) error { +func writeHeader(w io.Writer, h *header) error { const maxUint16 = 1<<16 - 1 if len(h.Name) > maxUint16 { return errLongName @@ -390,9 +400,20 @@ func writeHeader(w io.Writer, h *FileHeader) error { b.uint16(h.Method) b.uint16(h.ModifiedTime) b.uint16(h.ModifiedDate) - b.uint32(0) // since we are writing a data descriptor crc32, - b.uint32(0) // compressed size, - b.uint32(0) // and uncompressed size should be zero + // In raw mode (caller does the compression), the values are either + // written here or in the trailing data descriptor based on the header + // flags. + if h.raw && !h.hasDataDescriptor() { + b.uint32(h.CRC32) + b.uint32(uint32(min64(h.CompressedSize64, uint32max))) + b.uint32(uint32(min64(h.UncompressedSize64, uint32max))) + } else { + // When this package handle the compression, these values are + // always written to the trailing data descriptor. + b.uint32(0) // crc32 + b.uint32(0) // compressed size + b.uint32(0) // uncompressed size + } b.uint16(uint16(len(h.Name))) b.uint16(uint16(len(h.Extra))) if _, err := w.Write(buf[:]); err != nil { @@ -405,6 +426,65 @@ func writeHeader(w io.Writer, h *FileHeader) error { return err } +func min64(x, y uint64) uint64 { + if x < y { + return x + } + return y +} + +// CreateRaw adds a file to the zip archive using the provided FileHeader and +// returns a Writer to which the file contents should be written. The file's +// contents must be written to the io.Writer before the next call to Create, +// CreateHeader, CreateRaw, or Close. +// +// In contrast to CreateHeader, the bytes passed to Writer are not compressed. +func (w *Writer) CreateRaw(fh *FileHeader) (io.Writer, error) { + if err := w.prepare(fh); err != nil { + return nil, err + } + + fh.CompressedSize = uint32(min64(fh.CompressedSize64, uint32max)) + fh.UncompressedSize = uint32(min64(fh.UncompressedSize64, uint32max)) + + h := &header{ + FileHeader: fh, + offset: uint64(w.cw.count), + raw: true, + } + w.dir = append(w.dir, h) + if err := writeHeader(w.cw, h); err != nil { + return nil, err + } + + if strings.HasSuffix(fh.Name, "/") { + w.last = nil + return dirWriter{}, nil + } + + fw := &fileWriter{ + header: h, + zipw: w.cw, + } + w.last = fw + return fw, nil +} + +// Copy copies the file f (obtained from a Reader) into w. It copies the raw +// form directly bypassing decompression, compression, and validation. +func (w *Writer) Copy(f *File) error { + r, err := f.OpenRaw() + if err != nil { + return err + } + fw, err := w.CreateRaw(&f.FileHeader) + if err != nil { + return err + } + _, err = io.Copy(fw, r) + return err +} + // RegisterCompressor registers or overrides a custom compressor for a specific // method ID. If a compressor for a given method is not found, Writer will // default to looking up the compressor at the package level. @@ -446,6 +526,9 @@ func (w *fileWriter) Write(p []byte) (int, error) { if w.closed { return 0, errors.New("zip: write to closed file") } + if w.raw { + return w.zipw.Write(p) + } w.crc32.Write(p) return w.rawCount.Write(p) } @@ -455,6 +538,9 @@ func (w *fileWriter) close() error { return errors.New("zip: file closed twice") } w.closed = true + if w.raw { + return w.writeDataDescriptor() + } if err := w.comp.Close(); err != nil { return err } @@ -474,26 +560,33 @@ func (w *fileWriter) close() error { fh.UncompressedSize = uint32(fh.UncompressedSize64) } + return w.writeDataDescriptor() +} + +func (w *fileWriter) writeDataDescriptor() error { + if !w.hasDataDescriptor() { + return nil + } // Write data descriptor. This is more complicated than one would // think, see e.g. comments in zipfile.c:putextended() and // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7073588. // The approach here is to write 8 byte sizes if needed without // adding a zip64 extra in the local header (too late anyway). var buf []byte - if fh.isZip64() { + if w.isZip64() { buf = make([]byte, dataDescriptor64Len) } else { buf = make([]byte, dataDescriptorLen) } b := writeBuf(buf) b.uint32(dataDescriptorSignature) // de-facto standard, required by OS X - b.uint32(fh.CRC32) - if fh.isZip64() { - b.uint64(fh.CompressedSize64) - b.uint64(fh.UncompressedSize64) + b.uint32(w.CRC32) + if w.isZip64() { + b.uint64(w.CompressedSize64) + b.uint64(w.UncompressedSize64) } else { - b.uint32(fh.CompressedSize) - b.uint32(fh.UncompressedSize) + b.uint32(w.CompressedSize) + b.uint32(w.UncompressedSize) } _, err := w.zipw.Write(buf) return err diff --git a/libgo/go/archive/zip/writer_test.go b/libgo/go/archive/zip/writer_test.go index 5985144..97c6c52 100644 --- a/libgo/go/archive/zip/writer_test.go +++ b/libgo/go/archive/zip/writer_test.go @@ -6,8 +6,10 @@ package zip import ( "bytes" + "compress/flate" "encoding/binary" "fmt" + "hash/crc32" "io" "io/fs" "math/rand" @@ -57,6 +59,18 @@ var writeTests = []WriteTest{ Method: Deflate, Mode: 0755 | fs.ModeSymlink, }, + { + Name: "device", + Data: []byte("device file"), + Method: Deflate, + Mode: 0755 | fs.ModeDevice, + }, + { + Name: "chardevice", + Data: []byte("char device file"), + Method: Deflate, + Mode: 0755 | fs.ModeDevice | fs.ModeCharDevice, + }, } func TestWriter(t *testing.T) { @@ -353,6 +367,171 @@ func TestWriterDirAttributes(t *testing.T) { } } +func TestWriterCopy(t *testing.T) { + // make a zip file + buf := new(bytes.Buffer) + w := NewWriter(buf) + for _, wt := range writeTests { + testCreate(t, w, &wt) + } + if err := w.Close(); err != nil { + t.Fatal(err) + } + + // read it back + src, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len())) + if err != nil { + t.Fatal(err) + } + for i, wt := range writeTests { + testReadFile(t, src.File[i], &wt) + } + + // make a new zip file copying the old compressed data. + buf2 := new(bytes.Buffer) + dst := NewWriter(buf2) + for _, f := range src.File { + if err := dst.Copy(f); err != nil { + t.Fatal(err) + } + } + if err := dst.Close(); err != nil { + t.Fatal(err) + } + + // read the new one back + r, err := NewReader(bytes.NewReader(buf2.Bytes()), int64(buf2.Len())) + if err != nil { + t.Fatal(err) + } + for i, wt := range writeTests { + testReadFile(t, r.File[i], &wt) + } +} + +func TestWriterCreateRaw(t *testing.T) { + files := []struct { + name string + content []byte + method uint16 + flags uint16 + crc32 uint32 + uncompressedSize uint64 + compressedSize uint64 + }{ + { + name: "small store w desc", + content: []byte("gophers"), + method: Store, + flags: 0x8, + }, + { + name: "small deflate wo desc", + content: bytes.Repeat([]byte("abcdefg"), 2048), + method: Deflate, + }, + } + + // write a zip file + archive := new(bytes.Buffer) + w := NewWriter(archive) + + for i := range files { + f := &files[i] + f.crc32 = crc32.ChecksumIEEE(f.content) + size := uint64(len(f.content)) + f.uncompressedSize = size + f.compressedSize = size + + var compressedContent []byte + if f.method == Deflate { + var buf bytes.Buffer + w, err := flate.NewWriter(&buf, flate.BestSpeed) + if err != nil { + t.Fatalf("flate.NewWriter err = %v", err) + } + _, err = w.Write(f.content) + if err != nil { + t.Fatalf("flate Write err = %v", err) + } + err = w.Close() + if err != nil { + t.Fatalf("flate Writer.Close err = %v", err) + } + compressedContent = buf.Bytes() + f.compressedSize = uint64(len(compressedContent)) + } + + h := &FileHeader{ + Name: f.name, + Method: f.method, + Flags: f.flags, + CRC32: f.crc32, + CompressedSize64: f.compressedSize, + UncompressedSize64: f.uncompressedSize, + } + w, err := w.CreateRaw(h) + if err != nil { + t.Fatal(err) + } + if compressedContent != nil { + _, err = w.Write(compressedContent) + } else { + _, err = w.Write(f.content) + } + if err != nil { + t.Fatalf("%s Write got %v; want nil", f.name, err) + } + } + + if err := w.Close(); err != nil { + t.Fatal(err) + } + + // read it back + r, err := NewReader(bytes.NewReader(archive.Bytes()), int64(archive.Len())) + if err != nil { + t.Fatal(err) + } + for i, want := range files { + got := r.File[i] + if got.Name != want.name { + t.Errorf("got Name %s; want %s", got.Name, want.name) + } + if got.Method != want.method { + t.Errorf("%s: got Method %#x; want %#x", want.name, got.Method, want.method) + } + if got.Flags != want.flags { + t.Errorf("%s: got Flags %#x; want %#x", want.name, got.Flags, want.flags) + } + if got.CRC32 != want.crc32 { + t.Errorf("%s: got CRC32 %#x; want %#x", want.name, got.CRC32, want.crc32) + } + if got.CompressedSize64 != want.compressedSize { + t.Errorf("%s: got CompressedSize64 %d; want %d", want.name, got.CompressedSize64, want.compressedSize) + } + if got.UncompressedSize64 != want.uncompressedSize { + t.Errorf("%s: got UncompressedSize64 %d; want %d", want.name, got.UncompressedSize64, want.uncompressedSize) + } + + r, err := got.Open() + if err != nil { + t.Errorf("%s: Open err = %v", got.Name, err) + continue + } + + buf, err := io.ReadAll(r) + if err != nil { + t.Errorf("%s: ReadAll err = %v", got.Name, err) + continue + } + + if !bytes.Equal(buf, want.content) { + t.Errorf("%v: ReadAll returned unexpected bytes", got.Name) + } + } +} + func testCreate(t *testing.T, w *Writer, wt *WriteTest) { header := &FileHeader{ Name: wt.Name, @@ -378,15 +557,15 @@ func testReadFile(t *testing.T, f *File, wt *WriteTest) { testFileMode(t, f, wt.Mode) rc, err := f.Open() if err != nil { - t.Fatal("opening:", err) + t.Fatalf("opening %s: %v", f.Name, err) } b, err := io.ReadAll(rc) if err != nil { - t.Fatal("reading:", err) + t.Fatalf("reading %s: %v", f.Name, err) } err = rc.Close() if err != nil { - t.Fatal("closing:", err) + t.Fatalf("closing %s: %v", f.Name, err) } if !bytes.Equal(b, wt.Data) { t.Errorf("File contents %q, want %q", b, wt.Data) diff --git a/libgo/go/bufio/bufio.go b/libgo/go/bufio/bufio.go index 6baf9b9..ec928e7 100644 --- a/libgo/go/bufio/bufio.go +++ b/libgo/go/bufio/bufio.go @@ -670,7 +670,8 @@ func (b *Writer) WriteByte(c byte) error { // WriteRune writes a single Unicode code point, returning // the number of bytes written and any error. func (b *Writer) WriteRune(r rune) (size int, err error) { - if r < utf8.RuneSelf { + // Compare as uint32 to correctly handle negative runes. + if uint32(r) < utf8.RuneSelf { err = b.WriteByte(byte(r)) if err != nil { return 0, err diff --git a/libgo/go/bufio/bufio_test.go b/libgo/go/bufio/bufio_test.go index d7b34bd..ebcc711 100644 --- a/libgo/go/bufio/bufio_test.go +++ b/libgo/go/bufio/bufio_test.go @@ -534,6 +534,20 @@ func TestReadWriteRune(t *testing.T) { } } +func TestWriteInvalidRune(t *testing.T) { + // Invalid runes, including negative ones, should be written as the + // replacement character. + for _, r := range []rune{-1, utf8.MaxRune + 1} { + var buf bytes.Buffer + w := NewWriter(&buf) + w.WriteRune(r) + w.Flush() + if s := buf.String(); s != "\uFFFD" { + t.Errorf("WriteRune(%d) wrote %q, not replacement character", r, s) + } + } +} + func TestReadStringAllocs(t *testing.T) { r := strings.NewReader(" foo foo 42 42 42 42 42 42 42 42 4.2 4.2 4.2 4.2\n") buf := NewReader(r) diff --git a/libgo/go/bufio/scan.go b/libgo/go/bufio/scan.go index af46a14..4846d4f 100644 --- a/libgo/go/bufio/scan.go +++ b/libgo/go/bufio/scan.go @@ -48,7 +48,8 @@ type Scanner struct { // and the next token to return to the user, if any, plus an error, if any. // // Scanning stops if the function returns an error, in which case some of -// the input may be discarded. +// the input may be discarded. If that error is ErrFinalToken, scanning +// stops with no error. // // Otherwise, the Scanner advances the input. If the token is not nil, // the Scanner returns it to the user. If the token is nil, the diff --git a/libgo/go/bytes/boundary_test.go b/libgo/go/bytes/boundary_test.go index ea84f1e..5a47526 100644 --- a/libgo/go/bytes/boundary_test.go +++ b/libgo/go/bytes/boundary_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +//go:build linux // +build linux package bytes_test diff --git a/libgo/go/bytes/buffer.go b/libgo/go/bytes/buffer.go index f19a4cf..549b077 100644 --- a/libgo/go/bytes/buffer.go +++ b/libgo/go/bytes/buffer.go @@ -275,7 +275,8 @@ func (b *Buffer) WriteByte(c byte) error { // included to match bufio.Writer's WriteRune. The buffer is grown as needed; // if it becomes too large, WriteRune will panic with ErrTooLarge. func (b *Buffer) WriteRune(r rune) (n int, err error) { - if r < utf8.RuneSelf { + // Compare as uint32 to correctly handle negative runes. + if uint32(r) < utf8.RuneSelf { b.WriteByte(byte(r)) return 1, nil } diff --git a/libgo/go/bytes/buffer_test.go b/libgo/go/bytes/buffer_test.go index fec5ef8..9c9b744 100644 --- a/libgo/go/bytes/buffer_test.go +++ b/libgo/go/bytes/buffer_test.go @@ -6,6 +6,7 @@ package bytes_test import ( . "bytes" + "fmt" "io" "math/rand" "testing" @@ -387,6 +388,16 @@ func TestRuneIO(t *testing.T) { } } +func TestWriteInvalidRune(t *testing.T) { + // Invalid runes, including negative ones, should be written as + // utf8.RuneError. + for _, r := range []rune{-1, utf8.MaxRune + 1} { + var buf Buffer + buf.WriteRune(r) + check(t, fmt.Sprintf("TestWriteInvalidRune (%d)", r), &buf, "\uFFFD") + } +} + func TestNext(t *testing.T) { b := []byte{0, 1, 2, 3, 4} tmp := make([]byte, 5) diff --git a/libgo/go/cmd/cgo/doc.go b/libgo/go/cmd/cgo/doc.go index e782c86..a6787f6 100644 --- a/libgo/go/cmd/cgo/doc.go +++ b/libgo/go/cmd/cgo/doc.go @@ -387,6 +387,9 @@ and of course there is nothing stopping the C code from doing anything it likes. However, programs that break these rules are likely to fail in unexpected and unpredictable ways. +The runtime/cgo.Handle type can be used to safely pass Go values +between Go and C. See the runtime/cgo package documentation for details. + Note: the current implementation has a bug. While Go code is permitted to write nil or a C pointer (but not a Go pointer) to C memory, the current implementation may sometimes cause a runtime error if the diff --git a/libgo/go/cmd/cgo/gcc.go b/libgo/go/cmd/cgo/gcc.go index fa24567..de64a75 100644 --- a/libgo/go/cmd/cgo/gcc.go +++ b/libgo/go/cmd/cgo/gcc.go @@ -927,7 +927,7 @@ func (p *Package) rewriteCall(f *File, call *Call) (string, bool) { var sbCheck bytes.Buffer for i, param := range params { origArg := args[i] - arg, nu := p.mangle(f, &args[i]) + arg, nu := p.mangle(f, &args[i], true) if nu { needsUnsafe = true } @@ -970,7 +970,7 @@ func (p *Package) rewriteCall(f *File, call *Call) (string, bool) { sb.WriteString("return ") } - m, nu := p.mangle(f, &call.Call.Fun) + m, nu := p.mangle(f, &call.Call.Fun, false) if nu { needsUnsafe = true } @@ -1104,7 +1104,8 @@ func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool { // rewriting calls when it finds them. // It removes the corresponding references in f.Ref and f.Calls, so that we // don't try to do the replacement again in rewriteRef or rewriteCall. -func (p *Package) mangle(f *File, arg *ast.Expr) (ast.Expr, bool) { +// If addPosition is true, add position info to the idents of C names in arg. +func (p *Package) mangle(f *File, arg *ast.Expr, addPosition bool) (ast.Expr, bool) { needsUnsafe := false f.walk(arg, ctxExpr, func(f *File, arg interface{}, context astContext) { px, ok := arg.(*ast.Expr) @@ -1119,7 +1120,7 @@ func (p *Package) mangle(f *File, arg *ast.Expr) (ast.Expr, bool) { for _, r := range f.Ref { if r.Expr == px { - *px = p.rewriteName(f, r) + *px = p.rewriteName(f, r, addPosition) r.Done = true break } @@ -1379,7 +1380,7 @@ func (p *Package) rewriteRef(f *File) { } } - expr := p.rewriteName(f, r) + expr := p.rewriteName(f, r, false) if *godefs { // Substitute definition for mangled type name. @@ -1442,8 +1443,23 @@ func (p *Package) rewriteRef(f *File) { } // rewriteName returns the expression used to rewrite a reference. -func (p *Package) rewriteName(f *File, r *Ref) ast.Expr { - var expr ast.Expr = ast.NewIdent(r.Name.Mangle) // default +// If addPosition is true, add position info in the ident name. +func (p *Package) rewriteName(f *File, r *Ref, addPosition bool) ast.Expr { + getNewIdent := ast.NewIdent + if addPosition { + getNewIdent = func(newName string) *ast.Ident { + mangledIdent := ast.NewIdent(newName) + if len(newName) == len(r.Name.Go) { + return mangledIdent + } + p := fset.Position((*r.Expr).End()) + if p.Column == 0 { + return mangledIdent + } + return ast.NewIdent(fmt.Sprintf("%s /*line :%d:%d*/", newName, p.Line, p.Column)) + } + } + var expr ast.Expr = getNewIdent(r.Name.Mangle) // default switch r.Context { case ctxCall, ctxCall2: if r.Name.Kind != "func" { @@ -1471,7 +1487,7 @@ func (p *Package) rewriteName(f *File, r *Ref) ast.Expr { n.Mangle = "_C2func_" + n.Go f.Name["2"+r.Name.Go] = n } - expr = ast.NewIdent(n.Mangle) + expr = getNewIdent(n.Mangle) r.Name = n break } @@ -1502,7 +1518,7 @@ func (p *Package) rewriteName(f *File, r *Ref) ast.Expr { // issue 7757. expr = &ast.CallExpr{ Fun: &ast.Ident{NamePos: (*r.Expr).Pos(), Name: "_Cgo_ptr"}, - Args: []ast.Expr{ast.NewIdent(name.Mangle)}, + Args: []ast.Expr{getNewIdent(name.Mangle)}, } case "type": // Okay - might be new(T) @@ -1584,9 +1600,17 @@ func (p *Package) gccMachine() []string { case "s390x": return []string{"-m64"} case "mips64", "mips64le": - return []string{"-mabi=64"} + if gomips64 == "hardfloat" { + return []string{"-mabi=64", "-mhard-float"} + } else if gomips64 == "softfloat" { + return []string{"-mabi=64", "-msoft-float"} + } case "mips", "mipsle": - return []string{"-mabi=32"} + if gomips == "hardfloat" { + return []string{"-mabi=32", "-mfp32", "-mhard-float", "-mno-odd-spreg"} + } else if gomips == "softfloat" { + return []string{"-mabi=32", "-msoft-float"} + } case "ppc64": if goos == "aix" { return []string{"-maix64"} @@ -1639,6 +1663,8 @@ func (p *Package) gccCmd() []string { if goos == "aix" { c = append(c, "-mcmodel=large") } + // disable LTO so we get an object whose symbols we can read + c = append(c, "-fno-lto") c = append(c, "-") //read input from standard input return c } diff --git a/libgo/go/cmd/cgo/main.go b/libgo/go/cmd/cgo/main.go index c47e991..40dc6d2 100644 --- a/libgo/go/cmd/cgo/main.go +++ b/libgo/go/cmd/cgo/main.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Cgo; see gmp.go for an overview. +// Cgo; see doc.go for an overview. // TODO(rsc): // Emit correct line number annotations. @@ -17,9 +17,11 @@ import ( "go/ast" "go/printer" "go/token" + "internal/buildcfg" "io" "io/ioutil" "os" + "os/exec" "path/filepath" "reflect" "runtime" @@ -249,7 +251,7 @@ var importRuntimeCgo = flag.Bool("import_runtime_cgo", true, "import runtime/cgo var importSyscall = flag.Bool("import_syscall", true, "import syscall in generated code") var trimpath = flag.String("trimpath", "", "applies supplied rewrites or trims prefixes to recorded source file paths") -var goarch, goos string +var goarch, goos, gomips, gomips64 string func main() { objabi.AddVersionFlag() // -V @@ -306,6 +308,14 @@ func main() { p := newPackage(args[:i]) + // We need a C compiler to be available. Check this. + gccName := p.gccBaseCmd()[0] + _, err := exec.LookPath(gccName) + if err != nil { + fatalf("C compiler %q not found: %v", gccName, err) + os.Exit(2) + } + // Record CGO_LDFLAGS from the environment for external linking. if ldflags := os.Getenv("CGO_LDFLAGS"); ldflags != "" { args, err := splitQuoted(ldflags) @@ -409,6 +419,9 @@ func newPackage(args []string) *Package { if s := os.Getenv("GOOS"); s != "" { goos = s } + buildcfg.Check() + gomips = buildcfg.GOMIPS + gomips64 = buildcfg.GOMIPS64 ptrSize := ptrSizeMap[goarch] if ptrSize == 0 { fatalf("unknown ptrSize for $GOARCH %q", goarch) diff --git a/libgo/go/cmd/cgo/out.go b/libgo/go/cmd/cgo/out.go index b469b5f..3cf16f9 100644 --- a/libgo/go/cmd/cgo/out.go +++ b/libgo/go/cmd/cgo/out.go @@ -173,8 +173,18 @@ func (p *Package) writeDefs() { if *gccgo { fmt.Fprintf(fc, "extern byte *%s;\n", n.C) } else { - fmt.Fprintf(fm, "extern char %s[];\n", n.C) - fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C) + // Force a reference to all symbols so that + // the external linker will add DT_NEEDED + // entries as needed on ELF systems. + // Treat function variables differently + // to avoid type confict errors from LTO + // (Link Time Optimization). + if n.Kind == "fpvar" { + fmt.Fprintf(fm, "extern void %s();\n", n.C) + } else { + fmt.Fprintf(fm, "extern char %s[];\n", n.C) + fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C) + } fmt.Fprintf(fgo2, "//go:linkname __cgo_%s %s\n", n.C, n.C) fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", n.C) fmt.Fprintf(fgo2, "var __cgo_%s byte\n", n.C) @@ -1026,14 +1036,28 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) { } fmt.Fprintf(fgcc, "}\n") - // Build the wrapper function compiled by cmd/compile. - // This unpacks the argument struct above and calls the Go function. + // In internal linking mode, the Go linker sees both + // the C wrapper written above and the Go wrapper it + // references. Hence, export the C wrapper (e.g., for + // if we're building a shared object). The Go linker + // will resolve the C wrapper's reference to the Go + // wrapper without a separate export. fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", exp.ExpName) + // cgo_export_static refers to a symbol by its linker + // name, so set the linker name of the Go wrapper. fmt.Fprintf(fgo2, "//go:linkname _cgoexp%s_%s _cgoexp%s_%s\n", cPrefix, exp.ExpName, cPrefix, exp.ExpName) + // In external linking mode, the Go linker sees the Go + // wrapper, but not the C wrapper. For this case, + // export the Go wrapper so the host linker can + // resolve the reference from the C wrapper to the Go + // wrapper. fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName) + + // Build the wrapper function compiled by cmd/compile. + // This unpacks the argument struct above and calls the Go function. fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a *%s) {\n", cPrefix, exp.ExpName, gotype) - fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName) + fmt.Fprintf(fm, "void _cgoexp%s_%s(void* p){}\n", cPrefix, exp.ExpName) if gccResult != "void" { // Write results back to frame. @@ -1722,8 +1746,12 @@ typedef struct __go_open_array { struct __go_string __go_byte_array_to_string(const void* p, intgo len); struct __go_open_array __go_string_to_byte_array (struct __go_string str); +extern void runtime_throw(const char *); + const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) { char *p = malloc(s.__length+1); + if(p == NULL) + runtime_throw("runtime: C malloc failed"); memmove(p, s.__data, s.__length); p[s.__length] = 0; return p; @@ -1731,6 +1759,8 @@ const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) { void *_cgoPREFIX_Cfunc_CBytes(struct __go_open_array b) { char *p = malloc(b.__count); + if(p == NULL) + runtime_throw("runtime: C malloc failed"); memmove(p, b.__values, b.__count); return p; } @@ -1749,14 +1779,13 @@ Slice _cgoPREFIX_Cfunc_GoBytes(char *p, int32_t n) { return __go_string_to_byte_array(s); } -extern void runtime_throw(const char *); void *_cgoPREFIX_Cfunc__CMalloc(size_t n) { - void *p = malloc(n); - if(p == NULL && n == 0) - p = malloc(1); - if(p == NULL) - runtime_throw("runtime: C malloc failed"); - return p; + void *p = malloc(n); + if(p == NULL && n == 0) + p = malloc(1); + if(p == NULL) + runtime_throw("runtime: C malloc failed"); + return p; } struct __go_type_descriptor; diff --git a/libgo/go/cmd/go.mod b/libgo/go/cmd/go.mod index 70b1b06..cd03968 100644 --- a/libgo/go/cmd/go.mod +++ b/libgo/go/cmd/go.mod @@ -1,12 +1,15 @@ module cmd -go 1.16 +go 1.17 require ( - github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2 - golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff - golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 - golang.org/x/mod v0.4.2-0.20210325185522-dbbbf8a3c6ea - golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect - golang.org/x/tools v0.0.0-20210107193943-4ed967dd8eff + github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a + github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect + golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e + golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e // indirect + golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a + golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect + golang.org/x/term v0.0.0-20210503060354-a79de5458b56 + golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9 + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/libgo/go/cmd/go/alldocs.go b/libgo/go/cmd/go/alldocs.go index 84f89c9..7f88d32 100644 --- a/libgo/go/cmd/go/alldocs.go +++ b/libgo/go/cmd/go/alldocs.go @@ -111,7 +111,7 @@ // -p n // the number of programs, such as build commands or // test binaries, that can be run in parallel. -// The default is the number of CPUs available. +// The default is GOMAXPROCS, normally the number of CPUs available. // -race // enable data race detection. // Supported only on linux/amd64, freebsd/amd64, darwin/amd64, windows/amd64, @@ -174,8 +174,8 @@ // a build will run as if the disk file path exists with the contents // given by the backing file paths, or as if the disk file path does not // exist if its backing file path is empty. Support for the -overlay flag -// has some limitations:importantly, cgo files included from outside the -// include path must be in the same directory as the Go package they are +// has some limitations: importantly, cgo files included from outside the +// include path must be in the same directory as the Go package they are // included from, and overlays will not appear when binaries and tests are // run through go run and go test respectively. // -pkgdir dir @@ -198,6 +198,8 @@ // a program to use to invoke toolchain programs like vet and asm. // For example, instead of running asm, the go command will run // 'cmd args /path/to/asm <arguments for asm>'. +// The TOOLEXEC_IMPORTPATH environment variable will be set, +// matching 'go list -f {{.ImportPath}}' for the package being built. // // The -asmflags, -gccgoflags, -gcflags, and -ldflags flags accept a // space-separated list of arguments to pass to an underlying tool @@ -291,7 +293,7 @@ // // Usage: // -// go doc [-u] [-c] [package|[package.]symbol[.methodOrField]] +// go doc [doc flags] [package|[package.]symbol[.methodOrField]] // // Doc prints the documentation comments associated with the item identified by its // arguments (a package, const, func, type, var, method, or struct field) @@ -596,7 +598,7 @@ // // Usage: // -// go get [-d] [-t] [-u] [-v] [-insecure] [build flags] [packages] +// go get [-d] [-t] [-u] [-v] [build flags] [packages] // // Get resolves its command-line arguments to packages at specific module versions, // updates go.mod to require those versions, downloads source code into the @@ -641,14 +643,6 @@ // When the -t and -u flags are used together, get will update // test dependencies as well. // -// The -insecure flag permits fetching from repositories and resolving -// custom domains using insecure schemes such as HTTP, and also bypassess -// module sum validation using the checksum database. Use with caution. -// This flag is deprecated and will be removed in a future version of go. -// To permit the use of insecure schemes, use the GOINSECURE environment -// variable instead. To bypass module sum validation, use GOPRIVATE or -// GONOSUMDB. See 'go help environment' for details. -// // The -d flag instructs get not to build or install packages. get will only // update go.mod and download source code needed to build packages. // @@ -849,6 +843,7 @@ // UseAllFiles bool // use files regardless of +build lines, file names // Compiler string // compiler to assume when computing target paths // BuildTags []string // build constraints to match in +build lines +// ToolTags []string // toolchain-specific build constraints // ReleaseTags []string // releases the current release is compatible with // InstallSuffix string // suffix to use in the name of the install dir // } @@ -1083,7 +1078,7 @@ // // Usage: // -// go mod edit [editing flags] [go.mod] +// go mod edit [editing flags] [-fmt|-print|-json] [go.mod] // // Edit provides a command-line interface for editing go.mod, // for use primarily by tools or scripts. It reads only go.mod; @@ -1142,12 +1137,12 @@ // writing it back to go.mod. The JSON output corresponds to these Go types: // // type Module struct { -// Path string +// Path string // Version string // } // // type GoMod struct { -// Module Module +// Module ModPath // Go string // Require []Require // Exclude []Module @@ -1155,6 +1150,11 @@ // Retract []Retract // } // +// type ModPath struct { +// Path string +// Deprecated string +// } +// // type Require struct { // Path string // Version string @@ -1186,13 +1186,17 @@ // // Usage: // -// go mod graph +// go mod graph [-go=version] // // Graph prints the module requirement graph (with replacements applied) // in text form. Each line in the output has two space-separated fields: a module // and one of its requirements. Each module is identified as a string of the form // path@version, except for the main module, which has no @version suffix. // +// The -go flag causes graph to report the module graph as loaded by the +// given Go version, instead of the version indicated by the 'go' directive +// in the go.mod file. +// // See https://golang.org/ref/mod#go-mod-graph for more about 'go mod graph'. // // @@ -1200,7 +1204,7 @@ // // Usage: // -// go mod init [module] +// go mod init [module-path] // // Init initializes and writes a new go.mod file in the current directory, in // effect creating a new module rooted at the current directory. The go.mod file @@ -1221,7 +1225,7 @@ // // Usage: // -// go mod tidy [-e] [-v] +// go mod tidy [-e] [-v] [-go=version] [-compat=version] // // Tidy makes sure go.mod matches the source code in the module. // It adds any missing modules necessary to build the current module's @@ -1235,6 +1239,20 @@ // The -e flag causes tidy to attempt to proceed despite errors // encountered while loading packages. // +// The -go flag causes tidy to update the 'go' directive in the go.mod +// file to the given version, which may change which module dependencies +// are retained as explicit requirements in the go.mod file. +// (Go versions 1.17 and higher retain more requirements in order to +// support lazy module loading.) +// +// The -compat flag preserves any additional checksums needed for the +// 'go' command from the indicated major Go release to successfully load +// the module graph, and causes tidy to error out if that version of the +// 'go' command would load any imported package from a different module +// version. By default, tidy acts as if the -compat flag were set to the +// version prior to the one indicated by the 'go' directive in the go.mod +// file. +// // See https://golang.org/ref/mod#go-mod-tidy for more about 'go mod tidy'. // // @@ -1318,10 +1336,21 @@ // go run [build flags] [-exec xprog] package [arguments...] // // Run compiles and runs the named main Go package. -// Typically the package is specified as a list of .go source files from a single directory, -// but it may also be an import path, file system path, or pattern +// Typically the package is specified as a list of .go source files from a single +// directory, but it may also be an import path, file system path, or pattern // matching a single known package, as in 'go run .' or 'go run my/cmd'. // +// If the package argument has a version suffix (like @latest or @v1.0.0), +// "go run" builds the program in module-aware mode, ignoring the go.mod file in +// the current directory or any parent directory, if there is one. This is useful +// for running programs without affecting the dependencies of the main module. +// +// If the package argument doesn't have a version suffix, "go run" may run in +// module-aware mode or GOPATH mode, depending on the GO111MODULE environment +// variable and the presence of a go.mod file. See 'go help modules' for details. +// If module-aware mode is enabled, "go run" runs in the context of the main +// module. +// // By default, 'go run' runs the compiled binary directly: 'a.out arguments...'. // If the -exec flag is given, 'go run' invokes the binary using xprog: // 'xprog a.out arguments...'. @@ -1416,8 +1445,8 @@ // // The rule for a match in the cache is that the run involves the same // test binary and the flags on the command line come entirely from a -// restricted set of 'cacheable' test flags, defined as -cpu, -list, -// -parallel, -run, -short, and -v. If a run of go test has any test +// restricted set of 'cacheable' test flags, defined as -benchtime, -cpu, +// -list, -parallel, -run, -short, and -v. If a run of go test has any test // or non-test flags outside this set, the result is not cached. To // disable test caching, use any test flag or argument other than the // cacheable flags. The idiomatic way to disable test caching explicitly @@ -1543,7 +1572,7 @@ // // A build constraint, also known as a build tag, is a line comment that begins // -// // +build +// //go:build // // that lists the conditions under which a file should be included in the package. // Constraints may appear in any kind of source file (not just Go), but @@ -1551,30 +1580,20 @@ // only by blank lines and other line comments. These rules mean that in Go // files a build constraint must appear before the package clause. // -// To distinguish build constraints from package documentation, a series of -// build constraints must be followed by a blank line. -// -// A build constraint is evaluated as the OR of space-separated options. -// Each option evaluates as the AND of its comma-separated terms. -// Each term consists of letters, digits, underscores, and dots. -// A term may be negated with a preceding !. -// For example, the build constraint: -// -// // +build linux,386 darwin,!cgo -// -// corresponds to the boolean formula: +// To distinguish build constraints from package documentation, +// a build constraint should be followed by a blank line. // -// (linux AND 386) OR (darwin AND (NOT cgo)) +// A build constraint is evaluated as an expression containing options +// combined by ||, &&, and ! operators and parentheses. Operators have +// the same meaning as in Go. // -// A file may have multiple build constraints. The overall constraint is the AND -// of the individual constraints. That is, the build constraints: +// For example, the following build constraint constrains a file to +// build when the "linux" and "386" constraints are satisfied, or when +// "darwin" is satisfied and "cgo" is not: // -// // +build linux darwin -// // +build amd64 +// //go:build (linux && 386) || (darwin && !cgo) // -// corresponds to the boolean formula: -// -// (linux OR darwin) AND amd64 +// It is an error for a file to have more than one //go:build line. // // During a particular build, the following words are satisfied: // @@ -1612,24 +1631,28 @@ // // To keep a file from being considered for the build: // -// // +build ignore +// //go:build ignore // // (any other unsatisfied word will work as well, but "ignore" is conventional.) // // To build a file only when using cgo, and only on Linux and OS X: // -// // +build linux,cgo darwin,cgo +// //go:build cgo && (linux || darwin) // // Such a file is usually paired with another file implementing the // default functionality for other systems, which in this case would // carry the constraint: // -// // +build !linux,!darwin !cgo +// //go:build !(cgo && (linux || darwin)) // // Naming a file dns_windows.go will cause it to be included only when // building the package for Windows; similarly, math_386.s will be included // only when building the package for 32-bit x86. // +// Go versions 1.16 and earlier used a different syntax for build constraints, +// with a "// +build" prefix. The gofmt command will add an equivalent //go:build +// constraint when encountering the older syntax. +// // // Build modes // @@ -1787,9 +1810,8 @@ // Comma-separated list of glob patterns (in the syntax of Go's path.Match) // of module path prefixes that should always be fetched in an insecure // manner. Only applies to dependencies that are being fetched directly. -// Unlike the -insecure flag on 'go get', GOINSECURE does not disable -// checksum database validation. GOPRIVATE or GONOSUMDB may be used -// to achieve that. +// GOINSECURE does not disable checksum database validation. GOPRIVATE or +// GONOSUMDB may be used to achieve that. // GOOS // The operating system for which to compile code. // Examples are linux, darwin, windows, netbsd. @@ -1869,6 +1891,9 @@ // GOMIPS64 // For GOARCH=mips64{,le}, whether to use floating point instructions. // Valid values are hardfloat (default), softfloat. +// GOPPC64 +// For GOARCH=ppc64{,le}, the target ISA (Instruction Set Architecture). +// Valid values are power8 (default), power9. // GOWASM // For GOARCH=wasm, comma-separated list of experimental WebAssembly features to use. // Valid values are satconv, signext. @@ -1878,6 +1903,12 @@ // GCCGOTOOLDIR // If set, where to find gccgo tools, such as cgo. // The default is based on how gccgo was configured. +// GOEXPERIMENT +// Comma-separated list of toolchain experiments to enable or disable. +// The list of available experiments may change arbitrarily over time. +// See src/internal/goexperiment/flags.go for currently valid values. +// Warning: This variable is provided for the development and testing +// of the Go toolchain itself. Use beyond that purpose is unsupported. // GOROOT_FINAL // The root of the installed Go tree, when it is // installed in a location other than where it is built. @@ -1961,7 +1992,7 @@ // The go.mod file format is described in detail at // https://golang.org/ref/mod#go-mod-file. // -// To create a new go.mod file, use 'go help init'. For details see +// To create a new go.mod file, use 'go mod init'. For details see // 'go help mod init' or https://golang.org/ref/mod#go-mod-init. // // To add missing module requirements or remove unneeded requirements, @@ -2139,7 +2170,7 @@ // This help text, accessible as 'go help gopath-get' even in module-aware mode, // describes 'go get' as it operates in legacy GOPATH mode. // -// Usage: go get [-d] [-f] [-t] [-u] [-v] [-fix] [-insecure] [build flags] [packages] +// Usage: go get [-d] [-f] [-t] [-u] [-v] [-fix] [build flags] [packages] // // Get downloads the packages named by the import paths, along with their // dependencies. It then installs the named packages, like 'go install'. @@ -2155,13 +2186,6 @@ // The -fix flag instructs get to run the fix tool on the downloaded packages // before resolving dependencies or building the code. // -// The -insecure flag permits fetching from repositories and resolving -// custom domains using insecure schemes such as HTTP. Use with caution. -// This flag is deprecated and will be removed in a future version of go. -// The GOINSECURE environment variable should be used instead, since it -// provides control over which packages may be retrieved using an insecure -// scheme. See 'go help environment' for details. -// // The -t flag instructs get to also download the packages required to build // the tests for the specified packages. // @@ -2346,7 +2370,7 @@ // will result in the following requests: // // https://example.org/pkg/foo?go-get=1 (preferred) -// http://example.org/pkg/foo?go-get=1 (fallback, only with -insecure) +// http://example.org/pkg/foo?go-get=1 (fallback, only with use of correctly set GOINSECURE) // // If that page contains the meta tag // @@ -2664,6 +2688,13 @@ // the Go tree can run a sanity check but not spend time running // exhaustive tests. // +// -shuffle off,on,N +// Randomize the execution order of tests and benchmarks. +// It is off by default. If -shuffle is set to on, then it will seed +// the randomizer using the system clock. If -shuffle is set to an +// integer N, then N will be used as the seed value. In both cases, +// the seed will be reported for reproducibility. +// // -timeout d // If a test binary runs longer than duration d, panic. // If d is 0, the timeout is disabled. diff --git a/libgo/go/cmd/go/go11.go b/libgo/go/cmd/go/go11.go index 7e383f4..a1f2727 100644 --- a/libgo/go/cmd/go/go11.go +++ b/libgo/go/cmd/go/go11.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build go1.1 // +build go1.1 package main diff --git a/libgo/go/cmd/go/go_test.go b/libgo/go/cmd/go/go_test.go index 3ce3238..6ce2765 100644 --- a/libgo/go/cmd/go/go_test.go +++ b/libgo/go/cmd/go/go_test.go @@ -72,7 +72,6 @@ func tooSlow(t *testing.T) { // (temp) directory. var testGOROOT string -var testCC string var testGOCACHE string var testGo string @@ -179,13 +178,6 @@ func TestMain(m *testing.M) { os.Exit(2) } - out, err = exec.Command(gotool, "env", "CC").CombinedOutput() - if err != nil { - fmt.Fprintf(os.Stderr, "could not find testing CC: %v\n%s", err, out) - os.Exit(2) - } - testCC = strings.TrimSpace(string(out)) - cmd := exec.Command(testGo, "env", "CGO_ENABLED") cmd.Stderr = new(strings.Builder) if out, err := cmd.Output(); err != nil { @@ -811,8 +803,10 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) { // so that we can change files. for _, copydir := range []string{ "src/runtime", + "src/internal/abi", "src/internal/bytealg", "src/internal/cpu", + "src/internal/goexperiment", "src/math/bits", "src/unsafe", filepath.Join("pkg", runtime.GOOS+"_"+runtime.GOARCH), @@ -2183,7 +2177,7 @@ func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) { // See https://sourceware.org/bugzilla/show_bug.cgi?id=19011 section := f.Section(".edata") if section == nil { - t.Fatalf(".edata section is not present") + t.Skip(".edata section is not present") } // TODO: deduplicate this struct from cmd/link/internal/ld/pe.go type IMAGE_EXPORT_DIRECTORY struct { @@ -2830,3 +2824,59 @@ func TestCoverpkgTestOnly(t *testing.T) { tg.grepStderrNot("no packages being tested depend on matches", "bad match message") tg.grepStdout("coverage: 100", "no coverage") } + +// Regression test for golang.org/issue/34499: version command should not crash +// when executed in a deleted directory on Linux. +func TestExecInDeletedDir(t *testing.T) { + switch runtime.GOOS { + case "windows", "plan9", + "aix", // Fails with "device busy". + "solaris", "illumos": // Fails with "invalid argument". + t.Skipf("%v does not support removing the current working directory", runtime.GOOS) + } + tg := testgo(t) + defer tg.cleanup() + + wd, err := os.Getwd() + tg.check(err) + tg.makeTempdir() + tg.check(os.Chdir(tg.tempdir)) + defer func() { tg.check(os.Chdir(wd)) }() + + tg.check(os.Remove(tg.tempdir)) + + // `go version` should not fail + tg.run("version") +} + +// A missing C compiler should not force the net package to be stale. +// Issue 47215. +func TestMissingCC(t *testing.T) { + if !canCgo { + t.Skip("test is only meaningful on systems with cgo") + } + cc := os.Getenv("CC") + if cc == "" { + cc = "gcc" + } + if filepath.IsAbs(cc) { + t.Skipf(`"CC" (%s) is an absolute path`, cc) + } + _, err := exec.LookPath(cc) + if err != nil { + t.Skipf(`"CC" (%s) not on PATH`, cc) + } + + tg := testgo(t) + defer tg.cleanup() + netStale, _ := tg.isStale("net") + if netStale { + t.Skip(`skipping test because "net" package is currently stale`) + } + + tg.setenv("PATH", "") // No C compiler on PATH. + netStale, _ = tg.isStale("net") + if netStale { + t.Error(`clearing "PATH" causes "net" to be stale`) + } +} diff --git a/libgo/go/cmd/go/go_unix_test.go b/libgo/go/cmd/go/go_unix_test.go index 030ef79..db992b7 100644 --- a/libgo/go/cmd/go/go_unix_test.go +++ b/libgo/go/cmd/go/go_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build darwin dragonfly freebsd hurd linux netbsd openbsd solaris package main_test diff --git a/libgo/go/cmd/go/internal/base/path.go b/libgo/go/cmd/go/internal/base/path.go index 7a51181..4d8715e 100644 --- a/libgo/go/cmd/go/internal/base/path.go +++ b/libgo/go/cmd/go/internal/base/path.go @@ -8,21 +8,27 @@ import ( "os" "path/filepath" "strings" + "sync" ) -func getwd() string { - wd, err := os.Getwd() - if err != nil { - Fatalf("cannot determine current directory: %v", err) - } - return wd -} +var cwd string +var cwdOnce sync.Once -var Cwd = getwd() +// Cwd returns the current working directory at the time of the first call. +func Cwd() string { + cwdOnce.Do(func() { + var err error + cwd, err = os.Getwd() + if err != nil { + Fatalf("cannot determine current directory: %v", err) + } + }) + return cwd +} // ShortPath returns an absolute or relative name for path, whatever is shorter. func ShortPath(path string) string { - if rel, err := filepath.Rel(Cwd, path); err == nil && len(rel) < len(path) { + if rel, err := filepath.Rel(Cwd(), path); err == nil && len(rel) < len(path) { return rel } return path @@ -32,10 +38,8 @@ func ShortPath(path string) string { // made relative to the current directory if they would be shorter. func RelPaths(paths []string) []string { var out []string - // TODO(rsc): Can this use Cwd from above? - pwd, _ := os.Getwd() for _, p := range paths { - rel, err := filepath.Rel(pwd, p) + rel, err := filepath.Rel(Cwd(), p) if err == nil && len(rel) < len(p) { p = rel } diff --git a/libgo/go/cmd/go/internal/base/signal_notunix.go b/libgo/go/cmd/go/internal/base/signal_notunix.go index 9e869b0..5cc0b0f 100644 --- a/libgo/go/cmd/go/internal/base/signal_notunix.go +++ b/libgo/go/cmd/go/internal/base/signal_notunix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build plan9 || windows // +build plan9 windows package base diff --git a/libgo/go/cmd/go/internal/base/signal_unix.go b/libgo/go/cmd/go/internal/base/signal_unix.go index 2b1507b..cdb2593 100644 --- a/libgo/go/cmd/go/internal/base/signal_unix.go +++ b/libgo/go/cmd/go/internal/base/signal_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || js || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js linux netbsd openbsd solaris package base diff --git a/libgo/go/cmd/go/internal/bug/bug.go b/libgo/go/cmd/go/internal/bug/bug.go index 4aa08b4..307527c 100644 --- a/libgo/go/cmd/go/internal/bug/bug.go +++ b/libgo/go/cmd/go/internal/bug/bug.go @@ -20,6 +20,7 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" + "cmd/go/internal/envcmd" "cmd/go/internal/web" ) @@ -81,7 +82,7 @@ func printGoVersion(w io.Writer) { fmt.Fprintf(w, "### What version of Go are you using (`go version`)?\n\n") fmt.Fprintf(w, "<pre>\n") fmt.Fprintf(w, "$ go version\n") - printCmdOut(w, "", "go", "version") + fmt.Fprintf(w, "go version %s %s/%s\n", runtime.Version(), runtime.GOOS, runtime.GOARCH) fmt.Fprintf(w, "</pre>\n") fmt.Fprintf(w, "\n") } @@ -90,13 +91,20 @@ func printEnvDetails(w io.Writer) { fmt.Fprintf(w, "### What operating system and processor architecture are you using (`go env`)?\n\n") fmt.Fprintf(w, "<details><summary><code>go env</code> Output</summary><br><pre>\n") fmt.Fprintf(w, "$ go env\n") - printCmdOut(w, "", "go", "env") + printGoEnv(w) printGoDetails(w) printOSDetails(w) printCDetails(w) fmt.Fprintf(w, "</pre></details>\n\n") } +func printGoEnv(w io.Writer) { + env := envcmd.MkEnv() + env = append(env, envcmd.ExtraEnvVars()...) + env = append(env, envcmd.ExtraEnvVarsCostly()...) + envcmd.PrintEnv(w, env) +} + func printGoDetails(w io.Writer) { printCmdOut(w, "GOROOT/bin/go version: ", filepath.Join(runtime.GOROOT(), "bin/go"), "version") printCmdOut(w, "GOROOT/bin/go tool compile -V: ", filepath.Join(runtime.GOROOT(), "bin/go"), "tool", "compile", "-V") diff --git a/libgo/go/cmd/go/internal/cache/cache.go b/libgo/go/cmd/go/internal/cache/cache.go index 41f9216..d592d70 100644 --- a/libgo/go/cmd/go/internal/cache/cache.go +++ b/libgo/go/cmd/go/internal/cache/cache.go @@ -19,7 +19,7 @@ import ( "strings" "time" - "cmd/go/internal/renameio" + "cmd/go/internal/lockedfile" ) // An ActionID is a cache action key, the hash of a complete description of a @@ -294,10 +294,17 @@ func (c *Cache) Trim() { // We maintain in dir/trim.txt the time of the last completed cache trim. // If the cache has been trimmed recently enough, do nothing. // This is the common case. - data, _ := renameio.ReadFile(filepath.Join(c.dir, "trim.txt")) - t, err := strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64) - if err == nil && now.Sub(time.Unix(t, 0)) < trimInterval { - return + // If the trim file is corrupt, detected if the file can't be parsed, or the + // trim time is too far in the future, attempt the trim anyway. It's possible that + // the cache was full when the corruption happened. Attempting a trim on + // an empty cache is cheap, so there wouldn't be a big performance hit in that case. + if data, err := lockedfile.Read(filepath.Join(c.dir, "trim.txt")); err == nil { + if t, err := strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64); err == nil { + lastTrim := time.Unix(t, 0) + if d := now.Sub(lastTrim); d < trimInterval && d > -mtimeInterval { + return + } + } } // Trim each of the 256 subdirectories. @@ -311,7 +318,11 @@ func (c *Cache) Trim() { // Ignore errors from here: if we don't write the complete timestamp, the // cache will appear older than it is, and we'll trim it again next time. - renameio.WriteFile(filepath.Join(c.dir, "trim.txt"), []byte(fmt.Sprintf("%d", now.Unix())), 0666) + var b bytes.Buffer + fmt.Fprintf(&b, "%d", now.Unix()) + if err := lockedfile.Write(filepath.Join(c.dir, "trim.txt"), &b, 0666); err != nil { + return + } } // trimSubdir trims a single cache subdirectory. diff --git a/libgo/go/cmd/go/internal/cache/hash.go b/libgo/go/cmd/go/internal/cache/hash.go index e4bb2a3..4f79c31 100644 --- a/libgo/go/cmd/go/internal/cache/hash.go +++ b/libgo/go/cmd/go/internal/cache/hash.go @@ -12,6 +12,7 @@ import ( "io" "os" "runtime" + "strings" "sync" ) @@ -36,7 +37,22 @@ type Hash struct { // of other versions. This salt will result in additional ActionID files // in the cache, but not additional copies of the large output files, // which are still addressed by unsalted SHA256. -var hashSalt = []byte(runtime.Version()) +// +// We strip any GOEXPERIMENTs the go tool was built with from this +// version string on the assumption that they shouldn't affect go tool +// execution. This allows bootstrapping to converge faster: dist builds +// go_bootstrap without any experiments, so by stripping experiments +// go_bootstrap and the final go binary will use the same salt. +var hashSalt = []byte(stripExperiment(runtime.Version())) + +// stripExperiment strips any GOEXPERIMENT configuration from the Go +// version string. +func stripExperiment(version string) string { + if i := strings.Index(version, " X:"); i >= 0 { + return version[:i] + } + return version +} // Subkey returns an action ID corresponding to mixing a parent // action ID with a string description of the subkey. diff --git a/libgo/go/cmd/go/internal/cfg/cfg.go b/libgo/go/cmd/go/internal/cfg/cfg.go index c48904e..57a3c1f 100644 --- a/libgo/go/cmd/go/internal/cfg/cfg.go +++ b/libgo/go/cmd/go/internal/cfg/cfg.go @@ -10,6 +10,7 @@ import ( "bytes" "fmt" "go/build" + "internal/buildcfg" "internal/cfg" "io" "os" @@ -19,8 +20,6 @@ import ( "sync" "cmd/go/internal/fsys" - - "cmd/internal/objabi" ) // These are general "build flags" used by build and other commands. @@ -28,18 +27,18 @@ var ( BuildA bool // -a flag BuildBuildmode string // -buildmode flag BuildContext = defaultContext() - BuildMod string // -mod flag - BuildModExplicit bool // whether -mod was set explicitly - BuildModReason string // reason -mod was set, if set by default - BuildI bool // -i flag - BuildLinkshared bool // -linkshared flag - BuildMSan bool // -msan flag - BuildN bool // -n flag - BuildO string // -o flag - BuildP = runtime.NumCPU() // -p flag - BuildPkgdir string // -pkgdir flag - BuildRace bool // -race flag - BuildToolexec []string // -toolexec flag + BuildMod string // -mod flag + BuildModExplicit bool // whether -mod was set explicitly + BuildModReason string // reason -mod was set, if set by default + BuildI bool // -i flag + BuildLinkshared bool // -linkshared flag + BuildMSan bool // -msan flag + BuildN bool // -n flag + BuildO string // -o flag + BuildP = runtime.GOMAXPROCS(0) // -p flag + BuildPkgdir string // -pkgdir flag + BuildRace bool // -race flag + BuildToolexec []string // -toolexec flag BuildToolchainName string BuildToolchainCompiler func() string BuildToolchainLinker func() string @@ -51,8 +50,6 @@ var ( ModCacheRW bool // -modcacherw flag ModFile string // -modfile flag - Insecure bool // -insecure flag - CmdName string // "build", "install", "list", "mod tidy", etc. DebugActiongraph string // -debug-actiongraph flag (undocumented, unstable) @@ -80,6 +77,14 @@ func defaultContext() build.Context { ctxt.GOOS = envOr("GOOS", ctxt.GOOS) ctxt.GOARCH = envOr("GOARCH", ctxt.GOARCH) + // The experiments flags are based on GOARCH, so they may + // need to change. TODO: This should be cleaned up. + buildcfg.UpdateExperiments(ctxt.GOOS, ctxt.GOARCH, envOr("GOEXPERIMENT", buildcfg.DefaultGOEXPERIMENT)) + ctxt.ToolTags = nil + for _, exp := range buildcfg.EnabledExperiments() { + ctxt.ToolTags = append(ctxt.ToolTags, "goexperiment."+exp) + } + // The go/build rule for whether cgo is enabled is: // 1. If $CGO_ENABLED is set, respect it. // 2. Otherwise, if this is a cross-compile, disable cgo. @@ -254,12 +259,12 @@ var ( GOMODCACHE = envOr("GOMODCACHE", gopathDir("pkg/mod")) // Used in envcmd.MkEnv and build ID computations. - GOARM = envOr("GOARM", fmt.Sprint(objabi.GOARM)) - GO386 = envOr("GO386", objabi.GO386) - GOMIPS = envOr("GOMIPS", objabi.GOMIPS) - GOMIPS64 = envOr("GOMIPS64", objabi.GOMIPS64) - GOPPC64 = envOr("GOPPC64", fmt.Sprintf("%s%d", "power", objabi.GOPPC64)) - GOWASM = envOr("GOWASM", fmt.Sprint(objabi.GOWASM)) + GOARM = envOr("GOARM", fmt.Sprint(buildcfg.GOARM)) + GO386 = envOr("GO386", buildcfg.GO386) + GOMIPS = envOr("GOMIPS", buildcfg.GOMIPS) + GOMIPS64 = envOr("GOMIPS64", buildcfg.GOMIPS64) + GOPPC64 = envOr("GOPPC64", fmt.Sprintf("%s%d", "power", buildcfg.GOPPC64)) + GOWASM = envOr("GOWASM", fmt.Sprint(buildcfg.GOWASM)) GOPROXY = envOr("GOPROXY", "https://proxy.golang.org,direct") GOSUMDB = envOr("GOSUMDB", "sum.golang.org") diff --git a/libgo/go/cmd/go/internal/clean/clean.go b/libgo/go/cmd/go/internal/clean/clean.go index b1d40fe..fd4cb20 100644 --- a/libgo/go/cmd/go/internal/clean/clean.go +++ b/libgo/go/cmd/go/internal/clean/clean.go @@ -117,7 +117,7 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) { } if cleanPkg { - for _, pkg := range load.PackagesAndErrors(ctx, args) { + for _, pkg := range load.PackagesAndErrors(ctx, load.PackageOpts{}, args) { clean(pkg) } } diff --git a/libgo/go/cmd/go/internal/doc/doc.go b/libgo/go/cmd/go/internal/doc/doc.go index 67f76e2..8580a5d 100644 --- a/libgo/go/cmd/go/internal/doc/doc.go +++ b/libgo/go/cmd/go/internal/doc/doc.go @@ -13,7 +13,7 @@ import ( var CmdDoc = &base.Command{ Run: runDoc, - UsageLine: "go doc [-u] [-c] [package|[package.]symbol[.methodOrField]]", + UsageLine: "go doc [doc flags] [package|[package.]symbol[.methodOrField]]", CustomFlags: true, Short: "show documentation for package or symbol", Long: ` diff --git a/libgo/go/cmd/go/internal/envcmd/env.go b/libgo/go/cmd/go/internal/envcmd/env.go index 6937187..1553d26 100644 --- a/libgo/go/cmd/go/internal/envcmd/env.go +++ b/libgo/go/cmd/go/internal/envcmd/env.go @@ -10,6 +10,8 @@ import ( "encoding/json" "fmt" "go/build" + "internal/buildcfg" + "io" "os" "path/filepath" "runtime" @@ -71,6 +73,7 @@ func MkEnv() []cfg.EnvVar { {Name: "GOCACHE", Value: cache.DefaultDir()}, {Name: "GOENV", Value: envFile}, {Name: "GOEXE", Value: cfg.ExeSuffix}, + {Name: "GOEXPERIMENT", Value: buildcfg.GOEXPERIMENT()}, {Name: "GOFLAGS", Value: cfg.Getenv("GOFLAGS")}, {Name: "GOHOSTARCH", Value: runtime.GOARCH}, {Name: "GOHOSTOS", Value: runtime.GOOS}, @@ -196,23 +199,31 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) { if *envU && *envW { base.Fatalf("go env: cannot use -u with -w") } + + // Handle 'go env -w' and 'go env -u' before calling buildcfg.Check, + // so they can be used to recover from an invalid configuration. + if *envW { + runEnvW(args) + return + } + + if *envU { + runEnvU(args) + return + } + + buildcfg.Check() + env := cfg.CmdEnv env = append(env, ExtraEnvVars()...) - if err := fsys.Init(base.Cwd); err != nil { + if err := fsys.Init(base.Cwd()); err != nil { base.Fatalf("go: %v", err) } // Do we need to call ExtraEnvVarsCostly, which is a bit expensive? needCostly := false - if *envU || *envW { - // We're overwriting or removing default settings, - // so it doesn't really matter what the existing settings are. - // - // Moreover, we haven't validated the new settings yet, so it is - // important that we NOT perform any actions based on them, - // such as initializing the builder to compute other variables. - } else if len(args) == 0 { + if len(args) == 0 { // We're listing all environment variables ("go env"), // including the expensive ones. needCostly = true @@ -237,95 +248,6 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) { env = append(env, ExtraEnvVarsCostly()...) } - if *envW { - // Process and sanity-check command line. - if len(args) == 0 { - base.Fatalf("go env -w: no KEY=VALUE arguments given") - } - osEnv := make(map[string]string) - for _, e := range cfg.OrigEnv { - if i := strings.Index(e, "="); i >= 0 { - osEnv[e[:i]] = e[i+1:] - } - } - add := make(map[string]string) - for _, arg := range args { - i := strings.Index(arg, "=") - if i < 0 { - base.Fatalf("go env -w: arguments must be KEY=VALUE: invalid argument: %s", arg) - } - key, val := arg[:i], arg[i+1:] - if err := checkEnvWrite(key, val); err != nil { - base.Fatalf("go env -w: %v", err) - } - if _, ok := add[key]; ok { - base.Fatalf("go env -w: multiple values for key: %s", key) - } - add[key] = val - if osVal := osEnv[key]; osVal != "" && osVal != val { - fmt.Fprintf(os.Stderr, "warning: go env -w %s=... does not override conflicting OS environment variable\n", key) - } - } - - goos, okGOOS := add["GOOS"] - goarch, okGOARCH := add["GOARCH"] - if okGOOS || okGOARCH { - if !okGOOS { - goos = cfg.Goos - } - if !okGOARCH { - goarch = cfg.Goarch - } - if err := work.CheckGOOSARCHPair(goos, goarch); err != nil { - base.Fatalf("go env -w: %v", err) - } - } - - gotmp, okGOTMP := add["GOTMPDIR"] - if okGOTMP { - if !filepath.IsAbs(gotmp) && gotmp != "" { - base.Fatalf("go env -w: GOTMPDIR must be an absolute path") - } - } - - updateEnvFile(add, nil) - return - } - - if *envU { - // Process and sanity-check command line. - if len(args) == 0 { - base.Fatalf("go env -u: no arguments given") - } - del := make(map[string]bool) - for _, arg := range args { - if err := checkEnvWrite(arg, ""); err != nil { - base.Fatalf("go env -u: %v", err) - } - del[arg] = true - } - if del["GOOS"] || del["GOARCH"] { - goos, goarch := cfg.Goos, cfg.Goarch - if del["GOOS"] { - goos = getOrigEnv("GOOS") - if goos == "" { - goos = build.Default.GOOS - } - } - if del["GOARCH"] { - goarch = getOrigEnv("GOARCH") - if goarch == "" { - goarch = build.Default.GOARCH - } - } - if err := work.CheckGOOSARCHPair(goos, goarch); err != nil { - base.Fatalf("go env -u: %v", err) - } - } - updateEnvFile(nil, del) - return - } - if len(args) > 0 { if *envJson { var es []cfg.EnvVar @@ -347,27 +269,135 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) { return } + PrintEnv(os.Stdout, env) +} + +func runEnvW(args []string) { + // Process and sanity-check command line. + if len(args) == 0 { + base.Fatalf("go env -w: no KEY=VALUE arguments given") + } + osEnv := make(map[string]string) + for _, e := range cfg.OrigEnv { + if i := strings.Index(e, "="); i >= 0 { + osEnv[e[:i]] = e[i+1:] + } + } + add := make(map[string]string) + for _, arg := range args { + i := strings.Index(arg, "=") + if i < 0 { + base.Fatalf("go env -w: arguments must be KEY=VALUE: invalid argument: %s", arg) + } + key, val := arg[:i], arg[i+1:] + if err := checkEnvWrite(key, val); err != nil { + base.Fatalf("go env -w: %v", err) + } + if _, ok := add[key]; ok { + base.Fatalf("go env -w: multiple values for key: %s", key) + } + add[key] = val + if osVal := osEnv[key]; osVal != "" && osVal != val { + fmt.Fprintf(os.Stderr, "warning: go env -w %s=... does not override conflicting OS environment variable\n", key) + } + } + + if err := checkBuildConfig(add, nil); err != nil { + base.Fatalf("go env -w: %v", err) + } + + gotmp, okGOTMP := add["GOTMPDIR"] + if okGOTMP { + if !filepath.IsAbs(gotmp) && gotmp != "" { + base.Fatalf("go env -w: GOTMPDIR must be an absolute path") + } + } + + updateEnvFile(add, nil) +} + +func runEnvU(args []string) { + // Process and sanity-check command line. + if len(args) == 0 { + base.Fatalf("go env -u: no arguments given") + } + del := make(map[string]bool) + for _, arg := range args { + if err := checkEnvWrite(arg, ""); err != nil { + base.Fatalf("go env -u: %v", err) + } + del[arg] = true + } + + if err := checkBuildConfig(nil, del); err != nil { + base.Fatalf("go env -u: %v", err) + } + + updateEnvFile(nil, del) +} + +// checkBuildConfig checks whether the build configuration is valid +// after the specified configuration environment changes are applied. +func checkBuildConfig(add map[string]string, del map[string]bool) error { + // get returns the value for key after applying add and del and + // reports whether it changed. cur should be the current value + // (i.e., before applying changes) and def should be the default + // value (i.e., when no environment variables are provided at all). + get := func(key, cur, def string) (string, bool) { + if val, ok := add[key]; ok { + return val, true + } + if del[key] { + val := getOrigEnv(key) + if val == "" { + val = def + } + return val, true + } + return cur, false + } + + goos, okGOOS := get("GOOS", cfg.Goos, build.Default.GOOS) + goarch, okGOARCH := get("GOARCH", cfg.Goarch, build.Default.GOARCH) + if okGOOS || okGOARCH { + if err := work.CheckGOOSARCHPair(goos, goarch); err != nil { + return err + } + } + + goexperiment, okGOEXPERIMENT := get("GOEXPERIMENT", buildcfg.GOEXPERIMENT(), "") + if okGOEXPERIMENT { + if _, _, err := buildcfg.ParseGOEXPERIMENT(goos, goarch, goexperiment); err != nil { + return err + } + } + + return nil +} + +// PrintEnv prints the environment variables to w. +func PrintEnv(w io.Writer, env []cfg.EnvVar) { for _, e := range env { if e.Name != "TERM" { switch runtime.GOOS { default: - fmt.Printf("%s=\"%s\"\n", e.Name, e.Value) + fmt.Fprintf(w, "%s=\"%s\"\n", e.Name, e.Value) case "plan9": if strings.IndexByte(e.Value, '\x00') < 0 { - fmt.Printf("%s='%s'\n", e.Name, strings.ReplaceAll(e.Value, "'", "''")) + fmt.Fprintf(w, "%s='%s'\n", e.Name, strings.ReplaceAll(e.Value, "'", "''")) } else { v := strings.Split(e.Value, "\x00") - fmt.Printf("%s=(", e.Name) + fmt.Fprintf(w, "%s=(", e.Name) for x, s := range v { if x > 0 { - fmt.Printf(" ") + fmt.Fprintf(w, " ") } - fmt.Printf("%s", s) + fmt.Fprintf(w, "%s", s) } - fmt.Printf(")\n") + fmt.Fprintf(w, ")\n") } case "windows": - fmt.Printf("set %s=%s\n", e.Name, e.Value) + fmt.Fprintf(w, "set %s=%s\n", e.Name, e.Value) } } } @@ -428,7 +458,7 @@ func checkEnvWrite(key, val string) error { return fmt.Errorf("GOPATH entry is relative; must be absolute path: %q", val) } // Make sure CC and CXX are absolute paths - case "CC", "CXX": + case "CC", "CXX", "GOMODCACHE": if !filepath.IsAbs(val) && val != "" && val != filepath.Base(val) { return fmt.Errorf("%s entry is relative; must be absolute path: %q", key, val) } diff --git a/libgo/go/cmd/go/internal/fix/fix.go b/libgo/go/cmd/go/internal/fix/fix.go index c7588c6..988d45e 100644 --- a/libgo/go/cmd/go/internal/fix/fix.go +++ b/libgo/go/cmd/go/internal/fix/fix.go @@ -33,7 +33,7 @@ See also: go fmt, go vet. } func runFix(ctx context.Context, cmd *base.Command, args []string) { - pkgs := load.PackagesAndErrors(ctx, args) + pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, args) w := 0 for _, pkg := range pkgs { if pkg.Error != nil { diff --git a/libgo/go/cmd/go/internal/fmtcmd/fmt.go b/libgo/go/cmd/go/internal/fmtcmd/fmt.go index 6b98f0c..8a04008 100644 --- a/libgo/go/cmd/go/internal/fmtcmd/fmt.go +++ b/libgo/go/cmd/go/internal/fmtcmd/fmt.go @@ -65,7 +65,7 @@ func runFmt(ctx context.Context, cmd *base.Command, args []string) { } }() } - for _, pkg := range load.PackagesAndErrors(ctx, args) { + for _, pkg := range load.PackagesAndErrors(ctx, load.PackageOpts{}, args) { if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main { if !printed { fmt.Fprintf(os.Stderr, "go: not formatting packages in dependency modules\n") diff --git a/libgo/go/cmd/go/internal/fsys/fsys.go b/libgo/go/cmd/go/internal/fsys/fsys.go index 7b06c3c..0b80602 100644 --- a/libgo/go/cmd/go/internal/fsys/fsys.go +++ b/libgo/go/cmd/go/internal/fsys/fsys.go @@ -44,7 +44,7 @@ func (n *node) isDeleted() bool { // TODO(matloob): encapsulate these in an io/fs-like interface var overlay map[string]*node // path -> file or directory node -var cwd string // copy of base.Cwd to avoid dependency +var cwd string // copy of base.Cwd() to avoid dependency // Canonicalize a path for looking it up in the overlay. // Important: filepath.Join(cwd, path) doesn't always produce @@ -100,7 +100,7 @@ func Init(wd string) error { } func initFromJSON(overlayJSON OverlayJSON) error { - // Canonicalize the paths in in the overlay map. + // Canonicalize the paths in the overlay map. // Use reverseCanonicalized to check for collisions: // no two 'from' paths should canonicalize to the same path. overlay = make(map[string]*node) diff --git a/libgo/go/cmd/go/internal/generate/generate.go b/libgo/go/cmd/go/internal/generate/generate.go index a48311d..80ea32b 100644 --- a/libgo/go/cmd/go/internal/generate/generate.go +++ b/libgo/go/cmd/go/internal/generate/generate.go @@ -161,8 +161,6 @@ func init() { } func runGenerate(ctx context.Context, cmd *base.Command, args []string) { - load.IgnoreImports = true - if generateRunFlag != "" { var err error generateRunRE, err = regexp.Compile(generateRunFlag) @@ -175,7 +173,8 @@ func runGenerate(ctx context.Context, cmd *base.Command, args []string) { // Even if the arguments are .go files, this loop suffices. printed := false - for _, pkg := range load.PackagesAndErrors(ctx, args) { + pkgOpts := load.PackageOpts{IgnoreImports: true} + for _, pkg := range load.PackagesAndErrors(ctx, pkgOpts, args) { if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main { if !printed { fmt.Fprintf(os.Stderr, "go: not generating in packages in dependency modules\n") @@ -334,6 +333,7 @@ func (g *Generator) setEnv() { "GOPACKAGE=" + g.pkg, "DOLLAR=" + "$", } + g.env = base.AppendPWD(g.env, g.dir) } // split breaks the line into words, evaluating quoted diff --git a/libgo/go/cmd/go/internal/get/get.go b/libgo/go/cmd/go/internal/get/get.go index 329a2f5..3c16dc3 100644 --- a/libgo/go/cmd/go/internal/get/get.go +++ b/libgo/go/cmd/go/internal/get/get.go @@ -26,7 +26,7 @@ import ( ) var CmdGet = &base.Command{ - UsageLine: "go get [-d] [-f] [-t] [-u] [-v] [-fix] [-insecure] [build flags] [packages]", + UsageLine: "go get [-d] [-f] [-t] [-u] [-v] [-fix] [build flags] [packages]", Short: "download and install packages and dependencies", Long: ` Get downloads the packages named by the import paths, along with their @@ -43,13 +43,6 @@ of the original. The -fix flag instructs get to run the fix tool on the downloaded packages before resolving dependencies or building the code. -The -insecure flag permits fetching from repositories and resolving -custom domains using insecure schemes such as HTTP. Use with caution. -This flag is deprecated and will be removed in a future version of go. -The GOINSECURE environment variable should be used instead, since it -provides control over which packages may be retrieved using an insecure -scheme. See 'go help environment' for details. - The -t flag instructs get to also download the packages required to build the tests for the specified packages. @@ -105,17 +98,17 @@ Usage: ` + CmdGet.UsageLine + ` } var ( - getD = CmdGet.Flag.Bool("d", false, "") - getF = CmdGet.Flag.Bool("f", false, "") - getT = CmdGet.Flag.Bool("t", false, "") - getU = CmdGet.Flag.Bool("u", false, "") - getFix = CmdGet.Flag.Bool("fix", false, "") + getD = CmdGet.Flag.Bool("d", false, "") + getF = CmdGet.Flag.Bool("f", false, "") + getT = CmdGet.Flag.Bool("t", false, "") + getU = CmdGet.Flag.Bool("u", false, "") + getFix = CmdGet.Flag.Bool("fix", false, "") + getInsecure = CmdGet.Flag.Bool("insecure", false, "") ) func init() { work.AddBuildFlags(CmdGet, work.OmitModFlag|work.OmitModCommonFlags) CmdGet.Run = runGet // break init loop - CmdGet.Flag.BoolVar(&cfg.Insecure, "insecure", cfg.Insecure, "") } func runGet(ctx context.Context, cmd *base.Command, args []string) { @@ -129,11 +122,11 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { if *getF && !*getU { base.Fatalf("go get: cannot use -f flag without -u") } - if cfg.Insecure { - fmt.Fprintf(os.Stderr, "go get: -insecure flag is deprecated; see 'go help get' for details\n") + if *getInsecure { + base.Fatalf("go get: -insecure flag is no longer supported; use GOINSECURE instead") } - // Disable any prompting for passwords by Git. + // Disable any prompting for passwords by Git itself. // Only has an effect for 2.3.0 or later, but avoiding // the prompt in earlier versions is just too hard. // If user has explicitly set GIT_TERMINAL_PROMPT=1, keep @@ -143,7 +136,10 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { os.Setenv("GIT_TERMINAL_PROMPT", "0") } - // Disable any ssh connection pooling by Git. + // Also disable prompting for passwords by the 'ssh' subprocess spawned by + // Git, because apparently GIT_TERMINAL_PROMPT isn't sufficient to do that. + // Adding '-o BatchMode=yes' should do the trick. + // // If a Git subprocess forks a child into the background to cache a new connection, // that child keeps stdout/stderr open. After the Git subprocess exits, // os /exec expects to be able to read from the stdout/stderr pipe @@ -157,7 +153,14 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { // assume they know what they are doing and don't step on it. // But default to turning off ControlMaster. if os.Getenv("GIT_SSH") == "" && os.Getenv("GIT_SSH_COMMAND") == "" { - os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no") + os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no -o BatchMode=yes") + } + + // And one more source of Git prompts: the Git Credential Manager Core for Windows. + // + // See https://github.com/microsoft/Git-Credential-Manager-Core/blob/master/docs/environment.md#gcm_interactive. + if os.Getenv("GCM_INTERACTIVE") == "" { + os.Setenv("GCM_INTERACTIVE", "never") } // Phase 1. Download/update. @@ -180,7 +183,7 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { // everything. load.ClearPackageCache() - pkgs := load.PackagesAndErrors(ctx, args) + pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, args) load.CheckPackageErrors(pkgs) // Phase 3. Install. @@ -255,9 +258,9 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) load1 := func(path string, mode int) *load.Package { if parent == nil { mode := 0 // don't do module or vendor resolution - return load.LoadImport(context.TODO(), path, base.Cwd, nil, stk, nil, mode) + return load.LoadImport(context.TODO(), load.PackageOpts{}, path, base.Cwd(), nil, stk, nil, mode) } - return load.LoadImport(context.TODO(), path, parent.Dir, parent, stk, nil, mode|load.ResolveModule) + return load.LoadImport(context.TODO(), load.PackageOpts{}, path, parent.Dir, parent, stk, nil, mode|load.ResolveModule) } p := load1(arg, mode) @@ -435,7 +438,7 @@ func downloadPackage(p *load.Package) error { return fmt.Errorf("%s: invalid import path: %v", p.ImportPath, err) } security := web.SecureOnly - if cfg.Insecure || module.MatchPrefixPatterns(cfg.GOINSECURE, importPrefix) { + if module.MatchPrefixPatterns(cfg.GOINSECURE, importPrefix) { security = web.Insecure } diff --git a/libgo/go/cmd/go/internal/help/helpdoc.go b/libgo/go/cmd/go/internal/help/helpdoc.go index 57cee4f..490ff1f 100644 --- a/libgo/go/cmd/go/internal/help/helpdoc.go +++ b/libgo/go/cmd/go/internal/help/helpdoc.go @@ -251,7 +251,7 @@ For example, will result in the following requests: https://example.org/pkg/foo?go-get=1 (preferred) - http://example.org/pkg/foo?go-get=1 (fallback, only with -insecure) + http://example.org/pkg/foo?go-get=1 (fallback, only with use of correctly set GOINSECURE) If that page contains the meta tag @@ -517,9 +517,8 @@ General-purpose environment variables: Comma-separated list of glob patterns (in the syntax of Go's path.Match) of module path prefixes that should always be fetched in an insecure manner. Only applies to dependencies that are being fetched directly. - Unlike the -insecure flag on 'go get', GOINSECURE does not disable - checksum database validation. GOPRIVATE or GONOSUMDB may be used - to achieve that. + GOINSECURE does not disable checksum database validation. GOPRIVATE or + GONOSUMDB may be used to achieve that. GOOS The operating system for which to compile code. Examples are linux, darwin, windows, netbsd. @@ -599,6 +598,9 @@ Architecture-specific environment variables: GOMIPS64 For GOARCH=mips64{,le}, whether to use floating point instructions. Valid values are hardfloat (default), softfloat. + GOPPC64 + For GOARCH=ppc64{,le}, the target ISA (Instruction Set Architecture). + Valid values are power8 (default), power9. GOWASM For GOARCH=wasm, comma-separated list of experimental WebAssembly features to use. Valid values are satconv, signext. @@ -608,6 +610,12 @@ Special-purpose environment variables: GCCGOTOOLDIR If set, where to find gccgo tools, such as cgo. The default is based on how gccgo was configured. + GOEXPERIMENT + Comma-separated list of toolchain experiments to enable or disable. + The list of available experiments may change arbitrarily over time. + See src/internal/goexperiment/flags.go for currently valid values. + Warning: This variable is provided for the development and testing + of the Go toolchain itself. Use beyond that purpose is unsupported. GOROOT_FINAL The root of the installed Go tree, when it is installed in a location other than where it is built. @@ -785,7 +793,7 @@ var HelpBuildConstraint = &base.Command{ Long: ` A build constraint, also known as a build tag, is a line comment that begins - // +build + //go:build that lists the conditions under which a file should be included in the package. Constraints may appear in any kind of source file (not just Go), but @@ -793,30 +801,20 @@ they must appear near the top of the file, preceded only by blank lines and other line comments. These rules mean that in Go files a build constraint must appear before the package clause. -To distinguish build constraints from package documentation, a series of -build constraints must be followed by a blank line. +To distinguish build constraints from package documentation, +a build constraint should be followed by a blank line. -A build constraint is evaluated as the OR of space-separated options. -Each option evaluates as the AND of its comma-separated terms. -Each term consists of letters, digits, underscores, and dots. -A term may be negated with a preceding !. -For example, the build constraint: +A build constraint is evaluated as an expression containing options +combined by ||, &&, and ! operators and parentheses. Operators have +the same meaning as in Go. - // +build linux,386 darwin,!cgo +For example, the following build constraint constrains a file to +build when the "linux" and "386" constraints are satisfied, or when +"darwin" is satisfied and "cgo" is not: -corresponds to the boolean formula: + //go:build (linux && 386) || (darwin && !cgo) - (linux AND 386) OR (darwin AND (NOT cgo)) - -A file may have multiple build constraints. The overall constraint is the AND -of the individual constraints. That is, the build constraints: - - // +build linux darwin - // +build amd64 - -corresponds to the boolean formula: - - (linux OR darwin) AND amd64 +It is an error for a file to have more than one //go:build line. During a particular build, the following words are satisfied: @@ -854,22 +852,26 @@ in addition to ios tags and files. To keep a file from being considered for the build: - // +build ignore + //go:build ignore (any other unsatisfied word will work as well, but "ignore" is conventional.) To build a file only when using cgo, and only on Linux and OS X: - // +build linux,cgo darwin,cgo + //go:build cgo && (linux || darwin) Such a file is usually paired with another file implementing the default functionality for other systems, which in this case would carry the constraint: - // +build !linux,!darwin !cgo + //go:build !(cgo && (linux || darwin)) Naming a file dns_windows.go will cause it to be included only when building the package for Windows; similarly, math_386.s will be included only when building the package for 32-bit x86. + +Go versions 1.16 and earlier used a different syntax for build constraints, +with a "// +build" prefix. The gofmt command will add an equivalent //go:build +constraint when encountering the older syntax. `, } diff --git a/libgo/go/cmd/go/internal/imports/read.go b/libgo/go/cmd/go/internal/imports/read.go index 5e27078..70d5190 100644 --- a/libgo/go/cmd/go/internal/imports/read.go +++ b/libgo/go/cmd/go/internal/imports/read.go @@ -8,6 +8,7 @@ package imports import ( "bufio" + "bytes" "errors" "io" "unicode/utf8" @@ -22,6 +23,19 @@ type importReader struct { nerr int } +var bom = []byte{0xef, 0xbb, 0xbf} + +func newImportReader(b *bufio.Reader) *importReader { + // Remove leading UTF-8 BOM. + // Per https://golang.org/ref/spec#Source_code_representation: + // a compiler may ignore a UTF-8-encoded byte order mark (U+FEFF) + // if it is the first Unicode code point in the source text. + if leadingBytes, err := b.Peek(3); err == nil && bytes.Equal(leadingBytes, bom) { + b.Discard(3) + } + return &importReader{b: b} +} + func isIdent(c byte) bool { return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c >= utf8.RuneSelf } @@ -201,7 +215,7 @@ func (r *importReader) readImport(imports *[]string) { // ReadComments is like io.ReadAll, except that it only reads the leading // block of comments in the file. func ReadComments(f io.Reader) ([]byte, error) { - r := &importReader{b: bufio.NewReader(f)} + r := newImportReader(bufio.NewReader(f)) r.peekByte(true) if r.err == nil && !r.eof { // Didn't reach EOF, so must have found a non-space byte. Remove it. @@ -213,7 +227,7 @@ func ReadComments(f io.Reader) ([]byte, error) { // ReadImports is like io.ReadAll, except that it expects a Go file as input // and stops reading the input once the imports have completed. func ReadImports(f io.Reader, reportSyntaxError bool, imports *[]string) ([]byte, error) { - r := &importReader{b: bufio.NewReader(f)} + r := newImportReader(bufio.NewReader(f)) r.readKeyword("package") r.readIdent() diff --git a/libgo/go/cmd/go/internal/imports/read_test.go b/libgo/go/cmd/go/internal/imports/read_test.go index 6ea356f..6a1a652 100644 --- a/libgo/go/cmd/go/internal/imports/read_test.go +++ b/libgo/go/cmd/go/internal/imports/read_test.go @@ -66,6 +66,10 @@ var readImportsTests = []readTest{ `, "", }, + { + "\ufeff𝔻" + `package p; import "x";ℙvar x = 1`, + "", + }, } var readCommentsTests = []readTest{ @@ -82,6 +86,10 @@ var readCommentsTests = []readTest{ "", }, { + "\ufeff𝔻" + `ℙpackage p; import . "x"`, + "", + }, + { `// foo /* bar */ @@ -94,6 +102,19 @@ var readCommentsTests = []readTest{ ℙHello, world`, "", }, + { + "\ufeff𝔻" + `// foo + + /* bar */ + + /* quux */ // baz + + /*/ zot */ + + // asdf + ℙHello, world`, + "", + }, } func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, error)) { @@ -107,6 +128,11 @@ func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, erro in = tt.in[:j] + tt.in[j+len("ℙ"):] testOut = tt.in[:j] } + d := strings.Index(tt.in, "𝔻") + if d >= 0 { + in = in[:d] + in[d+len("𝔻"):] + testOut = testOut[d+len("𝔻"):] + } r := strings.NewReader(in) buf, err := read(r) if err != nil { diff --git a/libgo/go/cmd/go/internal/imports/testdata/android/tags.txt b/libgo/go/cmd/go/internal/imports/testdata/android/tags.txt new file mode 100644 index 0000000..aaf5a6b --- /dev/null +++ b/libgo/go/cmd/go/internal/imports/testdata/android/tags.txt @@ -0,0 +1 @@ +android arm64
\ No newline at end of file diff --git a/libgo/go/cmd/go/internal/imports/testdata/android/want.txt b/libgo/go/cmd/go/internal/imports/testdata/android/want.txt new file mode 100644 index 0000000..0fdf397 --- /dev/null +++ b/libgo/go/cmd/go/internal/imports/testdata/android/want.txt @@ -0,0 +1,6 @@ +a +b +c +d +e +f diff --git a/libgo/go/cmd/go/internal/imports/testdata/illumos/tags.txt b/libgo/go/cmd/go/internal/imports/testdata/illumos/tags.txt new file mode 100644 index 0000000..b6386a3 --- /dev/null +++ b/libgo/go/cmd/go/internal/imports/testdata/illumos/tags.txt @@ -0,0 +1 @@ +illumos amd64 diff --git a/libgo/go/cmd/go/internal/imports/testdata/illumos/want.txt b/libgo/go/cmd/go/internal/imports/testdata/illumos/want.txt new file mode 100644 index 0000000..0fdf397 --- /dev/null +++ b/libgo/go/cmd/go/internal/imports/testdata/illumos/want.txt @@ -0,0 +1,6 @@ +a +b +c +d +e +f diff --git a/libgo/go/cmd/go/internal/imports/testdata/star/tags.txt b/libgo/go/cmd/go/internal/imports/testdata/star/tags.txt new file mode 100644 index 0000000..f59ec20 --- /dev/null +++ b/libgo/go/cmd/go/internal/imports/testdata/star/tags.txt @@ -0,0 +1 @@ +*
\ No newline at end of file diff --git a/libgo/go/cmd/go/internal/imports/testdata/star/want.txt b/libgo/go/cmd/go/internal/imports/testdata/star/want.txt new file mode 100644 index 0000000..139f5f4 --- /dev/null +++ b/libgo/go/cmd/go/internal/imports/testdata/star/want.txt @@ -0,0 +1,4 @@ +import1 +import2 +import3 +import4 diff --git a/libgo/go/cmd/go/internal/list/context.go b/libgo/go/cmd/go/internal/list/context.go index 68d691e..2dc6376 100644 --- a/libgo/go/cmd/go/internal/list/context.go +++ b/libgo/go/cmd/go/internal/list/context.go @@ -17,6 +17,7 @@ type Context struct { UseAllFiles bool `json:",omitempty"` // use files regardless of +build lines, file names Compiler string `json:",omitempty"` // compiler to assume when computing target paths BuildTags []string `json:",omitempty"` // build constraints to match in +build lines + ToolTags []string `json:",omitempty"` // toolchain-specific build constraints ReleaseTags []string `json:",omitempty"` // releases the current release is compatible with InstallSuffix string `json:",omitempty"` // suffix to use in the name of the install dir } @@ -31,6 +32,7 @@ func newContext(c *build.Context) *Context { UseAllFiles: c.UseAllFiles, Compiler: c.Compiler, BuildTags: c.BuildTags, + ToolTags: c.ToolTags, ReleaseTags: c.ReleaseTags, InstallSuffix: c.InstallSuffix, } diff --git a/libgo/go/cmd/go/internal/list/list.go b/libgo/go/cmd/go/internal/list/list.go index b4d82d9..7cb9ec6 100644 --- a/libgo/go/cmd/go/internal/list/list.go +++ b/libgo/go/cmd/go/internal/list/list.go @@ -148,6 +148,7 @@ The template function "context" returns the build context, defined as: UseAllFiles bool // use files regardless of +build lines, file names Compiler string // compiler to assume when computing target paths BuildTags []string // build constraints to match in +build lines + ToolTags []string // toolchain-specific build constraints ReleaseTags []string // releases the current release is compatible with InstallSuffix string // suffix to use in the name of the install dir } @@ -335,7 +336,10 @@ var ( var nl = []byte{'\n'} func runList(ctx context.Context, cmd *base.Command, args []string) { - load.ModResolveTests = *listTest + if *listFmt != "" && *listJson == true { + base.Fatalf("go list -f cannot be used with -json") + } + work.BuildInit() out := newTrackingWriter(os.Stdout) defer out.w.Flush() @@ -344,7 +348,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { if *listM { *listFmt = "{{.String}}" if *listVersions { - *listFmt = `{{.Path}}{{range .Versions}} {{.}}{{end}}` + *listFmt = `{{.Path}}{{range .Versions}} {{.}}{{end}}{{if .Deprecated}} (deprecated){{end}}` } } else { *listFmt = "{{.ImportPath}}" @@ -423,7 +427,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { base.Fatalf("go list -m: not using modules") } - modload.LoadModFile(ctx) // Parses go.mod and sets cfg.BuildMod. + modload.LoadModFile(ctx) // Sets cfg.BuildMod as a side-effect. if cfg.BuildMod == "vendor" { const actionDisabledFormat = "go list -m: can't %s using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)" @@ -447,13 +451,29 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { } } - mods := modload.ListModules(ctx, args, *listU, *listVersions, *listRetracted) + var mode modload.ListMode + if *listU { + mode |= modload.ListU | modload.ListRetracted | modload.ListDeprecated + } + if *listRetracted { + mode |= modload.ListRetracted + } + if *listVersions { + mode |= modload.ListVersions + if *listRetracted { + mode |= modload.ListRetractedVersions + } + } + mods, err := modload.ListModules(ctx, args, mode) if !*listE { for _, m := range mods { if m.Error != nil { base.Errorf("go list -m: %v", m.Error.Err) } } + if err != nil { + base.Errorf("go list -m: %v", err) + } base.ExitIfErrors() } for _, m := range mods { @@ -478,8 +498,11 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { base.Fatalf("go list -test cannot be used with -find") } - load.IgnoreImports = *listFind - pkgs := load.PackagesAndErrors(ctx, args) + pkgOpts := load.PackageOpts{ + IgnoreImports: *listFind, + ModResolveTests: *listTest, + } + pkgs := load.PackagesAndErrors(ctx, pkgOpts, args) if !*listE { w := 0 for _, pkg := range pkgs { @@ -516,9 +539,9 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { var pmain, ptest, pxtest *load.Package var err error if *listE { - pmain, ptest, pxtest = load.TestPackagesAndErrors(ctx, p, nil) + pmain, ptest, pxtest = load.TestPackagesAndErrors(ctx, pkgOpts, p, nil) } else { - pmain, ptest, pxtest, err = load.TestPackagesFor(ctx, p, nil) + pmain, ptest, pxtest, err = load.TestPackagesFor(ctx, pkgOpts, p, nil) if err != nil { base.Errorf("can't load test package: %s", err) } @@ -605,7 +628,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { old := make(map[string]string) for _, p := range all { if p.ForTest != "" { - new := p.ImportPath + " [" + p.ForTest + ".test]" + new := p.Desc() old[new] = p.ImportPath p.ImportPath = new } @@ -679,9 +702,14 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { } if len(args) > 0 { - listU := false - listVersions := false - rmods := modload.ListModules(ctx, args, listU, listVersions, *listRetracted) + var mode modload.ListMode + if *listRetracted { + mode |= modload.ListRetracted + } + rmods, err := modload.ListModules(ctx, args, mode) + if err != nil && !*listE { + base.Errorf("go list -retracted: %v", err) + } for i, arg := range args { rmod := rmods[i] for _, mod := range argToMods[arg] { @@ -696,8 +724,18 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { // Record non-identity import mappings in p.ImportMap. for _, p := range pkgs { - for i, srcPath := range p.Internal.RawImports { - path := p.Imports[i] + nRaw := len(p.Internal.RawImports) + for i, path := range p.Imports { + var srcPath string + if i < nRaw { + srcPath = p.Internal.RawImports[i] + } else { + // This path is not within the raw imports, so it must be an import + // found only within CompiledGoFiles. Those paths are found in + // CompiledImports. + srcPath = p.Internal.CompiledImports[i-nRaw] + } + if path != srcPath { if p.ImportMap == nil { p.ImportMap = make(map[string]string) diff --git a/libgo/go/cmd/go/internal/load/flag.go b/libgo/go/cmd/go/internal/load/flag.go index 7534e65..440cb86 100644 --- a/libgo/go/cmd/go/internal/load/flag.go +++ b/libgo/go/cmd/go/internal/load/flag.go @@ -34,7 +34,7 @@ type ppfValue struct { // Set is called each time the flag is encountered on the command line. func (f *PerPackageFlag) Set(v string) error { - return f.set(v, base.Cwd) + return f.set(v, base.Cwd()) } // set is the implementation of Set, taking a cwd (current working directory) for easier testing. diff --git a/libgo/go/cmd/go/internal/load/pkg.go b/libgo/go/cmd/go/internal/load/pkg.go index e83f1d2..c085fcb 100644 --- a/libgo/go/cmd/go/internal/load/pkg.go +++ b/libgo/go/cmd/go/internal/load/pkg.go @@ -14,6 +14,7 @@ import ( "go/build" "go/scanner" "go/token" + "internal/goroot" "io/fs" "os" "path" @@ -29,6 +30,8 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/fsys" + "cmd/go/internal/imports" + "cmd/go/internal/modfetch" "cmd/go/internal/modinfo" "cmd/go/internal/modload" "cmd/go/internal/par" @@ -37,11 +40,10 @@ import ( "cmd/go/internal/trace" "cmd/internal/sys" + "golang.org/x/mod/modfile" "golang.org/x/mod/module" ) -var IgnoreImports bool // control whether we ignore imports in packages - // A Package describes a single package found in a directory. type Package struct { PackagePublic // visible in 'go list' @@ -85,6 +87,7 @@ type PackagePublic struct { CgoFiles []string `json:",omitempty"` // .go source files that import "C" CompiledGoFiles []string `json:",omitempty"` // .go output from running cgo on CgoFiles IgnoredGoFiles []string `json:",omitempty"` // .go source files ignored due to build constraints + InvalidGoFiles []string `json:",omitempty"` // .go source files with detected problems (parse error, wrong package name, and so on) IgnoredOtherFiles []string `json:",omitempty"` // non-.go source files ignored due to build constraints CFiles []string `json:",omitempty"` // .c source files CXXFiles []string `json:",omitempty"` // .cc, .cpp and .cxx source files @@ -142,6 +145,7 @@ func (p *Package) AllFiles() []string { p.CgoFiles, // no p.CompiledGoFiles, because they are from GoFiles or generated by us p.IgnoredGoFiles, + // no p.InvalidGoFiles, because they are from GoFiles p.IgnoredOtherFiles, p.CFiles, p.CXXFiles, @@ -190,8 +194,8 @@ type PackageInternal struct { // Unexported fields are not part of the public API. Build *build.Package Imports []*Package // this package's direct imports - CompiledImports []string // additional Imports necessary when using CompiledGoFiles (all from standard library) - RawImports []string // this package's original imports as they appear in the text of the program + CompiledImports []string // additional Imports necessary when using CompiledGoFiles (all from standard library); 1:1 with the end of PackagePublic.Imports + RawImports []string // this package's original imports as they appear in the text of the program; 1:1 with the end of PackagePublic.Imports ForceLibrary bool // this package is a library (even if named "main") CmdlineFiles bool // package built from files listed on command line CmdlinePkg bool // package listed on command line @@ -206,6 +210,7 @@ type PackageInternal struct { BuildInfo string // add this info to package main TestmainGo *[]byte // content for _testmain.go Embed map[string][]string // //go:embed comment mapping + OrigImportPath string // original import path before adding '_test' suffix Asmflags []string // -asmflags for this package Gcflags []string // -gcflags for this package @@ -343,7 +348,7 @@ type CoverVar struct { Var string // name of count struct } -func (p *Package) copyBuild(pp *build.Package) { +func (p *Package) copyBuild(opts PackageOpts, pp *build.Package) { p.Internal.Build = pp if pp.PkgTargetRoot != "" && cfg.BuildPkgdir != "" { @@ -368,6 +373,7 @@ func (p *Package) copyBuild(pp *build.Package) { p.GoFiles = pp.GoFiles p.CgoFiles = pp.CgoFiles p.IgnoredGoFiles = pp.IgnoredGoFiles + p.InvalidGoFiles = pp.InvalidGoFiles p.IgnoredOtherFiles = pp.IgnoredOtherFiles p.CFiles = pp.CFiles p.CXXFiles = pp.CXXFiles @@ -392,7 +398,7 @@ func (p *Package) copyBuild(pp *build.Package) { p.TestImports = pp.TestImports p.XTestGoFiles = pp.XTestGoFiles p.XTestImports = pp.XTestImports - if IgnoreImports { + if opts.IgnoreImports { p.Imports = nil p.Internal.RawImports = nil p.TestImports = nil @@ -401,6 +407,7 @@ func (p *Package) copyBuild(pp *build.Package) { p.EmbedPatterns = pp.EmbedPatterns p.TestEmbedPatterns = pp.TestEmbedPatterns p.XTestEmbedPatterns = pp.XTestEmbedPatterns + p.Internal.OrigImportPath = pp.ImportPath } // A PackageError describes an error loading information about a package. @@ -476,8 +483,10 @@ type ImportPathError interface { var ( _ ImportPathError = (*importError)(nil) + _ ImportPathError = (*mainPackageError)(nil) _ ImportPathError = (*modload.ImportMissingError)(nil) _ ImportPathError = (*modload.ImportMissingSumError)(nil) + _ ImportPathError = (*modload.DirectImportFromImplicitDependencyError)(nil) ) type importError struct { @@ -597,7 +606,7 @@ func ReloadPackageNoFlags(arg string, stk *ImportStack) *Package { }) packageDataCache.Delete(p.ImportPath) } - return LoadImport(context.TODO(), arg, base.Cwd, nil, stk, nil, 0) + return LoadImport(context.TODO(), PackageOpts{}, arg, base.Cwd(), nil, stk, nil, 0) } // dirToImportPath returns the pseudo-import path we use for a package @@ -649,11 +658,11 @@ const ( // LoadImport does not set tool flags and should only be used by // this package, as part of a bigger load operation, and by GOPATH-based "go get". // TODO(rsc): When GOPATH-based "go get" is removed, unexport this function. -func LoadImport(ctx context.Context, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package { - return loadImport(ctx, nil, path, srcDir, parent, stk, importPos, mode) +func LoadImport(ctx context.Context, opts PackageOpts, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package { + return loadImport(ctx, opts, nil, path, srcDir, parent, stk, importPos, mode) } -func loadImport(ctx context.Context, pre *preload, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package { +func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package { if path == "" { panic("LoadImport called with empty package path") } @@ -665,25 +674,30 @@ func loadImport(ctx context.Context, pre *preload, path, srcDir string, parent * parentRoot = parent.Root parentIsStd = parent.Standard } - bp, loaded, err := loadPackageData(path, parentPath, srcDir, parentRoot, parentIsStd, mode) - if loaded && pre != nil && !IgnoreImports { - pre.preloadImports(bp.Imports, bp) + bp, loaded, err := loadPackageData(ctx, path, parentPath, srcDir, parentRoot, parentIsStd, mode) + if loaded && pre != nil && !opts.IgnoreImports { + pre.preloadImports(ctx, opts, bp.Imports, bp) } if bp == nil { - if importErr, ok := err.(ImportPathError); !ok || importErr.ImportPath() != path { - // Only add path to the error's import stack if it's not already present on the error. - stk.Push(path) - defer stk.Pop() - } - return &Package{ + p := &Package{ PackagePublic: PackagePublic{ ImportPath: path, - Error: &PackageError{ - ImportStack: stk.Copy(), - Err: err, - }, + Incomplete: true, }, } + if importErr, ok := err.(ImportPathError); !ok || importErr.ImportPath() != path { + // Only add path to the error's import stack if it's not already present + // in the error. + // + // TODO(bcmills): setLoadPackageDataError itself has a similar Push / Pop + // sequence that empirically doesn't trigger for these errors, guarded by + // a somewhat complex condition. Figure out how to generalize that + // condition and eliminate the explicit calls here. + stk.Push(path) + defer stk.Pop() + } + p.setLoadPackageDataError(err, path, stk, nil) + return p } importPath := bp.ImportPath @@ -701,7 +715,7 @@ func loadImport(ctx context.Context, pre *preload, path, srcDir string, parent * // Load package. // loadPackageData may return bp != nil even if an error occurs, // in order to return partial information. - p.load(ctx, path, stk, importPos, bp, err) + p.load(ctx, opts, path, stk, importPos, bp, err) if !cfg.ModulesEnabled && path != cleanImport(path) { p.Error = &PackageError{ @@ -714,7 +728,7 @@ func loadImport(ctx context.Context, pre *preload, path, srcDir string, parent * } // Checked on every import because the rules depend on the code doing the importing. - if perr := disallowInternal(srcDir, parent, parentPath, p, stk); perr != p { + if perr := disallowInternal(ctx, srcDir, parent, parentPath, p, stk); perr != p { perr.Error.setPos(importPos) return perr } @@ -763,7 +777,7 @@ func loadImport(ctx context.Context, pre *preload, path, srcDir string, parent * // // loadPackageData returns a boolean, loaded, which is true if this is the // first time the package was loaded. Callers may preload imports in this case. -func loadPackageData(path, parentPath, parentDir, parentRoot string, parentIsStd bool, mode int) (bp *build.Package, loaded bool, err error) { +func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoot string, parentIsStd bool, mode int) (bp *build.Package, loaded bool, err error) { if path == "" { panic("loadPackageData called with empty package path") } @@ -835,11 +849,34 @@ func loadPackageData(path, parentPath, parentDir, parentRoot string, parentIsStd buildMode = build.ImportComment } data.p, data.err = cfg.BuildContext.ImportDir(r.dir, buildMode) - if data.p.Root == "" && cfg.ModulesEnabled { - if info := modload.PackageModuleInfo(path); info != nil { + if cfg.ModulesEnabled { + // Override data.p.Root, since ImportDir sets it to $GOPATH, if + // the module is inside $GOPATH/src. + if info := modload.PackageModuleInfo(ctx, path); info != nil { data.p.Root = info.Dir } } + if r.err != nil { + if data.err != nil { + // ImportDir gave us one error, and the module loader gave us another. + // We arbitrarily choose to keep the error from ImportDir because + // that's what our tests already expect, and it seems to provide a bit + // more detail in most cases. + } else if errors.Is(r.err, imports.ErrNoGo) { + // ImportDir said there were files in the package, but the module + // loader said there weren't. Which one is right? + // Without this special-case hack, the TestScript/test_vet case fails + // on the vetfail/p1 package (added in CL 83955). + // Apparently, imports.ShouldBuild biases toward rejecting files + // with invalid build constraints, whereas ImportDir biases toward + // accepting them. + // + // TODO(#41410: Figure out how this actually ought to work and fix + // this mess. + } else { + data.err = r.err + } + } } else if r.err != nil { data.p = new(build.Package) data.err = r.err @@ -950,7 +987,7 @@ func newPreload() *preload { // preloadMatches loads data for package paths matched by patterns. // When preloadMatches returns, some packages may not be loaded yet, but // loadPackageData and loadImport are always safe to call. -func (pre *preload) preloadMatches(matches []*search.Match) { +func (pre *preload) preloadMatches(ctx context.Context, opts PackageOpts, matches []*search.Match) { for _, m := range matches { for _, pkg := range m.Pkgs { select { @@ -959,10 +996,10 @@ func (pre *preload) preloadMatches(matches []*search.Match) { case pre.sema <- struct{}{}: go func(pkg string) { mode := 0 // don't use vendoring or module import resolution - bp, loaded, err := loadPackageData(pkg, "", base.Cwd, "", false, mode) + bp, loaded, err := loadPackageData(ctx, pkg, "", base.Cwd(), "", false, mode) <-pre.sema - if bp != nil && loaded && err == nil && !IgnoreImports { - pre.preloadImports(bp.Imports, bp) + if bp != nil && loaded && err == nil && !opts.IgnoreImports { + pre.preloadImports(ctx, opts, bp.Imports, bp) } }(pkg) } @@ -973,7 +1010,7 @@ func (pre *preload) preloadMatches(matches []*search.Match) { // preloadImports queues a list of imports for preloading. // When preloadImports returns, some packages may not be loaded yet, // but loadPackageData and loadImport are always safe to call. -func (pre *preload) preloadImports(imports []string, parent *build.Package) { +func (pre *preload) preloadImports(ctx context.Context, opts PackageOpts, imports []string, parent *build.Package) { parentIsStd := parent.Goroot && parent.ImportPath != "" && search.IsStandardImportPath(parent.ImportPath) for _, path := range imports { if path == "C" || path == "unsafe" { @@ -984,10 +1021,10 @@ func (pre *preload) preloadImports(imports []string, parent *build.Package) { return case pre.sema <- struct{}{}: go func(path string) { - bp, loaded, err := loadPackageData(path, parent.ImportPath, parent.Dir, parent.Root, parentIsStd, ResolveImport) + bp, loaded, err := loadPackageData(ctx, path, parent.ImportPath, parent.Dir, parent.Root, parentIsStd, ResolveImport) <-pre.sema - if bp != nil && loaded && err == nil && !IgnoreImports { - pre.preloadImports(bp.Imports, bp) + if bp != nil && loaded && err == nil && !opts.IgnoreImports { + pre.preloadImports(ctx, opts, bp.Imports, bp) } }(path) } @@ -1323,6 +1360,11 @@ func reusePackage(p *Package, stk *ImportStack) *Package { Err: errors.New("import cycle not allowed"), IsImportCycle: true, } + } else if !p.Error.IsImportCycle { + // If the error is already set, but it does not indicate that + // we are in an import cycle, set IsImportCycle so that we don't + // end up stuck in a loop down the road. + p.Error.IsImportCycle = true } p.Incomplete = true } @@ -1338,7 +1380,7 @@ func reusePackage(p *Package, stk *ImportStack) *Package { // is allowed to import p. // If the import is allowed, disallowInternal returns the original package p. // If not, it returns a new package containing just an appropriate error. -func disallowInternal(srcDir string, importer *Package, importerPath string, p *Package, stk *ImportStack) *Package { +func disallowInternal(ctx context.Context, srcDir string, importer *Package, importerPath string, p *Package, stk *ImportStack) *Package { // golang.org/s/go14internal: // An import of a path containing the element “internal” // is disallowed if the importing code is outside the tree @@ -1416,7 +1458,7 @@ func disallowInternal(srcDir string, importer *Package, importerPath string, p * // directory containing them. // If the directory is outside the main module, this will resolve to ".", // which is not a prefix of any valid module. - importerPath = modload.DirImportPath(importer.Dir) + importerPath = modload.DirImportPath(ctx, importer.Dir) } parentOfInternal := p.ImportPath[:i] if str.HasPathPrefix(importerPath, parentOfInternal) { @@ -1638,8 +1680,8 @@ func (p *Package) DefaultExecName() string { // load populates p using information from bp, err, which should // be the result of calling build.Context.Import. // stk contains the import stack, not including path itself. -func (p *Package) load(ctx context.Context, path string, stk *ImportStack, importPos []token.Position, bp *build.Package, err error) { - p.copyBuild(bp) +func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk *ImportStack, importPos []token.Position, bp *build.Package, err error) { + p.copyBuild(opts, bp) // The localPrefix is the path we interpret ./ imports relative to. // Synthesized main packages sometimes override this. @@ -1763,35 +1805,37 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor } } - // Cgo translation adds imports of "unsafe", "runtime/cgo" and "syscall", - // except for certain packages, to avoid circular dependencies. - if p.UsesCgo() { - addImport("unsafe", true) - } - if p.UsesCgo() && (!p.Standard || !cgoExclude[p.ImportPath]) && cfg.BuildContext.Compiler != "gccgo" { - addImport("runtime/cgo", true) - } - if p.UsesCgo() && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) { - addImport("syscall", true) - } - - // SWIG adds imports of some standard packages. - if p.UsesSwig() { - addImport("unsafe", true) - if cfg.BuildContext.Compiler != "gccgo" { + if !opts.IgnoreImports { + // Cgo translation adds imports of "unsafe", "runtime/cgo" and "syscall", + // except for certain packages, to avoid circular dependencies. + if p.UsesCgo() { + addImport("unsafe", true) + } + if p.UsesCgo() && (!p.Standard || !cgoExclude[p.ImportPath]) && cfg.BuildContext.Compiler != "gccgo" { addImport("runtime/cgo", true) } - addImport("syscall", true) - addImport("sync", true) + if p.UsesCgo() && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) { + addImport("syscall", true) + } - // TODO: The .swig and .swigcxx files can use - // %go_import directives to import other packages. - } + // SWIG adds imports of some standard packages. + if p.UsesSwig() { + addImport("unsafe", true) + if cfg.BuildContext.Compiler != "gccgo" { + addImport("runtime/cgo", true) + } + addImport("syscall", true) + addImport("sync", true) - // The linker loads implicit dependencies. - if p.Name == "main" && !p.Internal.ForceLibrary { - for _, dep := range LinkerDeps(p) { - addImport(dep, false) + // TODO: The .swig and .swigcxx files can use + // %go_import directives to import other packages. + } + + // The linker loads implicit dependencies. + if p.Name == "main" && !p.Internal.ForceLibrary { + for _, dep := range LinkerDeps(p) { + addImport(dep, false) + } } } @@ -1815,6 +1859,14 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor stk.Push(path) defer stk.Pop() + pkgPath := p.ImportPath + if p.Internal.CmdlineFiles { + pkgPath = "command-line-arguments" + } + if cfg.ModulesEnabled { + p.Module = modload.PackageModuleInfo(ctx, pkgPath) + } + p.EmbedFiles, p.Internal.Embed, err = resolveEmbed(p.Dir, p.EmbedPatterns) if err != nil { p.Incomplete = true @@ -1858,7 +1910,7 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor if path == "C" { continue } - p1 := LoadImport(ctx, path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], ResolveImport) + p1 := LoadImport(ctx, opts, path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], ResolveImport) path = p1.ImportPath importPaths[i] = path @@ -1874,6 +1926,10 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor p.Internal.Imports = imports p.collectDeps() + if cfg.ModulesEnabled && p.Error == nil && p.Name == "main" && len(p.DepsErrors) == 0 { + p.Internal.BuildInfo = modload.PackageBuildInfo(pkgPath, p.Deps) + } + // unsafe is a fake package. if p.Standard && (p.ImportPath == "unsafe" || cfg.BuildContext.Compiler == "gccgo") { p.Target = "" @@ -1913,17 +1969,6 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor setError(fmt.Errorf("Fortran source files not allowed when not using cgo or SWIG: %s", strings.Join(p.FFiles, " "))) return } - - if cfg.ModulesEnabled && p.Error == nil { - mainPath := p.ImportPath - if p.Internal.CmdlineFiles { - mainPath = "command-line-arguments" - } - p.Module = modload.PackageModuleInfo(mainPath) - if p.Name == "main" && len(p.DepsErrors) == 0 { - p.Internal.BuildInfo = modload.PackageBuildInfo(mainPath, p.Deps) - } - } } // An EmbedError indicates a problem with a go:embed directive. @@ -2305,7 +2350,7 @@ func PackageList(roots []*Package) []*Package { // TestPackageList returns the list of packages in the dag rooted at roots // as visited in a depth-first post-order traversal, including the test // imports of the roots. This ignores errors in test packages. -func TestPackageList(ctx context.Context, roots []*Package) []*Package { +func TestPackageList(ctx context.Context, opts PackageOpts, roots []*Package) []*Package { seen := map[*Package]bool{} all := []*Package{} var walk func(*Package) @@ -2321,7 +2366,7 @@ func TestPackageList(ctx context.Context, roots []*Package) []*Package { } walkTest := func(root *Package, path string) { var stk ImportStack - p1 := LoadImport(ctx, path, root.Dir, root, &stk, root.Internal.Build.TestImportPos[path], ResolveImport) + p1 := LoadImport(ctx, opts, path, root.Dir, root, &stk, root.Internal.Build.TestImportPos[path], ResolveImport) if p1.Error == nil { walk(p1) } @@ -2344,22 +2389,35 @@ func TestPackageList(ctx context.Context, roots []*Package) []*Package { // TODO(jayconrod): delete this function and set flags automatically // in LoadImport instead. func LoadImportWithFlags(path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package { - p := LoadImport(context.TODO(), path, srcDir, parent, stk, importPos, mode) + p := LoadImport(context.TODO(), PackageOpts{}, path, srcDir, parent, stk, importPos, mode) setToolFlags(p) return p } -// ModResolveTests indicates whether calls to the module loader should also -// resolve test dependencies of the requested packages. -// -// If ModResolveTests is true, then the module loader needs to resolve test -// dependencies at the same time as packages; otherwise, the test dependencies -// of those packages could be missing, and resolving those missing dependencies -// could change the selected versions of modules that provide other packages. -// -// TODO(#40775): Change this from a global variable to an explicit function -// argument where needed. -var ModResolveTests bool +// PackageOpts control the behavior of PackagesAndErrors and other package +// loading functions. +type PackageOpts struct { + // IgnoreImports controls whether we ignore explicit and implicit imports + // when loading packages. Implicit imports are added when supporting Cgo + // or SWIG and when linking main packages. + IgnoreImports bool + + // ModResolveTests indicates whether calls to the module loader should also + // resolve test dependencies of the requested packages. + // + // If ModResolveTests is true, then the module loader needs to resolve test + // dependencies at the same time as packages; otherwise, the test dependencies + // of those packages could be missing, and resolving those missing dependencies + // could change the selected versions of modules that provide other packages. + ModResolveTests bool + + // MainOnly is true if the caller only wants to load main packages. + // For a literal argument matching a non-main package, a stub may be returned + // with an error. For a non-literal argument (with "..."), non-main packages + // are not be matched, and their dependencies may not be loaded. A warning + // may be printed for non-literal arguments that match no main packages. + MainOnly bool +} // PackagesAndErrors returns the packages named by the command line arguments // 'patterns'. If a named package cannot be loaded, PackagesAndErrors returns @@ -2369,7 +2427,7 @@ var ModResolveTests bool // // To obtain a flat list of packages, use PackageList. // To report errors loading packages, use ReportPackageErrors. -func PackagesAndErrors(ctx context.Context, patterns []string) []*Package { +func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string) []*Package { ctx, span := trace.StartSpan(ctx, "load.PackagesAndErrors") defer span.Done() @@ -2381,19 +2439,19 @@ func PackagesAndErrors(ctx context.Context, patterns []string) []*Package { // We need to test whether the path is an actual Go file and not a // package path or pattern ending in '.go' (see golang.org/issue/34653). if fi, err := fsys.Stat(p); err == nil && !fi.IsDir() { - return []*Package{GoFilesPackage(ctx, patterns)} + return []*Package{GoFilesPackage(ctx, opts, patterns)} } } } var matches []*search.Match if modload.Init(); cfg.ModulesEnabled { - loadOpts := modload.PackageOpts{ + modOpts := modload.PackageOpts{ ResolveMissingImports: true, - LoadTests: ModResolveTests, - SilenceErrors: true, + LoadTests: opts.ModResolveTests, + SilencePackageErrors: true, } - matches, _ = modload.LoadPackages(ctx, loadOpts, patterns...) + matches, _ = modload.LoadPackages(ctx, modOpts, patterns...) } else { matches = search.ImportPaths(patterns) } @@ -2406,14 +2464,14 @@ func PackagesAndErrors(ctx context.Context, patterns []string) []*Package { pre := newPreload() defer pre.flush() - pre.preloadMatches(matches) + pre.preloadMatches(ctx, opts, matches) for _, m := range matches { for _, pkg := range m.Pkgs { if pkg == "" { panic(fmt.Sprintf("ImportPaths returned empty package for pattern %s", m.Pattern())) } - p := loadImport(ctx, pre, pkg, base.Cwd, nil, &stk, nil, 0) + p := loadImport(ctx, opts, pre, pkg, base.Cwd(), nil, &stk, nil, 0) p.Match = append(p.Match, m.Pattern()) p.Internal.CmdlinePkg = true if m.IsLiteral() { @@ -2449,6 +2507,10 @@ func PackagesAndErrors(ctx context.Context, patterns []string) []*Package { } } + if opts.MainOnly { + pkgs = mainPackagesOnly(pkgs, matches) + } + // Now that CmdlinePkg is set correctly, // compute the effective flags for all loaded packages // (not just the ones matching the patterns but also @@ -2497,6 +2559,80 @@ func CheckPackageErrors(pkgs []*Package) { base.ExitIfErrors() } +// mainPackagesOnly filters out non-main packages matched only by arguments +// containing "..." and returns the remaining main packages. +// +// Packages with missing, invalid, or ambiguous names may be treated as +// possibly-main packages. +// +// mainPackagesOnly sets a non-main package's Error field and returns it if it +// is named by a literal argument. +// +// mainPackagesOnly prints warnings for non-literal arguments that only match +// non-main packages. +func mainPackagesOnly(pkgs []*Package, matches []*search.Match) []*Package { + treatAsMain := map[string]bool{} + for _, m := range matches { + if m.IsLiteral() { + for _, path := range m.Pkgs { + treatAsMain[path] = true + } + } + } + + var mains []*Package + for _, pkg := range pkgs { + if pkg.Name == "main" { + treatAsMain[pkg.ImportPath] = true + mains = append(mains, pkg) + continue + } + + if len(pkg.InvalidGoFiles) > 0 { // TODO(#45999): && pkg.Name == "", but currently go/build sets pkg.Name arbitrarily if it is ambiguous. + // The package has (or may have) conflicting names, and we can't easily + // tell whether one of them is "main". So assume that it could be, and + // report an error for the package. + treatAsMain[pkg.ImportPath] = true + } + if treatAsMain[pkg.ImportPath] { + if pkg.Error == nil { + pkg.Error = &PackageError{Err: &mainPackageError{importPath: pkg.ImportPath}} + } + mains = append(mains, pkg) + } + } + + for _, m := range matches { + if m.IsLiteral() || len(m.Pkgs) == 0 { + continue + } + foundMain := false + for _, path := range m.Pkgs { + if treatAsMain[path] { + foundMain = true + break + } + } + if !foundMain { + fmt.Fprintf(os.Stderr, "go: warning: %q matched only non-main packages\n", m.Pattern()) + } + } + + return mains +} + +type mainPackageError struct { + importPath string +} + +func (e *mainPackageError) Error() string { + return fmt.Sprintf("package %s is not a main package", e.importPath) +} + +func (e *mainPackageError) ImportPath() string { + return e.importPath +} + func setToolFlags(pkgs ...*Package) { for _, p := range PackageList(pkgs) { p.Internal.Asmflags = BuildAsmflags.For(p) @@ -2509,7 +2645,7 @@ func setToolFlags(pkgs ...*Package) { // GoFilesPackage creates a package for building a collection of Go files // (typically named on the command line). The target is named p.a for // package p or named after the first Go file for package main. -func GoFilesPackage(ctx context.Context, gofiles []string) *Package { +func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Package { modload.Init() for _, f := range gofiles { @@ -2562,7 +2698,7 @@ func GoFilesPackage(ctx context.Context, gofiles []string) *Package { var err error if dir == "" { - dir = base.Cwd + dir = base.Cwd() } dir, err = filepath.Abs(dir) if err != nil { @@ -2573,7 +2709,7 @@ func GoFilesPackage(ctx context.Context, gofiles []string) *Package { pkg := new(Package) pkg.Internal.Local = true pkg.Internal.CmdlineFiles = true - pkg.load(ctx, "command-line-arguments", &stk, nil, bp, err) + pkg.load(ctx, opts, "command-line-arguments", &stk, nil, bp, err) pkg.Internal.LocalPrefix = dirToImportPath(dir) pkg.ImportPath = "command-line-arguments" pkg.Target = "" @@ -2589,7 +2725,138 @@ func GoFilesPackage(ctx context.Context, gofiles []string) *Package { } } + if opts.MainOnly && pkg.Name != "main" && pkg.Error == nil { + pkg.Error = &PackageError{Err: &mainPackageError{importPath: pkg.ImportPath}} + } setToolFlags(pkg) return pkg } + +// PackagesAndErrorsOutsideModule is like PackagesAndErrors but runs in +// module-aware mode and ignores the go.mod file in the current directory or any +// parent directory, if there is one. This is used in the implementation of 'go +// install pkg@version' and other commands that support similar forms. +// +// modload.ForceUseModules must be true, and modload.RootMode must be NoRoot +// before calling this function. +// +// PackagesAndErrorsOutsideModule imposes several constraints to avoid +// ambiguity. All arguments must have the same version suffix (not just a suffix +// that resolves to the same version). They must refer to packages in the same +// module, which must not be std or cmd. That module is not considered the main +// module, but its go.mod file (if it has one) must not contain directives that +// would cause it to be interpreted differently if it were the main module +// (replace, exclude). +func PackagesAndErrorsOutsideModule(ctx context.Context, opts PackageOpts, args []string) ([]*Package, error) { + if !modload.ForceUseModules { + panic("modload.ForceUseModules must be true") + } + if modload.RootMode != modload.NoRoot { + panic("modload.RootMode must be NoRoot") + } + + // Check that the arguments satisfy syntactic constraints. + var version string + for _, arg := range args { + if i := strings.Index(arg, "@"); i >= 0 { + version = arg[i+1:] + if version == "" { + return nil, fmt.Errorf("%s: version must not be empty", arg) + } + break + } + } + patterns := make([]string, len(args)) + for i, arg := range args { + if !strings.HasSuffix(arg, "@"+version) { + return nil, fmt.Errorf("%s: all arguments must have the same version (@%s)", arg, version) + } + p := arg[:len(arg)-len(version)-1] + switch { + case build.IsLocalImport(p): + return nil, fmt.Errorf("%s: argument must be a package path, not a relative path", arg) + case filepath.IsAbs(p): + return nil, fmt.Errorf("%s: argument must be a package path, not an absolute path", arg) + case search.IsMetaPackage(p): + return nil, fmt.Errorf("%s: argument must be a package path, not a meta-package", arg) + case path.Clean(p) != p: + return nil, fmt.Errorf("%s: argument must be a clean package path", arg) + case !strings.Contains(p, "...") && search.IsStandardImportPath(p) && goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, p): + return nil, fmt.Errorf("%s: argument must not be a package in the standard library", arg) + default: + patterns[i] = p + } + } + + // Query the module providing the first argument, load its go.mod file, and + // check that it doesn't contain directives that would cause it to be + // interpreted differently if it were the main module. + // + // If multiple modules match the first argument, accept the longest match + // (first result). It's possible this module won't provide packages named by + // later arguments, and other modules would. Let's not try to be too + // magical though. + allowed := modload.CheckAllowed + if modload.IsRevisionQuery(version) { + // Don't check for retractions if a specific revision is requested. + allowed = nil + } + noneSelected := func(path string) (version string) { return "none" } + qrs, err := modload.QueryPackages(ctx, patterns[0], version, noneSelected, allowed) + if err != nil { + return nil, fmt.Errorf("%s: %w", args[0], err) + } + rootMod := qrs[0].Mod + data, err := modfetch.GoMod(rootMod.Path, rootMod.Version) + if err != nil { + return nil, fmt.Errorf("%s: %w", args[0], err) + } + f, err := modfile.Parse("go.mod", data, nil) + if err != nil { + return nil, fmt.Errorf("%s (in %s): %w", args[0], rootMod, err) + } + directiveFmt := "%s (in %s):\n" + + "\tThe go.mod file for the module providing named packages contains one or\n" + + "\tmore %s directives. It must not contain directives that would cause\n" + + "\tit to be interpreted differently than if it were the main module." + if len(f.Replace) > 0 { + return nil, fmt.Errorf(directiveFmt, args[0], rootMod, "replace") + } + if len(f.Exclude) > 0 { + return nil, fmt.Errorf(directiveFmt, args[0], rootMod, "exclude") + } + + // Since we are in NoRoot mode, the build list initially contains only + // the dummy command-line-arguments module. Add a requirement on the + // module that provides the packages named on the command line. + if _, err := modload.EditBuildList(ctx, nil, []module.Version{rootMod}); err != nil { + return nil, fmt.Errorf("%s: %w", args[0], err) + } + + // Load packages for all arguments. + pkgs := PackagesAndErrors(ctx, opts, patterns) + + // Check that named packages are all provided by the same module. + for _, pkg := range pkgs { + var pkgErr error + if pkg.Module == nil { + // Packages in std, cmd, and their vendored dependencies + // don't have this field set. + pkgErr = fmt.Errorf("package %s not provided by module %s", pkg.ImportPath, rootMod) + } else if pkg.Module.Path != rootMod.Path || pkg.Module.Version != rootMod.Version { + pkgErr = fmt.Errorf("package %s provided by module %s@%s\n\tAll packages must be provided by the same module (%s).", pkg.ImportPath, pkg.Module.Path, pkg.Module.Version, rootMod) + } + if pkgErr != nil && pkg.Error == nil { + pkg.Error = &PackageError{Err: pkgErr} + } + } + + matchers := make([]func(string) bool, len(patterns)) + for i, p := range patterns { + if strings.Contains(p, "...") { + matchers[i] = search.MatchPattern(p) + } + } + return pkgs, nil +} diff --git a/libgo/go/cmd/go/internal/load/test.go b/libgo/go/cmd/go/internal/load/test.go index eb8aef3..c828296 100644 --- a/libgo/go/cmd/go/internal/load/test.go +++ b/libgo/go/cmd/go/internal/load/test.go @@ -21,6 +21,7 @@ import ( "unicode" "unicode/utf8" + "cmd/go/internal/fsys" "cmd/go/internal/str" "cmd/go/internal/trace" ) @@ -45,8 +46,8 @@ type TestCover struct { // TestPackagesFor is like TestPackagesAndErrors but it returns // an error if the test packages or their dependencies have errors. // Only test packages without errors are returned. -func TestPackagesFor(ctx context.Context, p *Package, cover *TestCover) (pmain, ptest, pxtest *Package, err error) { - pmain, ptest, pxtest = TestPackagesAndErrors(ctx, p, cover) +func TestPackagesFor(ctx context.Context, opts PackageOpts, p *Package, cover *TestCover) (pmain, ptest, pxtest *Package, err error) { + pmain, ptest, pxtest = TestPackagesAndErrors(ctx, opts, p, cover) for _, p1 := range []*Package{ptest, pxtest, pmain} { if p1 == nil { // pxtest may be nil @@ -92,7 +93,7 @@ func TestPackagesFor(ctx context.Context, p *Package, cover *TestCover) (pmain, // // The caller is expected to have checked that len(p.TestGoFiles)+len(p.XTestGoFiles) > 0, // or else there's no point in any of this. -func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (pmain, ptest, pxtest *Package) { +func TestPackagesAndErrors(ctx context.Context, opts PackageOpts, p *Package, cover *TestCover) (pmain, ptest, pxtest *Package) { ctx, span := trace.StartSpan(ctx, "load.TestPackagesAndErrors") defer span.Done() @@ -100,7 +101,7 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p defer pre.flush() allImports := append([]string{}, p.TestImports...) allImports = append(allImports, p.XTestImports...) - pre.preloadImports(allImports, p.Internal.Build) + pre.preloadImports(ctx, opts, allImports, p.Internal.Build) var ptestErr, pxtestErr *PackageError var imports, ximports []*Package @@ -109,13 +110,13 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p stk.Push(p.ImportPath + " (test)") rawTestImports := str.StringList(p.TestImports) for i, path := range p.TestImports { - p1 := loadImport(ctx, pre, path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport) + p1 := loadImport(ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport) if str.Contains(p1.Deps, p.ImportPath) || p1.ImportPath == p.ImportPath { // Same error that loadPackage returns (via reusePackage) in pkg.go. // Can't change that code, because that code is only for loading the // non-test copy of a package. ptestErr = &PackageError{ - ImportStack: testImportStack(stk[0], p1, p.ImportPath), + ImportStack: importCycleStack(p1, p.ImportPath), Err: errors.New("import cycle not allowed in test"), IsImportCycle: true, } @@ -139,7 +140,7 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p pxtestNeedsPtest := false rawXTestImports := str.StringList(p.XTestImports) for i, path := range p.XTestImports { - p1 := loadImport(ctx, pre, path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport) + p1 := loadImport(ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport) if p1.ImportPath == p.ImportPath { pxtestNeedsPtest = true } else { @@ -203,6 +204,7 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p } ptest.Internal.Embed = testEmbed ptest.EmbedFiles = str.StringList(p.EmbedFiles, p.TestEmbedFiles) + ptest.Internal.OrigImportPath = p.Internal.OrigImportPath ptest.collectDeps() } else { ptest = p @@ -232,11 +234,12 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p Imports: ximports, RawImports: rawXTestImports, - Asmflags: p.Internal.Asmflags, - Gcflags: p.Internal.Gcflags, - Ldflags: p.Internal.Ldflags, - Gccgoflags: p.Internal.Gccgoflags, - Embed: xtestEmbed, + Asmflags: p.Internal.Asmflags, + Gcflags: p.Internal.Gcflags, + Ldflags: p.Internal.Ldflags, + Gccgoflags: p.Internal.Gccgoflags, + Embed: xtestEmbed, + OrigImportPath: p.Internal.OrigImportPath, }, } if pxtestNeedsPtest { @@ -257,12 +260,13 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p Module: p.Module, }, Internal: PackageInternal{ - Build: &build.Package{Name: "main"}, - BuildInfo: p.Internal.BuildInfo, - Asmflags: p.Internal.Asmflags, - Gcflags: p.Internal.Gcflags, - Ldflags: p.Internal.Ldflags, - Gccgoflags: p.Internal.Gccgoflags, + Build: &build.Package{Name: "main"}, + BuildInfo: p.Internal.BuildInfo, + Asmflags: p.Internal.Asmflags, + Gcflags: p.Internal.Gcflags, + Ldflags: p.Internal.Ldflags, + Gccgoflags: p.Internal.Gccgoflags, + OrigImportPath: p.Internal.OrigImportPath, }, } @@ -277,7 +281,7 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p if dep == ptest.ImportPath { pmain.Internal.Imports = append(pmain.Internal.Imports, ptest) } else { - p1 := loadImport(ctx, pre, dep, "", nil, &stk, nil, 0) + p1 := loadImport(ctx, opts, pre, dep, "", nil, &stk, nil, 0) pmain.Internal.Imports = append(pmain.Internal.Imports, p1) } } @@ -290,10 +294,12 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p seen[p1] = true } for _, p1 := range cover.Pkgs { - if !seen[p1] { - seen[p1] = true - pmain.Internal.Imports = append(pmain.Internal.Imports, p1) + if seen[p1] { + // Don't add duplicate imports. + continue } + seen[p1] = true + pmain.Internal.Imports = append(pmain.Internal.Imports, p1) } } @@ -369,22 +375,44 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p return pmain, ptest, pxtest } -func testImportStack(top string, p *Package, target string) []string { - stk := []string{top, p.ImportPath} -Search: - for p.ImportPath != target { - for _, p1 := range p.Internal.Imports { - if p1.ImportPath == target || str.Contains(p1.Deps, target) { - stk = append(stk, p1.ImportPath) - p = p1 - continue Search +// importCycleStack returns an import stack from p to the package whose import +// path is target. +func importCycleStack(p *Package, target string) []string { + // importerOf maps each import path to its importer nearest to p. + importerOf := map[string]string{p.ImportPath: ""} + + // q is a breadth-first queue of packages to search for target. + // Every package added to q has a corresponding entry in pathTo. + // + // We search breadth-first for two reasons: + // + // 1. We want to report the shortest cycle. + // + // 2. If p contains multiple cycles, the first cycle we encounter might not + // contain target. To ensure termination, we have to break all cycles + // other than the first. + q := []*Package{p} + + for len(q) > 0 { + p := q[0] + q = q[1:] + if path := p.ImportPath; path == target { + var stk []string + for path != "" { + stk = append(stk, path) + path = importerOf[path] + } + return stk + } + for _, dep := range p.Internal.Imports { + if _, ok := importerOf[dep.ImportPath]; !ok { + importerOf[dep.ImportPath] = p.ImportPath + q = append(q, dep) } } - // Can't happen, but in case it does... - stk = append(stk, "<lost path to cycle>") - break } - return stk + + panic("lost path to cycle") } // recompileForTest copies and replaces certain packages in pmain's dependency @@ -576,7 +604,13 @@ type testFunc struct { var testFileSet = token.NewFileSet() func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error { - f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments) + // Pass in the overlaid source if we have an overlay for this file. + src, err := fsys.Open(filename) + if err != nil { + return err + } + defer src.Close() + f, err := parser.ParseFile(testFileSet, filename, src, parser.ParseComments) if err != nil { return err } diff --git a/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go b/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go index ea480f8..e302fe7 100644 --- a/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go +++ b/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || (solaris && !illumos) // +build aix solaris,!illumos // This code implements the filelock API using POSIX 'fcntl' locks, which attach diff --git a/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_other.go b/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_other.go index c09530d..c6eac30 100644 --- a/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_other.go +++ b/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_other.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !aix && !darwin && !dragonfly && !freebsd && !hurd && !linux && !netbsd && !openbsd && !plan9 && !solaris && !windows // +build !aix,!darwin,!dragonfly,!freebsd,!hurd,!linux,!netbsd,!openbsd,!plan9,!solaris,!windows package filelock diff --git a/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_plan9.go b/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_plan9.go index 0798ee4..908afb6 100644 --- a/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_plan9.go +++ b/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_plan9.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build plan9 // +build plan9 package filelock diff --git a/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go b/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go index 2ac2052..640d440 100644 --- a/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go +++ b/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js && !plan9 // +build !js,!plan9 package filelock_test diff --git a/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_unix.go b/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_unix.go index c06b0f7..b22c0bb 100644 --- a/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_unix.go +++ b/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || hurd || illumos || linux || netbsd || openbsd // +build darwin dragonfly freebsd hurd illumos linux netbsd openbsd package filelock diff --git a/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_windows.go b/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_windows.go index 19de27e..dd27ce9 100644 --- a/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_windows.go +++ b/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_windows.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package filelock diff --git a/libgo/go/cmd/go/internal/lockedfile/lockedfile_filelock.go b/libgo/go/cmd/go/internal/lockedfile/lockedfile_filelock.go index efc6646..e4923f6 100644 --- a/libgo/go/cmd/go/internal/lockedfile/lockedfile_filelock.go +++ b/libgo/go/cmd/go/internal/lockedfile/lockedfile_filelock.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 // +build !plan9 package lockedfile @@ -10,7 +11,6 @@ import ( "io/fs" "os" - "cmd/go/internal/fsys" "cmd/go/internal/lockedfile/internal/filelock" ) @@ -20,7 +20,7 @@ func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) { // calls for Linux and Windows anyway, so it's simpler to use that approach // consistently. - f, err := fsys.OpenFile(name, flag&^os.O_TRUNC, perm) + f, err := os.OpenFile(name, flag&^os.O_TRUNC, perm) if err != nil { return nil, err } diff --git a/libgo/go/cmd/go/internal/lockedfile/lockedfile_plan9.go b/libgo/go/cmd/go/internal/lockedfile/lockedfile_plan9.go index 70d6edd..979118b 100644 --- a/libgo/go/cmd/go/internal/lockedfile/lockedfile_plan9.go +++ b/libgo/go/cmd/go/internal/lockedfile/lockedfile_plan9.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build plan9 // +build plan9 package lockedfile @@ -12,8 +13,6 @@ import ( "os" "strings" "time" - - "cmd/go/internal/fsys" ) // Opening an exclusive-use file returns an error. @@ -58,7 +57,7 @@ func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) { // If the file was unpacked or created by some other program, it might not // have the ModeExclusive bit set. Set it before we call OpenFile, so that we // can be confident that a successful OpenFile implies exclusive use. - if fi, err := fsys.Stat(name); err == nil { + if fi, err := os.Stat(name); err == nil { if fi.Mode()&fs.ModeExclusive == 0 { if err := os.Chmod(name, fi.Mode()|fs.ModeExclusive); err != nil { return nil, err @@ -71,7 +70,7 @@ func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) { nextSleep := 1 * time.Millisecond const maxSleep = 500 * time.Millisecond for { - f, err := fsys.OpenFile(name, flag, perm|fs.ModeExclusive) + f, err := os.OpenFile(name, flag, perm|fs.ModeExclusive) if err == nil { return f, nil } diff --git a/libgo/go/cmd/go/internal/lockedfile/lockedfile_test.go b/libgo/go/cmd/go/internal/lockedfile/lockedfile_test.go index 34327dd..3acc669 100644 --- a/libgo/go/cmd/go/internal/lockedfile/lockedfile_test.go +++ b/libgo/go/cmd/go/internal/lockedfile/lockedfile_test.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. // js does not support inter-process file locking. +//go:build !js // +build !js package lockedfile_test diff --git a/libgo/go/cmd/go/internal/lockedfile/transform_test.go b/libgo/go/cmd/go/internal/lockedfile/transform_test.go index 407d48e..b753346 100644 --- a/libgo/go/cmd/go/internal/lockedfile/transform_test.go +++ b/libgo/go/cmd/go/internal/lockedfile/transform_test.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. // js does not support inter-process file locking. +//go:build !js // +build !js package lockedfile_test diff --git a/libgo/go/cmd/go/internal/modcmd/download.go b/libgo/go/cmd/go/internal/modcmd/download.go index a602bb9..0e5af85 100644 --- a/libgo/go/cmd/go/internal/modcmd/download.go +++ b/libgo/go/cmd/go/internal/modcmd/download.go @@ -134,21 +134,18 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { } var mods []*moduleJSON - listU := false - listVersions := false - listRetractions := false type token struct{} sem := make(chan token, runtime.GOMAXPROCS(0)) - infos := modload.ListModules(ctx, args, listU, listVersions, listRetractions) + infos, infosErr := modload.ListModules(ctx, args, 0) 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() + // '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, in ListModules, 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.DisallowWriteGoMod() } @@ -209,6 +206,13 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) { // // Don't save sums for 'go mod download' without arguments; see comment above. if haveExplicitArgs { - modload.WriteGoMod() + modload.WriteGoMod(ctx) + } + + // If there was an error matching some of the requested packages, emit it now + // (after we've written the checksums for the modules that were downloaded + // successfully). + if infosErr != nil { + base.Errorf("go mod download: %v", infosErr) } } diff --git a/libgo/go/cmd/go/internal/modcmd/edit.go b/libgo/go/cmd/go/internal/modcmd/edit.go index 1df104e..bb3d521 100644 --- a/libgo/go/cmd/go/internal/modcmd/edit.go +++ b/libgo/go/cmd/go/internal/modcmd/edit.go @@ -25,7 +25,7 @@ import ( ) var cmdEdit = &base.Command{ - UsageLine: "go mod edit [editing flags] [go.mod]", + UsageLine: "go mod edit [editing flags] [-fmt|-print|-json] [go.mod]", Short: "edit go.mod from tools or scripts", Long: ` Edit provides a command-line interface for editing go.mod, @@ -85,12 +85,12 @@ The -json flag prints the final go.mod file in JSON format instead of writing it back to go.mod. The JSON output corresponds to these Go types: type Module struct { - Path string + Path string Version string } type GoMod struct { - Module Module + Module ModPath Go string Require []Require Exclude []Module @@ -98,6 +98,11 @@ writing it back to go.mod. The JSON output corresponds to these Go types: Retract []Retract } + type ModPath struct { + Path string + Deprecated string + } + type Require struct { Path string Version string @@ -191,7 +196,7 @@ func runEdit(ctx context.Context, cmd *base.Command, args []string) { if *editGo != "" { if !modfile.GoVersionRE.MatchString(*editGo) { - base.Fatalf(`go mod: invalid -go option; expecting something like "-go 1.12"`) + base.Fatalf(`go mod: invalid -go option; expecting something like "-go %s"`, modload.LatestGoVersion()) } } @@ -450,7 +455,7 @@ func flagDropRetract(arg string) { // fileJSON is the -json output data structure. type fileJSON struct { - Module module.Version + Module editModuleJSON Go string `json:",omitempty"` Require []requireJSON Exclude []module.Version @@ -458,6 +463,11 @@ type fileJSON struct { Retract []retractJSON } +type editModuleJSON struct { + Path string + Deprecated string `json:",omitempty"` +} + type requireJSON struct { Path string Version string `json:",omitempty"` @@ -479,7 +489,10 @@ type retractJSON struct { func editPrintJSON(modFile *modfile.File) { var f fileJSON if modFile.Module != nil { - f.Module = modFile.Module.Mod + f.Module = editModuleJSON{ + Path: modFile.Module.Mod.Path, + Deprecated: modFile.Module.Deprecated, + } } if modFile.Go != nil { f.Go = modFile.Go.Version diff --git a/libgo/go/cmd/go/internal/modcmd/graph.go b/libgo/go/cmd/go/internal/modcmd/graph.go index a88e9ef..ac81f26 100644 --- a/libgo/go/cmd/go/internal/modcmd/graph.go +++ b/libgo/go/cmd/go/internal/modcmd/graph.go @@ -10,7 +10,6 @@ import ( "bufio" "context" "os" - "sort" "cmd/go/internal/base" "cmd/go/internal/modload" @@ -19,7 +18,7 @@ import ( ) var cmdGraph = &base.Command{ - UsageLine: "go mod graph", + UsageLine: "go mod graph [-go=version]", Short: "print module requirement graph", Long: ` Graph prints the module requirement graph (with replacements applied) @@ -27,12 +26,21 @@ in text form. Each line in the output has two space-separated fields: a module and one of its requirements. Each module is identified as a string of the form path@version, except for the main module, which has no @version suffix. +The -go flag causes graph to report the module graph as loaded by the +given Go version, instead of the version indicated by the 'go' directive +in the go.mod file. + See https://golang.org/ref/mod#go-mod-graph for more about 'go mod graph'. `, Run: runGraph, } +var ( + graphGo goVersionFlag +) + func init() { + cmdGraph.Flag.Var(&graphGo, "go", "") base.AddModCommonFlags(&cmdGraph.Flag) } @@ -42,43 +50,26 @@ func runGraph(ctx context.Context, cmd *base.Command, args []string) { } modload.ForceUseModules = true modload.RootMode = modload.NeedRoot - modload.LoadAllModules(ctx) + mg := modload.LoadModGraph(ctx, graphGo.String()) - reqs := modload.MinReqs() - format := func(m module.Version) string { - if m.Version == "" { - return m.Path - } - return m.Path + "@" + m.Version - } + w := bufio.NewWriter(os.Stdout) + defer w.Flush() - var out []string - var deps int // index in out where deps start - seen := map[module.Version]bool{modload.Target: true} - queue := []module.Version{modload.Target} - for len(queue) > 0 { - var m module.Version - m, queue = queue[0], queue[1:] - list, _ := reqs.Required(m) - for _, r := range list { - if !seen[r] { - queue = append(queue, r) - seen[r] = true - } - out = append(out, format(m)+" "+format(r)+"\n") - } - if m == modload.Target { - deps = len(out) + format := func(m module.Version) { + w.WriteString(m.Path) + if m.Version != "" { + w.WriteString("@") + w.WriteString(m.Version) } } - sort.Slice(out[deps:], func(i, j int) bool { - return out[deps+i][0] < out[deps+j][0] + mg.WalkBreadthFirst(func(m module.Version) { + reqs, _ := mg.RequiredBy(m) + for _, r := range reqs { + format(m) + w.WriteByte(' ') + format(r) + w.WriteByte('\n') + } }) - - w := bufio.NewWriter(os.Stdout) - for _, line := range out { - w.WriteString(line) - } - w.Flush() } diff --git a/libgo/go/cmd/go/internal/modcmd/init.go b/libgo/go/cmd/go/internal/modcmd/init.go index 73cc282..958c306 100644 --- a/libgo/go/cmd/go/internal/modcmd/init.go +++ b/libgo/go/cmd/go/internal/modcmd/init.go @@ -13,7 +13,7 @@ import ( ) var cmdInit = &base.Command{ - UsageLine: "go mod init [module]", + UsageLine: "go mod init [module-path]", Short: "initialize new module in current directory", Long: ` Init initializes and writes a new go.mod file in the current directory, in diff --git a/libgo/go/cmd/go/internal/modcmd/tidy.go b/libgo/go/cmd/go/internal/modcmd/tidy.go index 67f90b1..fe25507 100644 --- a/libgo/go/cmd/go/internal/modcmd/tidy.go +++ b/libgo/go/cmd/go/internal/modcmd/tidy.go @@ -12,10 +12,14 @@ import ( "cmd/go/internal/imports" "cmd/go/internal/modload" "context" + "fmt" + + "golang.org/x/mod/modfile" + "golang.org/x/mod/semver" ) var cmdTidy = &base.Command{ - UsageLine: "go mod tidy [-e] [-v]", + UsageLine: "go mod tidy [-e] [-v] [-go=version] [-compat=version]", Short: "add missing and remove unused modules", Long: ` Tidy makes sure go.mod matches the source code in the module. @@ -30,19 +34,65 @@ to standard error. The -e flag causes tidy to attempt to proceed despite errors encountered while loading packages. +The -go flag causes tidy to update the 'go' directive in the go.mod +file to the given version, which may change which module dependencies +are retained as explicit requirements in the go.mod file. +(Go versions 1.17 and higher retain more requirements in order to +support lazy module loading.) + +The -compat flag preserves any additional checksums needed for the +'go' command from the indicated major Go release to successfully load +the module graph, and causes tidy to error out if that version of the +'go' command would load any imported package from a different module +version. By default, tidy acts as if the -compat flag were set to the +version prior to the one indicated by the 'go' directive in the go.mod +file. + See https://golang.org/ref/mod#go-mod-tidy for more about 'go mod tidy'. `, Run: runTidy, } -var tidyE bool // if true, report errors but proceed anyway. +var ( + tidyE bool // if true, report errors but proceed anyway. + tidyGo goVersionFlag // go version to write to the tidied go.mod file (toggles lazy loading) + tidyCompat goVersionFlag // go version for which the tidied go.mod and go.sum files should be “compatible” +) func init() { cmdTidy.Flag.BoolVar(&cfg.BuildV, "v", false, "") cmdTidy.Flag.BoolVar(&tidyE, "e", false, "") + cmdTidy.Flag.Var(&tidyGo, "go", "") + cmdTidy.Flag.Var(&tidyCompat, "compat", "") base.AddModCommonFlags(&cmdTidy.Flag) } +// A goVersionFlag is a flag.Value representing a supported Go version. +// +// (Note that the -go argument to 'go mod edit' is *not* a goVersionFlag. +// It intentionally allows newer-than-supported versions as arguments.) +type goVersionFlag struct { + v string +} + +func (f *goVersionFlag) String() string { return f.v } +func (f *goVersionFlag) Get() interface{} { return f.v } + +func (f *goVersionFlag) Set(s string) error { + if s != "" { + latest := modload.LatestGoVersion() + if !modfile.GoVersionRE.MatchString(s) { + return fmt.Errorf("expecting a Go version like %q", latest) + } + if semver.Compare("v"+s, "v"+latest) > 0 { + return fmt.Errorf("maximum supported Go version is %s", latest) + } + } + + f.v = s + return nil +} + func runTidy(ctx context.Context, cmd *base.Command, args []string) { if len(args) > 0 { base.Fatalf("go mod tidy: no arguments allowed") @@ -61,17 +111,15 @@ 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{ + GoVersion: tidyGo.String(), Tags: imports.AnyTags(), + Tidy: true, + TidyCompatibleVersion: tidyCompat.String(), + VendorModulesInGOROOTSrc: true, ResolveMissingImports: true, LoadTests: true, AllowErrors: tidyE, SilenceMissingStdImports: true, }, "all") - - modload.TidyBuildList() - modload.TrimGoSum() - modload.WriteGoMod() } diff --git a/libgo/go/cmd/go/internal/modcmd/vendor.go b/libgo/go/cmd/go/internal/modcmd/vendor.go index ac1fb77..713d5f9 100644 --- a/libgo/go/cmd/go/internal/modcmd/vendor.go +++ b/libgo/go/cmd/go/internal/modcmd/vendor.go @@ -13,6 +13,7 @@ import ( "io" "io/fs" "os" + "path" "path/filepath" "sort" "strings" @@ -65,6 +66,7 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) { loadOpts := modload.PackageOpts{ Tags: imports.AnyTags(), + VendorModulesInGOROOTSrc: true, ResolveMissingImports: true, UseVendorAll: true, AllowErrors: vendorE, @@ -87,15 +89,23 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) { } includeAllReplacements := false + includeGoVersions := false isExplicit := map[module.Version]bool{} - if gv := modload.ModFile().Go; gv != nil && semver.Compare("v"+gv.Version, "v1.14") >= 0 { - // If the Go version is at least 1.14, annotate all explicit 'require' and - // 'replace' targets found in the go.mod file so that we can perform a - // stronger consistency check when -mod=vendor is set. - for _, r := range modload.ModFile().Require { - isExplicit[r.Mod] = true + if gv := modload.ModFile().Go; gv != nil { + if semver.Compare("v"+gv.Version, "v1.14") >= 0 { + // If the Go version is at least 1.14, annotate all explicit 'require' and + // 'replace' targets found in the go.mod file so that we can perform a + // stronger consistency check when -mod=vendor is set. + for _, r := range modload.ModFile().Require { + isExplicit[r.Mod] = true + } + includeAllReplacements = true + } + if semver.Compare("v"+gv.Version, "v1.17") >= 0 { + // If the Go version is at least 1.17, annotate all modules with their + // 'go' version directives. + includeGoVersions = true } - includeAllReplacements = true } var vendorMods []module.Version @@ -109,26 +119,35 @@ func runVendor(ctx context.Context, cmd *base.Command, args []string) { } module.Sort(vendorMods) - var buf bytes.Buffer + var ( + buf bytes.Buffer + w io.Writer = &buf + ) + if cfg.BuildV { + w = io.MultiWriter(&buf, os.Stderr) + } + for _, m := range vendorMods { line := moduleLine(m, modload.Replacement(m)) - buf.WriteString(line) - if cfg.BuildV { - os.Stderr.WriteString(line) + io.WriteString(w, line) + + goVersion := "" + if includeGoVersions { + goVersion = modload.ModuleInfo(ctx, m.Path).GoVersion } - if isExplicit[m] { - buf.WriteString("## explicit\n") - if cfg.BuildV { - os.Stderr.WriteString("## explicit\n") - } + switch { + case isExplicit[m] && goVersion != "": + fmt.Fprintf(w, "## explicit; go %s\n", goVersion) + case isExplicit[m]: + io.WriteString(w, "## explicit\n") + case goVersion != "": + fmt.Fprintf(w, "## go %s\n", goVersion) } + pkgs := modpkgs[m] sort.Strings(pkgs) for _, pkg := range pkgs { - fmt.Fprintf(&buf, "%s\n", pkg) - if cfg.BuildV { - fmt.Fprintf(os.Stderr, "%s\n", pkg) - } + fmt.Fprintf(w, "%s\n", pkg) vendorPkg(vdir, pkg) } } @@ -281,7 +300,7 @@ func copyMetadata(modPath, pkg, dst, src string, copiedFiles map[string]bool) { if modPath == pkg { break } - pkg = filepath.Dir(pkg) + pkg = path.Dir(pkg) dst = filepath.Dir(dst) src = filepath.Dir(src) } @@ -322,6 +341,15 @@ func matchPotentialSourceFile(dir string, info fs.DirEntry) bool { if strings.HasSuffix(info.Name(), "_test.go") { return false } + if info.Name() == "go.mod" || info.Name() == "go.sum" { + if gv := modload.ModFile().Go; gv != nil && semver.Compare("v"+gv.Version, "v1.17") >= 0 { + // As of Go 1.17, we strip go.mod and go.sum files from dependency modules. + // Otherwise, 'go' commands invoked within the vendor subtree may misidentify + // an arbitrary directory within the vendor tree as a module root. + // (See https://golang.org/issue/42970.) + return false + } + } if strings.HasSuffix(info.Name(), ".go") { f, err := fsys.Open(filepath.Join(dir, info.Name())) if err != nil { diff --git a/libgo/go/cmd/go/internal/modcmd/verify.go b/libgo/go/cmd/go/internal/modcmd/verify.go index 8321429..5a6eca3 100644 --- a/libgo/go/cmd/go/internal/modcmd/verify.go +++ b/libgo/go/cmd/go/internal/modcmd/verify.go @@ -54,7 +54,8 @@ func runVerify(ctx context.Context, cmd *base.Command, args []string) { sem := make(chan token, runtime.GOMAXPROCS(0)) // Use a slice of result channels, so that the output is deterministic. - mods := modload.LoadAllModules(ctx)[1:] + const defaultGoVersion = "" + mods := modload.LoadModGraph(ctx, defaultGoVersion).BuildList()[1:] errsChans := make([]<-chan []error, len(mods)) for i, mod := range mods { diff --git a/libgo/go/cmd/go/internal/modcmd/why.go b/libgo/go/cmd/go/internal/modcmd/why.go index a5f3e8a..3b14b27 100644 --- a/libgo/go/cmd/go/internal/modcmd/why.go +++ b/libgo/go/cmd/go/internal/modcmd/why.go @@ -68,22 +68,25 @@ func runWhy(ctx context.Context, cmd *base.Command, args []string) { modload.RootMode = modload.NeedRoot loadOpts := modload.PackageOpts{ - Tags: imports.AnyTags(), - LoadTests: !*whyVendor, - SilenceErrors: true, - UseVendorAll: *whyVendor, + Tags: imports.AnyTags(), + VendorModulesInGOROOTSrc: true, + LoadTests: !*whyVendor, + SilencePackageErrors: true, + UseVendorAll: *whyVendor, } if *whyM { - listU := false - listVersions := false - listRetractions := false for _, arg := range args { if strings.Contains(arg, "@") { base.Fatalf("go mod why: module query not allowed") } } - mods := modload.ListModules(ctx, args, listU, listVersions, listRetractions) + + mods, err := modload.ListModules(ctx, args, 0) + if err != nil { + base.Fatalf("go mod why: %v", err) + } + byModule := make(map[module.Version][]string) _, pkgs := modload.LoadPackages(ctx, loadOpts, "all") for _, path := range pkgs { diff --git a/libgo/go/cmd/go/internal/modconv/convert.go b/libgo/go/cmd/go/internal/modconv/convert.go index 5d4165c..9c861f8 100644 --- a/libgo/go/cmd/go/internal/modconv/convert.go +++ b/libgo/go/cmd/go/internal/modconv/convert.go @@ -12,7 +12,6 @@ import ( "strings" "cmd/go/internal/base" - "cmd/go/internal/modfetch" "golang.org/x/mod/modfile" "golang.org/x/mod/module" @@ -21,7 +20,7 @@ import ( // ConvertLegacyConfig converts legacy config to modfile. // The file argument is slash-delimited. -func ConvertLegacyConfig(f *modfile.File, file string, data []byte) error { +func ConvertLegacyConfig(f *modfile.File, file string, data []byte, queryPackage func(path, rev string) (module.Version, error)) error { i := strings.LastIndex(file, "/") j := -2 if i >= 0 { @@ -62,15 +61,13 @@ func ConvertLegacyConfig(f *modfile.File, file string, data []byte) error { sem <- token{} go func(i int, m module.Version) { defer func() { <-sem }() - repo, info, err := modfetch.ImportRepoRev(m.Path, m.Version) + version, err := queryPackage(m.Path, m.Version) if err != nil { fmt.Fprintf(os.Stderr, "go: converting %s: stat %s@%s: %v\n", base.ShortPath(file), m.Path, m.Version, err) return } - path := repo.ModulePath() - versions[i].Path = path - versions[i].Version = info.Version + versions[i] = version }(i, m) } // Fill semaphore channel to wait for all tasks to finish. diff --git a/libgo/go/cmd/go/internal/modconv/convert_test.go b/libgo/go/cmd/go/internal/modconv/convert_test.go deleted file mode 100644 index 66b9ff4..0000000 --- a/libgo/go/cmd/go/internal/modconv/convert_test.go +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package modconv - -import ( - "bytes" - "context" - "fmt" - "internal/testenv" - "log" - "os" - "os/exec" - "path/filepath" - "strings" - "testing" - - "cmd/go/internal/cfg" - "cmd/go/internal/modfetch" - - "golang.org/x/mod/modfile" - "golang.org/x/mod/module" -) - -func TestMain(m *testing.M) { - os.Exit(testMain(m)) -} - -func testMain(m *testing.M) int { - cfg.GOPROXY = "direct" - - if _, err := exec.LookPath("git"); err != nil { - fmt.Fprintln(os.Stderr, "skipping because git binary not found") - fmt.Println("PASS") - return 0 - } - - dir, err := os.MkdirTemp("", "modconv-test-") - if err != nil { - log.Fatal(err) - } - defer os.RemoveAll(dir) - cfg.GOMODCACHE = filepath.Join(dir, "pkg/mod") - - return m.Run() -} - -func TestConvertLegacyConfig(t *testing.T) { - testenv.MustHaveExternalNetwork(t) - - if testing.Verbose() { - old := cfg.BuildX - defer func() { - cfg.BuildX = old - }() - cfg.BuildX = true - } - - var tests = []struct { - path string - vers string - gomod string - }{ - /* - Different versions of git seem to find or not find - github.com/Masterminds/semver's a93e51b5a57e, - which is an unmerged pull request. - We'd rather not provide access to unmerged pull requests, - so the line is removed from the golden file here, - but some git commands still find it somehow. - - { - // Gopkg.lock parsing. - "github.com/golang/dep", "v0.4.0", - `module github.com/golang/dep - - require ( - github.com/Masterminds/vcs v1.11.1 - github.com/armon/go-radix v0.0.0-20160115234725-4239b77079c7 - github.com/boltdb/bolt v1.3.1 - github.com/go-yaml/yaml v0.0.0-20170407172122-cd8b52f8269e - github.com/golang/protobuf v0.0.0-20170901042739-5afd06f9d81a - github.com/jmank88/nuts v0.3.0 - github.com/nightlyone/lockfile v0.0.0-20170707060451-e83dc5e7bba0 - github.com/pelletier/go-toml v0.0.0-20171218135716-b8b5e7696574 - github.com/pkg/errors v0.8.0 - github.com/sdboyer/constext v0.0.0-20170321163424-836a14457353 - golang.org/x/net v0.0.0-20170828231752-66aacef3dd8a - golang.org/x/sync v0.0.0-20170517211232-f52d1811a629 - golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea - )`, - }, - */ - - // TODO: https://github.com/docker/distribution uses vendor.conf - - { - // Godeps.json parsing. - // TODO: Should v2.0.0 work here too? - "github.com/docker/distribution", "v0.0.0-20150410205453-85de3967aa93", - `module github.com/docker/distribution - - require ( - github.com/AdRoll/goamz v0.0.0-20150130162828-d3664b76d905 - github.com/MSOpenTech/azure-sdk-for-go v0.0.0-20150323223030-d90753bcad2e - github.com/Sirupsen/logrus v0.7.3 - github.com/bugsnag/bugsnag-go v1.0.3-0.20141110184014-b1d153021fcd - github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b - github.com/bugsnag/panicwrap v0.0.0-20141110184334-e5f9854865b9 - github.com/codegangsta/cli v1.4.2-0.20150131031259-6086d7927ec3 - github.com/docker/docker v1.4.2-0.20150204013315-165ea5c158cf - github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 - github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7 - github.com/gorilla/context v0.0.0-20140604161150-14f550f51af5 - github.com/gorilla/handlers v0.0.0-20140825150757-0e84b7d810c1 - github.com/gorilla/mux v0.0.0-20140926153814-e444e69cbd2e - github.com/jlhawn/go-crypto v0.0.0-20150401213827-cd738dde20f0 - github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 - github.com/yvasiyarov/gorelic v0.0.7-0.20141212073537-a9bba5b9ab50 - github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f - golang.org/x/net v0.0.0-20150202051010-1dfe7915deaf - gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789 - gopkg.in/yaml.v2 v2.0.0-20150116202057-bef53efd0c76 - )`, - }, - - { - // golang.org/issue/24585 - confusion about v2.0.0 tag in legacy non-v2 module - "github.com/fishy/gcsbucket", "v0.0.0-20180217031846-618d60fe84e0", - `module github.com/fishy/gcsbucket - - require ( - cloud.google.com/go v0.18.0 - github.com/fishy/fsdb v0.0.0-20180217030800-5527ded01371 - github.com/golang/protobuf v1.0.0 - github.com/googleapis/gax-go v2.0.0+incompatible - golang.org/x/net v0.0.0-20180216171745-136a25c244d3 - golang.org/x/oauth2 v0.0.0-20180207181906-543e37812f10 - golang.org/x/text v0.3.1-0.20180208041248-4e4a3210bb54 - google.golang.org/api v0.0.0-20180217000815-c7a403bb5fe1 - google.golang.org/appengine v1.0.0 - google.golang.org/genproto v0.0.0-20180206005123-2b5a72b8730b - google.golang.org/grpc v1.10.0 - )`, - }, - } - - ctx := context.Background() - - for _, tt := range tests { - t.Run(strings.ReplaceAll(tt.path, "/", "_")+"_"+tt.vers, func(t *testing.T) { - f, err := modfile.Parse("golden", []byte(tt.gomod), nil) - if err != nil { - t.Fatal(err) - } - want, err := f.Format() - if err != nil { - t.Fatal(err) - } - - dir, err := modfetch.Download(ctx, module.Version{Path: tt.path, Version: tt.vers}) - if err != nil { - t.Fatal(err) - } - - for name := range Converters { - file := filepath.Join(dir, name) - data, err := os.ReadFile(file) - if err == nil { - f := new(modfile.File) - f.AddModuleStmt(tt.path) - if err := ConvertLegacyConfig(f, filepath.ToSlash(file), data); err != nil { - t.Fatal(err) - } - out, err := f.Format() - if err != nil { - t.Fatalf("format after conversion: %v", err) - } - if !bytes.Equal(out, want) { - t.Fatalf("final go.mod:\n%s\n\nwant:\n%s", out, want) - } - return - } - } - t.Fatalf("no converter found for %s@%s", tt.path, tt.vers) - }) - } -} diff --git a/libgo/go/cmd/go/internal/modconv/testdata/traefik.dep b/libgo/go/cmd/go/internal/modconv/testdata/traefik.dep new file mode 100644 index 0000000..8510f0f --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/traefik.dep @@ -0,0 +1,79 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + +[[projects]] + name = "github.com/Nvveen/Gotty" + packages = ["."] + revision = "a8b993ba6abdb0e0c12b0125c603323a71c7790c" + source = "github.com/ijc25/Gotty" + +[[projects]] + branch = "master" + name = "github.com/OpenDNS/vegadns2client" + packages = ["."] + revision = "a3fa4a771d87bda2514a90a157e1fed1b6897d2e" + +[[projects]] + name = "github.com/PuerkitoBio/purell" + packages = ["."] + revision = "8a290539e2e8629dbc4e6bad948158f790ec31f4" + version = "v1.0.0" + +[[projects]] + name = "github.com/PuerkitoBio/urlesc" + packages = ["."] + revision = "5bd2802263f21d8788851d5305584c82a5c75d7e" + +[[projects]] + name = "github.com/Shopify/sarama" + packages = ["."] + revision = "70f6a705d4a17af059acbc6946fb2bd30762acd7" + +[[projects]] + name = "github.com/VividCortex/gohistogram" + packages = ["."] + revision = "51564d9861991fb0ad0f531c99ef602d0f9866e6" + version = "v1.0.0" + +[[projects]] + branch = "containous-fork" + name = "github.com/abbot/go-http-auth" + packages = ["."] + revision = "65b0cdae8d7fe5c05c7430e055938ef6d24a66c9" + source = "github.com/containous/go-http-auth" + +[[projects]] + branch = "master" + name = "github.com/abronan/valkeyrie" + packages = [ + ".", + "store", + "store/boltdb", + "store/consul", + "store/etcd/v2", + "store/etcd/v3", + "store/zookeeper" + ] + revision = "063d875e3c5fd734fa2aa12fac83829f62acfc70" + +[[projects]] + branch = "master" + name = "github.com/mesosphere/mesos-dns" + packages = [ + "detect", + "errorutil", + "logging", + "models", + "records", + "records/labels", + "records/state", + "util" + ] + revision = "b47dc4c19f215e98da687b15b4c64e70f629bea5" + source = "git@github.com:containous/mesos-dns.git" + + [[projects]] + name = "gopkg.in/fsnotify.v1" + packages = ["."] + revision = "629574ca2a5df945712d3079857300b5e4da0236" + source = "github.com/fsnotify/fsnotify" + version = "v1.4.2"
\ No newline at end of file diff --git a/libgo/go/cmd/go/internal/modconv/testdata/traefik.out b/libgo/go/cmd/go/internal/modconv/testdata/traefik.out new file mode 100644 index 0000000..5054295 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/traefik.out @@ -0,0 +1,14 @@ +github.com/Nvveen/Gotty a8b993ba6abdb0e0c12b0125c603323a71c7790c +github.com/OpenDNS/vegadns2client a3fa4a771d87bda2514a90a157e1fed1b6897d2e +github.com/PuerkitoBio/purell v1.0.0 +github.com/PuerkitoBio/urlesc 5bd2802263f21d8788851d5305584c82a5c75d7e +github.com/Shopify/sarama 70f6a705d4a17af059acbc6946fb2bd30762acd7 +github.com/VividCortex/gohistogram v1.0.0 +github.com/abbot/go-http-auth 65b0cdae8d7fe5c05c7430e055938ef6d24a66c9 +github.com/abronan/valkeyrie 063d875e3c5fd734fa2aa12fac83829f62acfc70 +github.com/mesosphere/mesos-dns b47dc4c19f215e98da687b15b4c64e70f629bea5 +gopkg.in/fsnotify.v1 v1.4.2 +replace: github.com/Nvveen/Gotty a8b993ba6abdb0e0c12b0125c603323a71c7790c github.com/ijc25/Gotty a8b993ba6abdb0e0c12b0125c603323a71c7790c +replace: github.com/abbot/go-http-auth 65b0cdae8d7fe5c05c7430e055938ef6d24a66c9 github.com/containous/go-http-auth 65b0cdae8d7fe5c05c7430e055938ef6d24a66c9 +replace: github.com/mesosphere/mesos-dns b47dc4c19f215e98da687b15b4c64e70f629bea5 github.com/containous/mesos-dns b47dc4c19f215e98da687b15b4c64e70f629bea5 +replace: gopkg.in/fsnotify.v1 v1.4.2 github.com/fsnotify/fsnotify v1.4.2 diff --git a/libgo/go/cmd/go/internal/modfetch/bootstrap.go b/libgo/go/cmd/go/internal/modfetch/bootstrap.go index e4020b0..ed69458 100644 --- a/libgo/go/cmd/go/internal/modfetch/bootstrap.go +++ b/libgo/go/cmd/go/internal/modfetch/bootstrap.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cmd_go_bootstrap // +build cmd_go_bootstrap package modfetch diff --git a/libgo/go/cmd/go/internal/modfetch/cache.go b/libgo/go/cmd/go/internal/modfetch/cache.go index 07e046c8..b01b467 100644 --- a/libgo/go/cmd/go/internal/modfetch/cache.go +++ b/libgo/go/cmd/go/internal/modfetch/cache.go @@ -11,8 +11,10 @@ import ( "fmt" "io" "io/fs" + "math/rand" "os" "path/filepath" + "strconv" "strings" "sync" @@ -21,17 +23,15 @@ import ( "cmd/go/internal/lockedfile" "cmd/go/internal/modfetch/codehost" "cmd/go/internal/par" - "cmd/go/internal/renameio" + "cmd/go/internal/robustio" "golang.org/x/mod/module" "golang.org/x/mod/semver" ) func cacheDir(path string) (string, error) { - if cfg.GOMODCACHE == "" { - // modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE - // is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen. - return "", fmt.Errorf("internal error: cfg.GOMODCACHE not set") + if err := checkCacheDir(); err != nil { + return "", err } enc, err := module.EscapePath(path) if err != nil { @@ -64,10 +64,8 @@ func CachePath(m module.Version, suffix string) (string, error) { // along with the directory if the directory does not exist or if the directory // is not completely populated. func DownloadDir(m module.Version) (string, error) { - if cfg.GOMODCACHE == "" { - // modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE - // is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen. - return "", fmt.Errorf("internal error: cfg.GOMODCACHE not set") + if err := checkCacheDir(); err != nil { + return "", err } enc, err := module.EscapePath(m.Path) if err != nil { @@ -108,7 +106,9 @@ func DownloadDir(m module.Version) (string, error) { // Check if a .ziphash file exists. It should be created before the // zip is extracted, but if it was deleted (by another program?), we need - // to re-calculate it. + // to re-calculate it. Note that checkMod will repopulate the ziphash + // file if it doesn't exist, but if the module is excluded by checks + // through GONOSUMDB or GOPRIVATE, that check and repopulation won't happen. ziphashPath, err := CachePath(m, "ziphash") if err != nil { return dir, err @@ -146,15 +146,13 @@ func lockVersion(mod module.Version) (unlock func(), err error) { return lockedfile.MutexAt(path).Lock() } -// SideLock locks a file within the module cache that that previously guarded +// SideLock locks a file within the module cache that previously guarded // edits to files outside the cache, such as go.sum and go.mod files in the // user's working directory. // If err is nil, the caller MUST eventually call the unlock function. func SideLock() (unlock func(), err error) { - if cfg.GOMODCACHE == "" { - // modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE - // is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen. - base.Fatalf("go: internal error: cfg.GOMODCACHE not set") + if err := checkCacheDir(); err != nil { + return nil, err } path := filepath.Join(cfg.GOMODCACHE, "cache", "lock") @@ -332,7 +330,7 @@ func InfoFile(path, version string) (string, error) { } // Stat should have populated the disk cache for us. - file, _, err := readDiskStat(path, version) + file, err := CachePath(module.Version{Path: path, Version: version}, "info") if err != nil { return "", err } @@ -349,6 +347,9 @@ func GoMod(path, rev string) ([]byte, error) { if _, info, err := readDiskStat(path, rev); err == nil { rev = info.Version } else { + if errors.Is(err, statCacheErr) { + return nil, err + } err := TryProxies(func(proxy string) error { info, err := Lookup(proxy, path).Stat(rev) if err == nil { @@ -384,7 +385,7 @@ func GoModFile(path, version string) (string, error) { return "", err } // GoMod should have populated the disk cache for us. - file, _, err := readDiskGoMod(path, version) + file, err := CachePath(module.Version{Path: path, Version: version}, "mod") if err != nil { return "", err } @@ -499,7 +500,7 @@ func readDiskStatByHash(path, rev string) (file string, info *RevInfo, err error for _, name := range names { if strings.HasSuffix(name, suffix) { v := strings.TrimSuffix(name, ".info") - if IsPseudoVersion(v) && semver.Compare(v, maxVersion) > 0 { + if module.IsPseudoVersion(v) && semver.Compare(v, maxVersion) > 0 { maxVersion = v file, info, err = readDiskStat(path, strings.TrimSuffix(name, ".info")) } @@ -547,7 +548,7 @@ func readDiskCache(path, rev, suffix string) (file string, data []byte, err erro if err != nil { return "", nil, errNotCached } - data, err = renameio.ReadFile(file) + data, err = robustio.ReadFile(file) if err != nil { return file, nil, errNotCached } @@ -584,7 +585,29 @@ func writeDiskCache(file string, data []byte) error { return err } - if err := renameio.WriteFile(file, data, 0666); err != nil { + // Write the file to a temporary location, and then rename it to its final + // path to reduce the likelihood of a corrupt file existing at that final path. + f, err := tempFile(filepath.Dir(file), filepath.Base(file), 0666) + if err != nil { + return err + } + defer func() { + // Only call os.Remove on f.Name() if we failed to rename it: otherwise, + // some other process may have created a new file with the same name after + // the rename completed. + if err != nil { + f.Close() + os.Remove(f.Name()) + } + }() + + if _, err := f.Write(data); err != nil { + return err + } + if err := f.Close(); err != nil { + return err + } + if err := robustio.Rename(f.Name(), file); err != nil { return err } @@ -594,29 +617,49 @@ func writeDiskCache(file string, data []byte) error { return nil } +// tempFile creates a new temporary file with given permission bits. +func tempFile(dir, prefix string, perm fs.FileMode) (f *os.File, err error) { + for i := 0; i < 10000; i++ { + name := filepath.Join(dir, prefix+strconv.Itoa(rand.Intn(1000000000))+".tmp") + f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, perm) + if os.IsExist(err) { + continue + } + break + } + return +} + // rewriteVersionList rewrites the version list in dir // after a new *.mod file has been written. -func rewriteVersionList(dir string) { +func rewriteVersionList(dir string) (err error) { if filepath.Base(dir) != "@v" { base.Fatalf("go: internal error: misuse of rewriteVersionList") } listFile := filepath.Join(dir, "list") - // We use a separate lockfile here instead of locking listFile itself because - // we want to use Rename to write the file atomically. The list may be read by - // a GOPROXY HTTP server, and if we crash midway through a rewrite (or if the - // HTTP server ignores our locking and serves the file midway through a - // rewrite) it's better to serve a stale list than a truncated one. - unlock, err := lockedfile.MutexAt(listFile + ".lock").Lock() + // Lock listfile when writing to it to try to avoid corruption to the file. + // Under rare circumstances, for instance, if the system loses power in the + // middle of a write it is possible for corrupt data to be written. This is + // not a problem for the go command itself, but may be an issue if the the + // cache is being served by a GOPROXY HTTP server. This will be corrected + // the next time a new version of the module is fetched and the file is rewritten. + // TODO(matloob): golang.org/issue/43313 covers adding a go mod verify + // command that removes module versions that fail checksums. It should also + // remove list files that are detected to be corrupt. + f, err := lockedfile.Edit(listFile) if err != nil { - base.Fatalf("go: can't lock version list lockfile: %v", err) + return err } - defer unlock() - + defer func() { + if cerr := f.Close(); cerr != nil && err == nil { + err = cerr + } + }() infos, err := os.ReadDir(dir) if err != nil { - return + return err } var list []string for _, info := range infos { @@ -634,19 +677,74 @@ func rewriteVersionList(dir string) { } } } - SortVersions(list) + semver.Sort(list) var buf bytes.Buffer for _, v := range list { buf.WriteString(v) buf.WriteString("\n") } - old, _ := renameio.ReadFile(listFile) - if bytes.Equal(buf.Bytes(), old) { - return + if fi, err := f.Stat(); err == nil && int(fi.Size()) == buf.Len() { + old := make([]byte, buf.Len()+1) + if n, err := f.ReadAt(old, 0); err == io.EOF && n == buf.Len() && bytes.Equal(buf.Bytes(), old) { + return nil // No edit needed. + } + } + // Remove existing contents, so that when we truncate to the actual size it will zero-fill, + // and we will be able to detect (some) incomplete writes as files containing trailing NUL bytes. + if err := f.Truncate(0); err != nil { + return err + } + // Reserve the final size and zero-fill. + if err := f.Truncate(int64(buf.Len())); err != nil { + return err + } + // Write the actual contents. If this fails partway through, + // the remainder of the file should remain as zeroes. + if _, err := f.Write(buf.Bytes()); err != nil { + f.Truncate(0) + return err } - if err := renameio.WriteFile(listFile, buf.Bytes(), 0666); err != nil { - base.Fatalf("go: failed to write version list: %v", err) + return nil +} + +var ( + statCacheOnce sync.Once + statCacheErr error +) + +// checkCacheDir checks if the directory specified by GOMODCACHE exists. An +// error is returned if it does not. +func checkCacheDir() error { + if cfg.GOMODCACHE == "" { + // modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE + // is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen. + return fmt.Errorf("internal error: cfg.GOMODCACHE not set") + } + if !filepath.IsAbs(cfg.GOMODCACHE) { + return fmt.Errorf("GOMODCACHE entry is relative; must be absolute path: %q.\n", cfg.GOMODCACHE) } + + // os.Stat is slow on Windows, so we only call it once to prevent unnecessary + // I/O every time this function is called. + statCacheOnce.Do(func() { + fi, err := os.Stat(cfg.GOMODCACHE) + if err != nil { + if !os.IsNotExist(err) { + statCacheErr = fmt.Errorf("could not create module cache: %w", err) + return + } + if err := os.MkdirAll(cfg.GOMODCACHE, 0777); err != nil { + statCacheErr = fmt.Errorf("could not create module cache: %w", err) + return + } + return + } + if !fi.IsDir() { + statCacheErr = fmt.Errorf("could not create module cache: %q is not a directory", cfg.GOMODCACHE) + return + } + }) + return statCacheErr } diff --git a/libgo/go/cmd/go/internal/modfetch/codehost/git.go b/libgo/go/cmd/go/internal/modfetch/codehost/git.go index 72005e2..4d4964e 100644 --- a/libgo/go/cmd/go/internal/modfetch/codehost/git.go +++ b/libgo/go/cmd/go/internal/modfetch/codehost/git.go @@ -296,6 +296,9 @@ func (r *gitRepo) stat(rev string) (*RevInfo, error) { // Or maybe it's the prefix of a hash of a named ref. // Try to resolve to both a ref (git name) and full (40-hex-digit) commit hash. r.refsOnce.Do(r.loadRefs) + // loadRefs may return an error if git fails, for example segfaults, or + // could not load a private repo, but defer checking to the else block + // below, in case we already have the rev in question in the local cache. var ref, hash string if r.refs["refs/tags/"+rev] != "" { ref = "refs/tags/" + rev @@ -332,6 +335,9 @@ func (r *gitRepo) stat(rev string) (*RevInfo, error) { hash = rev } } else { + if r.refsErr != nil { + return nil, r.refsErr + } return nil, &UnknownRevisionError{Rev: rev} } diff --git a/libgo/go/cmd/go/internal/modfetch/codehost/git_test.go b/libgo/go/cmd/go/internal/modfetch/codehost/git_test.go index 89a73ba..a684fa1 100644 --- a/libgo/go/cmd/go/internal/modfetch/codehost/git_test.go +++ b/libgo/go/cmd/go/internal/modfetch/codehost/git_test.go @@ -8,7 +8,6 @@ import ( "archive/zip" "bytes" "flag" - "fmt" "internal/testenv" "io" "io/fs" @@ -47,12 +46,6 @@ var altRepos = []string{ var localGitRepo string func testMain(m *testing.M) int { - if _, err := exec.LookPath("git"); err != nil { - fmt.Fprintln(os.Stderr, "skipping because git binary not found") - fmt.Println("PASS") - return 0 - } - dir, err := os.MkdirTemp("", "gitrepo-test-") if err != nil { log.Fatal(err) @@ -60,23 +53,25 @@ func testMain(m *testing.M) int { defer os.RemoveAll(dir) if testenv.HasExternalNetwork() && testenv.HasExec() { - // Clone gitrepo1 into a local directory. - // If we use a file:// URL to access the local directory, - // then git starts up all the usual protocol machinery, - // which will let us test remote git archive invocations. - localGitRepo = filepath.Join(dir, "gitrepo2") - if _, err := Run("", "git", "clone", "--mirror", gitrepo1, localGitRepo); err != nil { - log.Fatal(err) - } - if _, err := Run(localGitRepo, "git", "config", "daemon.uploadarch", "true"); err != nil { - log.Fatal(err) + if _, err := exec.LookPath("git"); err == nil { + // Clone gitrepo1 into a local directory. + // If we use a file:// URL to access the local directory, + // then git starts up all the usual protocol machinery, + // which will let us test remote git archive invocations. + localGitRepo = filepath.Join(dir, "gitrepo2") + if _, err := Run("", "git", "clone", "--mirror", gitrepo1, localGitRepo); err != nil { + log.Fatal(err) + } + if _, err := Run(localGitRepo, "git", "config", "daemon.uploadarch", "true"); err != nil { + log.Fatal(err) + } } } return m.Run() } -func testRepo(remote string) (Repo, error) { +func testRepo(t *testing.T, remote string) (Repo, error) { if remote == "localGitRepo" { // Convert absolute path to file URL. LocalGitRepo will not accept // Windows absolute paths because they look like a host:path remote. @@ -87,15 +82,17 @@ func testRepo(remote string) (Repo, error) { } else { url = "file:///" + filepath.ToSlash(localGitRepo) } + testenv.MustHaveExecPath(t, "git") return LocalGitRepo(url) } - kind := "git" + vcs := "git" for _, k := range []string{"hg"} { if strings.Contains(remote, "/"+k+"/") { - kind = k + vcs = k } } - return NewRepo(kind, remote) + testenv.MustHaveExecPath(t, vcs) + return NewRepo(vcs, remote) } var tagsTests = []struct { @@ -116,7 +113,7 @@ func TestTags(t *testing.T) { for _, tt := range tagsTests { f := func(t *testing.T) { - r, err := testRepo(tt.repo) + r, err := testRepo(t, tt.repo) if err != nil { t.Fatal(err) } @@ -168,7 +165,7 @@ func TestLatest(t *testing.T) { for _, tt := range latestTests { f := func(t *testing.T) { - r, err := testRepo(tt.repo) + r, err := testRepo(t, tt.repo) if err != nil { t.Fatal(err) } @@ -221,7 +218,7 @@ func TestReadFile(t *testing.T) { for _, tt := range readFileTests { f := func(t *testing.T) { - r, err := testRepo(tt.repo) + r, err := testRepo(t, tt.repo) if err != nil { t.Fatal(err) } @@ -412,7 +409,7 @@ func TestReadZip(t *testing.T) { for _, tt := range readZipTests { f := func(t *testing.T) { - r, err := testRepo(tt.repo) + r, err := testRepo(t, tt.repo) if err != nil { t.Fatal(err) } @@ -581,7 +578,7 @@ func TestStat(t *testing.T) { for _, tt := range statTests { f := func(t *testing.T) { - r, err := testRepo(tt.repo) + r, err := testRepo(t, tt.repo) if err != nil { t.Fatal(err) } diff --git a/libgo/go/cmd/go/internal/modfetch/codehost/shell.go b/libgo/go/cmd/go/internal/modfetch/codehost/shell.go index ce8b501..0e9f381 100644 --- a/libgo/go/cmd/go/internal/modfetch/codehost/shell.go +++ b/libgo/go/cmd/go/internal/modfetch/codehost/shell.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // Interactive debugging shell for codehost.Repo implementations. diff --git a/libgo/go/cmd/go/internal/modfetch/coderepo.go b/libgo/go/cmd/go/internal/modfetch/coderepo.go index 2dcbb99..dfef9f7 100644 --- a/libgo/go/cmd/go/internal/modfetch/coderepo.go +++ b/libgo/go/cmd/go/internal/modfetch/coderepo.go @@ -159,7 +159,7 @@ func (r *codeRepo) Versions(prefix string) ([]string, error) { if r.codeDir != "" { v = v[len(r.codeDir)+1:] } - if v == "" || v != module.CanonicalVersion(v) || IsPseudoVersion(v) { + if v == "" || v != module.CanonicalVersion(v) || module.IsPseudoVersion(v) { continue } @@ -172,8 +172,8 @@ func (r *codeRepo) Versions(prefix string) ([]string, error) { list = append(list, v) } - SortVersions(list) - SortVersions(incompatible) + semver.Sort(list) + semver.Sort(incompatible) return r.appendIncompatibleVersions(list, incompatible) } @@ -385,7 +385,7 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e if statVers != "" && statVers == module.CanonicalVersion(statVers) { info2.Version = statVers - if IsPseudoVersion(info2.Version) { + if module.IsPseudoVersion(info2.Version) { if err := r.validatePseudoVersion(info, info2.Version); err != nil { return nil, err } @@ -433,7 +433,7 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e } trimmed := tag[len(tagPrefix):] // Tags that look like pseudo-versions would be confusing. Ignore them. - if IsPseudoVersion(tag) { + if module.IsPseudoVersion(tag) { return "", false } @@ -531,7 +531,7 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e pseudoBase, _ = tagToVersion(tag) // empty if the tag is invalid } - info2.Version = PseudoVersion(r.pseudoMajor, pseudoBase, info.Time, info.Short) + info2.Version = module.PseudoVersion(r.pseudoMajor, pseudoBase, info.Time, info.Short) return checkGoMod() } @@ -560,7 +560,7 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string) return err } - rev, err := PseudoVersionRev(version) + rev, err := module.PseudoVersionRev(version) if err != nil { return err } @@ -575,12 +575,12 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string) } } - t, err := PseudoVersionTime(version) + t, err := module.PseudoVersionTime(version) if err != nil { return err } if !t.Equal(info.Time.Truncate(time.Second)) { - return fmt.Errorf("does not match version-control timestamp (expected %s)", info.Time.UTC().Format(pseudoVersionTimestampFormat)) + return fmt.Errorf("does not match version-control timestamp (expected %s)", info.Time.UTC().Format(module.PseudoVersionTimestampFormat)) } tagPrefix := "" @@ -604,7 +604,7 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string) // not enforce that property when resolving existing pseudo-versions: we don't // know when the parent tags were added, and the highest-tagged parent may not // have existed when the pseudo-version was first resolved. - base, err := PseudoVersionBase(strings.TrimSuffix(version, "+incompatible")) + base, err := module.PseudoVersionBase(strings.TrimSuffix(version, "+incompatible")) if err != nil { return err } @@ -661,7 +661,7 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string) if err != nil { return err } - rev, err := PseudoVersionRev(version) + rev, err := module.PseudoVersionRev(version) if err != nil { return fmt.Errorf("not a descendent of preceding tag (%s)", lastTag) } @@ -672,8 +672,8 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string) func (r *codeRepo) revToRev(rev string) string { if semver.IsValid(rev) { - if IsPseudoVersion(rev) { - r, _ := PseudoVersionRev(rev) + if module.IsPseudoVersion(rev) { + r, _ := module.PseudoVersionRev(rev) return r } if semver.Build(rev) == "+incompatible" { @@ -843,7 +843,7 @@ func (r *codeRepo) GoMod(version string) (data []byte, err error) { return nil, fmt.Errorf("version %s is not canonical", version) } - if IsPseudoVersion(version) { + if module.IsPseudoVersion(version) { // findDir ignores the metadata encoded in a pseudo-version, // only using the revision at the end. // Invoke Stat to verify the metadata explicitly so we don't return @@ -864,22 +864,25 @@ func (r *codeRepo) GoMod(version string) (data []byte, err error) { data, err = r.code.ReadFile(rev, path.Join(dir, "go.mod"), codehost.MaxGoMod) if err != nil { if os.IsNotExist(err) { - return r.legacyGoMod(rev, dir), nil + return LegacyGoMod(r.modPath), nil } return nil, err } return data, nil } -func (r *codeRepo) legacyGoMod(rev, dir string) []byte { - // We used to try to build a go.mod reflecting pre-existing - // package management metadata files, but the conversion - // was inherently imperfect (because those files don't have - // exactly the same semantics as go.mod) and, when done - // for dependencies in the middle of a build, impossible to - // correct. So we stopped. - // Return a fake go.mod that simply declares the module path. - return []byte(fmt.Sprintf("module %s\n", modfile.AutoQuote(r.modPath))) +// LegacyGoMod generates a fake go.mod file for a module that doesn't have one. +// The go.mod file contains a module directive and nothing else: no go version, +// no requirements. +// +// We used to try to build a go.mod reflecting pre-existing +// package management metadata files, but the conversion +// was inherently imperfect (because those files don't have +// exactly the same semantics as go.mod) and, when done +// for dependencies in the middle of a build, impossible to +// correct. So we stopped. +func LegacyGoMod(modPath string) []byte { + return []byte(fmt.Sprintf("module %s\n", modfile.AutoQuote(modPath))) } func (r *codeRepo) modPrefix(rev string) string { @@ -942,7 +945,7 @@ func (r *codeRepo) Zip(dst io.Writer, version string) error { return fmt.Errorf("version %s is not canonical", version) } - if IsPseudoVersion(version) { + if module.IsPseudoVersion(version) { // findDir ignores the metadata encoded in a pseudo-version, // only using the revision at the end. // Invoke Stat to verify the metadata explicitly so we don't return diff --git a/libgo/go/cmd/go/internal/modfetch/fetch.go b/libgo/go/cmd/go/internal/modfetch/fetch.go index eb7d30e..d3d30d9 100644 --- a/libgo/go/cmd/go/internal/modfetch/fetch.go +++ b/libgo/go/cmd/go/internal/modfetch/fetch.go @@ -8,6 +8,8 @@ import ( "archive/zip" "bytes" "context" + "crypto/sha256" + "encoding/base64" "errors" "fmt" "io" @@ -20,9 +22,9 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" + "cmd/go/internal/fsys" "cmd/go/internal/lockedfile" "cmd/go/internal/par" - "cmd/go/internal/renameio" "cmd/go/internal/robustio" "cmd/go/internal/trace" @@ -37,10 +39,8 @@ var downloadCache par.Cache // local download cache and returns the name of the directory // corresponding to the root of the module's file tree. func Download(ctx context.Context, mod module.Version) (dir string, err error) { - if cfg.GOMODCACHE == "" { - // modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE - // is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen. - base.Fatalf("go: internal error: cfg.GOMODCACHE not set") + if err := checkCacheDir(); err != nil { + base.Fatalf("go: %v", err) } // The par.Cache here avoids duplicate work. @@ -223,11 +223,10 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e // Clean up any remaining tempfiles from previous runs. // This is only safe to do because the lock file ensures that their // writers are no longer active. - for _, base := range []string{zipfile, zipfile + "hash"} { - if old, err := filepath.Glob(renameio.Pattern(base)); err == nil { - for _, path := range old { - os.Remove(path) // best effort - } + tmpPattern := filepath.Base(zipfile) + "*.tmp" + if old, err := filepath.Glob(filepath.Join(filepath.Dir(zipfile), tmpPattern)); err == nil { + for _, path := range old { + os.Remove(path) // best effort } } @@ -242,7 +241,7 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e // contents of the file (by hashing it) before we commit it. Because the file // is zip-compressed, we need an actual file — or at least an io.ReaderAt — to // validate it: we can't just tee the stream as we write it. - f, err := os.CreateTemp(filepath.Dir(zipfile), filepath.Base(renameio.Pattern(zipfile))) + f, err := os.CreateTemp(filepath.Dir(zipfile), tmpPattern) if err != nil { return err } @@ -298,12 +297,6 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e } } - // Sync the file before renaming it: otherwise, after a crash the reader may - // observe a 0-length file instead of the actual contents. - // See https://golang.org/issue/22397#issuecomment-380831736. - if err := f.Sync(); err != nil { - return err - } if err := f.Close(); err != nil { return err } @@ -334,7 +327,21 @@ func hashZip(mod module.Version, zipfile, ziphashfile string) error { if err := checkModSum(mod, hash); err != nil { return err } - return renameio.WriteFile(ziphashfile, []byte(hash), 0666) + hf, err := lockedfile.Create(ziphashfile) + if err != nil { + return err + } + if err := hf.Truncate(int64(len(hash))); err != nil { + return err + } + if _, err := hf.WriteAt([]byte(hash), 0); err != nil { + return err + } + if err := hf.Close(); err != nil { + return err + } + + return nil } // makeDirsReadOnly makes a best-effort attempt to remove write permissions for dir @@ -410,7 +417,18 @@ func initGoSum() (bool, error) { goSum.m = make(map[module.Version][]string) goSum.status = make(map[modSum]modSumStatus) - data, err := lockedfile.Read(GoSumFile) + var ( + data []byte + err error + ) + if actualSumFile, ok := fsys.OverlayPath(GoSumFile); ok { + // Don't lock go.sum if it's part of the overlay. + // On Plan 9, locking requires chmod, and we don't want to modify any file + // in the overlay. See #44700. + data, err = os.ReadFile(actualSumFile) + } else { + data, err = lockedfile.Read(GoSumFile) + } if err != nil && !os.IsNotExist(err) { return false, err } @@ -485,11 +503,24 @@ func checkMod(mod module.Version) { if err != nil { base.Fatalf("verifying %v", module.VersionError(mod, err)) } - data, err := renameio.ReadFile(ziphash) + data, err := lockedfile.Read(ziphash) if err != nil { base.Fatalf("verifying %v", module.VersionError(mod, err)) } - h := strings.TrimSpace(string(data)) + data = bytes.TrimSpace(data) + if !isValidSum(data) { + // Recreate ziphash file from zip file and use that to check the mod sum. + zip, err := CachePath(mod, "zip") + if err != nil { + base.Fatalf("verifying %v", module.VersionError(mod, err)) + } + err = hashZip(mod, zip, ziphash) + if err != nil { + base.Fatalf("verifying %v", module.VersionError(mod, err)) + } + return + } + h := string(data) if !strings.HasPrefix(h, "h1:") { base.Fatalf("verifying %v", module.VersionError(mod, fmt.Errorf("unexpected ziphash: %q", h))) } @@ -634,11 +665,32 @@ func Sum(mod module.Version) string { if err != nil { return "" } - data, err := renameio.ReadFile(ziphash) + data, err := lockedfile.Read(ziphash) if err != nil { return "" } - return strings.TrimSpace(string(data)) + data = bytes.TrimSpace(data) + if !isValidSum(data) { + return "" + } + return string(data) +} + +// isValidSum returns true if data is the valid contents of a zip hash file. +// Certain critical files are written to disk by first truncating +// then writing the actual bytes, so that if the write fails +// the corrupt file should contain at least one of the null +// bytes written by the truncate operation. +func isValidSum(data []byte) bool { + if bytes.IndexByte(data, '\000') >= 0 { + return false + } + + if len(data) != len("h1:")+base64.StdEncoding.EncodedLen(sha256.Size) { + return false + } + + return true } // WriteGoSum writes the go.sum file if it needs to be updated. @@ -676,6 +728,9 @@ Outer: if cfg.BuildMod == "readonly" { base.Fatalf("go: updates to go.sum needed, disabled by -mod=readonly") } + if _, ok := fsys.OverlayPath(GoSumFile); ok { + base.Fatalf("go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay") + } // Make a best-effort attempt to acquire the side lock, only to exclude // previous versions of the 'go' command from making simultaneous edits. diff --git a/libgo/go/cmd/go/internal/modfetch/insecure.go b/libgo/go/cmd/go/internal/modfetch/insecure.go deleted file mode 100644 index 012d05f..0000000 --- a/libgo/go/cmd/go/internal/modfetch/insecure.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package modfetch - -import ( - "cmd/go/internal/cfg" - - "golang.org/x/mod/module" -) - -// allowInsecure reports whether we are allowed to fetch this path in an insecure manner. -func allowInsecure(path string) bool { - return cfg.Insecure || module.MatchPrefixPatterns(cfg.GOINSECURE, path) -} diff --git a/libgo/go/cmd/go/internal/modfetch/proxy.go b/libgo/go/cmd/go/internal/modfetch/proxy.go index 6c86d8d..31d453c 100644 --- a/libgo/go/cmd/go/internal/modfetch/proxy.go +++ b/libgo/go/cmd/go/internal/modfetch/proxy.go @@ -228,7 +228,7 @@ func (p *proxyRepo) versionError(version string, err error) error { Path: p.path, Err: &module.InvalidVersionError{ Version: version, - Pseudo: IsPseudoVersion(version), + Pseudo: module.IsPseudoVersion(version), Err: err, }, } @@ -276,11 +276,11 @@ func (p *proxyRepo) Versions(prefix string) ([]string, error) { var list []string for _, line := range strings.Split(string(data), "\n") { f := strings.Fields(line) - if len(f) >= 1 && semver.IsValid(f[0]) && strings.HasPrefix(f[0], prefix) && !IsPseudoVersion(f[0]) { + if len(f) >= 1 && semver.IsValid(f[0]) && strings.HasPrefix(f[0], prefix) && !module.IsPseudoVersion(f[0]) { list = append(list, f[0]) } } - SortVersions(list) + semver.Sort(list) return list, nil } @@ -307,8 +307,8 @@ func (p *proxyRepo) latest() (*RevInfo, error) { ) if len(f) >= 2 { ft, _ = time.Parse(time.RFC3339, f[1]) - } else if IsPseudoVersion(f[0]) { - ft, _ = PseudoVersionTime(f[0]) + } else if module.IsPseudoVersion(f[0]) { + ft, _ = module.PseudoVersionTime(f[0]) ftIsFromPseudo = true } else { // Repo.Latest promises that this method is only called where there are diff --git a/libgo/go/cmd/go/internal/modfetch/pseudo_test.go b/libgo/go/cmd/go/internal/modfetch/pseudo_test.go deleted file mode 100644 index 4483f8e..0000000 --- a/libgo/go/cmd/go/internal/modfetch/pseudo_test.go +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package modfetch - -import ( - "testing" - "time" -) - -var pseudoTests = []struct { - major string - older string - version string -}{ - {"", "", "v0.0.0-20060102150405-hash"}, - {"v0", "", "v0.0.0-20060102150405-hash"}, - {"v1", "", "v1.0.0-20060102150405-hash"}, - {"v2", "", "v2.0.0-20060102150405-hash"}, - {"unused", "v0.0.0", "v0.0.1-0.20060102150405-hash"}, - {"unused", "v1.2.3", "v1.2.4-0.20060102150405-hash"}, - {"unused", "v1.2.99999999999999999", "v1.2.100000000000000000-0.20060102150405-hash"}, - {"unused", "v1.2.3-pre", "v1.2.3-pre.0.20060102150405-hash"}, - {"unused", "v1.3.0-pre", "v1.3.0-pre.0.20060102150405-hash"}, - {"unused", "v0.0.0--", "v0.0.0--.0.20060102150405-hash"}, - {"unused", "v1.0.0+metadata", "v1.0.1-0.20060102150405-hash+metadata"}, - {"unused", "v2.0.0+incompatible", "v2.0.1-0.20060102150405-hash+incompatible"}, - {"unused", "v2.3.0-pre+incompatible", "v2.3.0-pre.0.20060102150405-hash+incompatible"}, -} - -var pseudoTime = time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC) - -func TestPseudoVersion(t *testing.T) { - for _, tt := range pseudoTests { - v := PseudoVersion(tt.major, tt.older, pseudoTime, "hash") - if v != tt.version { - t.Errorf("PseudoVersion(%q, %q, ...) = %v, want %v", tt.major, tt.older, v, tt.version) - } - } -} - -func TestIsPseudoVersion(t *testing.T) { - for _, tt := range pseudoTests { - if !IsPseudoVersion(tt.version) { - t.Errorf("IsPseudoVersion(%q) = false, want true", tt.version) - } - if IsPseudoVersion(tt.older) { - t.Errorf("IsPseudoVersion(%q) = true, want false", tt.older) - } - } -} - -func TestPseudoVersionTime(t *testing.T) { - for _, tt := range pseudoTests { - tm, err := PseudoVersionTime(tt.version) - if tm != pseudoTime || err != nil { - t.Errorf("PseudoVersionTime(%q) = %v, %v, want %v, nil", tt.version, tm.Format(time.RFC3339), err, pseudoTime.Format(time.RFC3339)) - } - tm, err = PseudoVersionTime(tt.older) - if tm != (time.Time{}) || err == nil { - t.Errorf("PseudoVersionTime(%q) = %v, %v, want %v, error", tt.older, tm.Format(time.RFC3339), err, time.Time{}.Format(time.RFC3339)) - } - } -} - -func TestInvalidPseudoVersionTime(t *testing.T) { - const v = "---" - if _, err := PseudoVersionTime(v); err == nil { - t.Error("expected error, got nil instead") - } -} - -func TestPseudoVersionRev(t *testing.T) { - for _, tt := range pseudoTests { - rev, err := PseudoVersionRev(tt.version) - if rev != "hash" || err != nil { - t.Errorf("PseudoVersionRev(%q) = %q, %v, want %q, nil", tt.older, rev, err, "hash") - } - rev, err = PseudoVersionRev(tt.older) - if rev != "" || err == nil { - t.Errorf("PseudoVersionRev(%q) = %q, %v, want %q, error", tt.older, rev, err, "") - } - } -} - -func TestPseudoVersionBase(t *testing.T) { - for _, tt := range pseudoTests { - base, err := PseudoVersionBase(tt.version) - if err != nil { - t.Errorf("PseudoVersionBase(%q): %v", tt.version, err) - } else if base != tt.older { - t.Errorf("PseudoVersionBase(%q) = %q; want %q", tt.version, base, tt.older) - } - } -} - -func TestInvalidPseudoVersionBase(t *testing.T) { - for _, in := range []string{ - "v0.0.0", - "v0.0.0-", // malformed: empty prerelease - "v0.0.0-0.20060102150405-hash", // Z+1 == 0 - "v0.1.0-0.20060102150405-hash", // Z+1 == 0 - "v1.0.0-0.20060102150405-hash", // Z+1 == 0 - "v0.0.0-20060102150405-hash+incompatible", // "+incompatible without base version - "v0.0.0-20060102150405-hash+metadata", // other metadata without base version - } { - base, err := PseudoVersionBase(in) - if err == nil || base != "" { - t.Errorf(`PseudoVersionBase(%q) = %q, %v; want "", error`, in, base, err) - } - } -} - -func TestIncDecimal(t *testing.T) { - cases := []struct { - in, want string - }{ - {"0", "1"}, - {"1", "2"}, - {"99", "100"}, - {"100", "101"}, - {"101", "102"}, - } - - for _, tc := range cases { - got := incDecimal(tc.in) - if got != tc.want { - t.Fatalf("incDecimal(%q) = %q; want %q", tc.in, tc.want, got) - } - } -} - -func TestDecDecimal(t *testing.T) { - cases := []struct { - in, want string - }{ - {"", ""}, - {"0", ""}, - {"00", ""}, - {"1", "0"}, - {"2", "1"}, - {"99", "98"}, - {"100", "99"}, - {"101", "100"}, - } - - for _, tc := range cases { - got := decDecimal(tc.in) - if got != tc.want { - t.Fatalf("decDecimal(%q) = %q; want %q", tc.in, tc.want, got) - } - } -} diff --git a/libgo/go/cmd/go/internal/modfetch/repo.go b/libgo/go/cmd/go/internal/modfetch/repo.go index af9e24c..0bffa55 100644 --- a/libgo/go/cmd/go/internal/modfetch/repo.go +++ b/libgo/go/cmd/go/internal/modfetch/repo.go @@ -9,7 +9,6 @@ import ( "io" "io/fs" "os" - "sort" "strconv" "time" @@ -20,7 +19,6 @@ import ( web "cmd/go/internal/web" "golang.org/x/mod/module" - "golang.org/x/mod/semver" ) const traceRepo = false // trace all repo actions, for debugging @@ -35,7 +33,7 @@ type Repo interface { // Pseudo-versions are not included. // // Versions should be returned sorted in semver order - // (implementations can use SortVersions). + // (implementations can use semver.Sort). // // Versions returns a non-nil error only if there was a problem // fetching the list of versions: it may return an empty list @@ -171,15 +169,6 @@ type RevInfo struct { // and it can check that the path can be resolved to a target repository. // To avoid version control access except when absolutely necessary, // Lookup does not attempt to connect to the repository itself. -// -// The ImportRepoRev function is a variant of Import which is limited -// to code in a source code repository at a particular revision identifier -// (usually a commit hash or source code repository tag, not necessarily -// a module version). -// ImportRepoRev is used when converting legacy dependency requirements -// from older systems into go.mod files. Those older systems worked -// at either package or repository granularity, and most of the time they -// recorded commit hashes, not tagged versions. var lookupCache par.Cache @@ -194,7 +183,8 @@ type lookupCacheKey struct { // from its origin, and "noproxy" indicates that the patch should be fetched // directly only if GONOPROXY matches the given path. // -// For the distinguished proxy "off", Lookup always returns a non-nil error. +// For the distinguished proxy "off", Lookup always returns a Repo that returns +// a non-nil error for every method call. // // A successful return does not guarantee that the module // has any defined versions. @@ -267,7 +257,7 @@ var ( func lookupDirect(path string) (Repo, error) { security := web.SecureOnly - if allowInsecure(path) { + if module.MatchPrefixPatterns(cfg.GOINSECURE, path) { security = web.Insecure } rr, err := vcs.RepoRootForImportPath(path, vcs.PreferMod, security) @@ -299,63 +289,6 @@ func lookupCodeRepo(rr *vcs.RepoRoot) (codehost.Repo, error) { return code, nil } -// ImportRepoRev returns the module and version to use to access -// the given import path loaded from the source code repository that -// the original "go get" would have used, at the specific repository revision -// (typically a commit hash, but possibly also a source control tag). -func ImportRepoRev(path, rev string) (Repo, *RevInfo, error) { - if cfg.BuildMod == "vendor" || cfg.BuildMod == "readonly" { - return nil, nil, fmt.Errorf("repo version lookup disabled by -mod=%s", cfg.BuildMod) - } - - // Note: Because we are converting a code reference from a legacy - // version control system, we ignore meta tags about modules - // and use only direct source control entries (get.IgnoreMod). - security := web.SecureOnly - if allowInsecure(path) { - security = web.Insecure - } - rr, err := vcs.RepoRootForImportPath(path, vcs.IgnoreMod, security) - if err != nil { - return nil, nil, err - } - - code, err := lookupCodeRepo(rr) - if err != nil { - return nil, nil, err - } - - revInfo, err := code.Stat(rev) - if err != nil { - return nil, nil, err - } - - // TODO: Look in repo to find path, check for go.mod files. - // For now we're just assuming rr.Root is the module path, - // which is true in the absence of go.mod files. - - repo, err := newCodeRepo(code, rr.Root, rr.Root) - if err != nil { - return nil, nil, err - } - - info, err := repo.(*codeRepo).convert(revInfo, rev) - if err != nil { - return nil, nil, err - } - return repo, info, nil -} - -func SortVersions(list []string) { - sort.Slice(list, func(i, j int) bool { - cmp := semver.Compare(list[i], list[j]) - if cmp != 0 { - return cmp < 0 - } - return list[i] < list[j] - }) -} - // A loggingRepo is a wrapper around an underlying Repo // that prints a log message at the start and end of each call. // It can be inserted when debugging. diff --git a/libgo/go/cmd/go/internal/modfetch/sumdb.go b/libgo/go/cmd/go/internal/modfetch/sumdb.go index 4fbc54d..f233cba 100644 --- a/libgo/go/cmd/go/internal/modfetch/sumdb.go +++ b/libgo/go/cmd/go/internal/modfetch/sumdb.go @@ -4,6 +4,7 @@ // Go checksum database lookup +//go:build !cmd_go_bootstrap // +build !cmd_go_bootstrap package modfetch @@ -33,7 +34,7 @@ import ( // useSumDB reports whether to use the Go checksum database for the given module. func useSumDB(mod module.Version) bool { - return cfg.GOSUMDB != "off" && !cfg.Insecure && !module.MatchPrefixPatterns(cfg.GONOSUMDB, mod.Path) + return cfg.GOSUMDB != "off" && !module.MatchPrefixPatterns(cfg.GONOSUMDB, mod.Path) } // lookupSumDB returns the Go checksum database's go.sum lines for the given module, @@ -184,7 +185,7 @@ func (c *dbClient) initBase() { } }) if errors.Is(err, fs.ErrNotExist) { - // No proxies, or all proxies failed (with 404, 410, or were were allowed + // No proxies, or all proxies failed (with 404, 410, or were allowed // to fall back), or we reached an explicit "direct" or "off". c.base = c.direct } else if err != nil { diff --git a/libgo/go/cmd/go/internal/modget/get.go b/libgo/go/cmd/go/internal/modget/get.go index 5a98408..9672e55 100644 --- a/libgo/go/cmd/go/internal/modget/get.go +++ b/libgo/go/cmd/go/internal/modget/get.go @@ -30,16 +30,15 @@ import ( "fmt" "os" "path/filepath" - "reflect" "runtime" "sort" "strings" "sync" "cmd/go/internal/base" - "cmd/go/internal/cfg" "cmd/go/internal/imports" "cmd/go/internal/load" + "cmd/go/internal/modfetch" "cmd/go/internal/modload" "cmd/go/internal/par" "cmd/go/internal/search" @@ -53,7 +52,7 @@ import ( var CmdGet = &base.Command{ // Note: -d -u are listed explicitly because they are the most common get flags. // Do not send CLs removing them because they're covered by [get flags]. - UsageLine: "go get [-d] [-t] [-u] [-v] [-insecure] [build flags] [packages]", + UsageLine: "go get [-d] [-t] [-u] [-v] [build flags] [packages]", Short: "add dependencies to current module and install them", Long: ` Get resolves its command-line arguments to packages at specific module versions, @@ -99,14 +98,6 @@ but changes the default to select patch releases. When the -t and -u flags are used together, get will update test dependencies as well. -The -insecure flag permits fetching from repositories and resolving -custom domains using insecure schemes such as HTTP, and also bypassess -module sum validation using the checksum database. Use with caution. -This flag is deprecated and will be removed in a future version of go. -To permit the use of insecure schemes, use the GOINSECURE environment -variable instead. To bypass module sum validation, use GOPRIVATE or -GONOSUMDB. See 'go help environment' for details. - The -d flag instructs get not to build or install packages. get will only update go.mod and download source code needed to build packages. @@ -227,13 +218,13 @@ variable for future go command invocations. } var ( - getD = CmdGet.Flag.Bool("d", false, "") - getF = CmdGet.Flag.Bool("f", false, "") - getFix = CmdGet.Flag.Bool("fix", false, "") - getM = CmdGet.Flag.Bool("m", false, "") - getT = CmdGet.Flag.Bool("t", false, "") - getU upgradeFlag - // -insecure is cfg.Insecure + getD = CmdGet.Flag.Bool("d", false, "") + getF = CmdGet.Flag.Bool("f", false, "") + getFix = CmdGet.Flag.Bool("fix", false, "") + getM = CmdGet.Flag.Bool("m", false, "") + getT = CmdGet.Flag.Bool("t", false, "") + getU upgradeFlag + getInsecure = CmdGet.Flag.Bool("insecure", false, "") // -v is cfg.BuildV ) @@ -264,7 +255,6 @@ func (v *upgradeFlag) String() string { return "" } func init() { work.AddBuildFlags(CmdGet, work.OmitModFlag) CmdGet.Run = runGet // break init loop - CmdGet.Flag.BoolVar(&cfg.Insecure, "insecure", cfg.Insecure, "") CmdGet.Flag.Var(&getU, "u", "") } @@ -284,10 +274,9 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { if *getM { base.Fatalf("go get: -m flag is no longer supported; consider -d to skip building packages") } - if cfg.Insecure { - fmt.Fprintf(os.Stderr, "go get: -insecure flag is deprecated; see 'go help get' for details\n") + if *getInsecure { + base.Fatalf("go get: -insecure flag is no longer supported; use GOINSECURE instead") } - load.ModResolveTests = *getT // Do not allow any updating of go.mod until we've applied // all the requested changes and checked that the result matches @@ -298,8 +287,6 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { // 'go get' is expected to do this, unlike other commands. modload.AllowMissingModuleImports() - modload.LoadModFile(ctx) // Initializes modload.Target. - queries := parseArgs(ctx, args) r := newResolver(ctx, queries) @@ -310,7 +297,7 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { r.performWildcardQueries(ctx) r.performPatternAllQueries(ctx) - if changed := r.resolveCandidates(ctx, queries, nil); changed { + if changed := r.resolveQueries(ctx, queries); changed { // 'go get' arguments can be (and often are) package patterns rather than // (just) modules. A package can be provided by any module with a prefix // of its import path, and a wildcard can even match packages in modules @@ -347,12 +334,12 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { // - ambiguous import errors. // TODO(#27899): Try to resolve ambiguous import errors automatically. upgrades := r.findAndUpgradeImports(ctx, queries) - if changed := r.resolveCandidates(ctx, nil, upgrades); changed { + if changed := r.applyUpgrades(ctx, upgrades); changed { continue } r.findMissingWildcards(ctx) - if changed := r.resolveCandidates(ctx, r.wildcardQueries, nil); changed { + if changed := r.resolveQueries(ctx, r.wildcardQueries); changed { continue } @@ -367,7 +354,7 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { pkgPatterns = append(pkgPatterns, q.pattern) } } - r.checkPackagesAndRetractions(ctx, pkgPatterns) + r.checkPackageProblems(ctx, pkgPatterns) // We've already downloaded modules (and identified direct and indirect // dependencies) by loading packages in findAndUpgradeImports. @@ -380,12 +367,51 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { // directory. if !*getD && len(pkgPatterns) > 0 { work.BuildInit() - pkgs := load.PackagesAndErrors(ctx, pkgPatterns) + + pkgOpts := load.PackageOpts{ModResolveTests: *getT} + var pkgs []*load.Package + for _, pkg := range load.PackagesAndErrors(ctx, pkgOpts, pkgPatterns) { + if pkg.Error != nil { + var noGo *load.NoGoError + if errors.As(pkg.Error.Err, &noGo) { + if m := modload.PackageModule(pkg.ImportPath); m.Path == pkg.ImportPath { + // pkg is at the root of a module, and doesn't exist with the current + // build tags. Probably the user just wanted to change the version of + // that module — not also build the package — so suppress the error. + // (See https://golang.org/issue/33526.) + continue + } + } + } + pkgs = append(pkgs, pkg) + } load.CheckPackageErrors(pkgs) + + haveExternalExe := false + for _, pkg := range pkgs { + if pkg.Name == "main" && pkg.Module != nil && pkg.Module.Path != modload.Target.Path { + haveExternalExe = true + break + } + } + if haveExternalExe { + fmt.Fprint(os.Stderr, "go get: installing executables with 'go get' in module mode is deprecated.") + var altMsg string + if modload.HasModRoot() { + altMsg = ` + To adjust and download dependencies of the current module, use 'go get -d'. + To install using requirements of the current module, use 'go install'. + To install ignoring the current module, use 'go install' with a version, + like 'go install example.com/cmd@latest'. +` + } else { + altMsg = "\n\tUse 'go install pkg@version' instead.\n" + } + fmt.Fprint(os.Stderr, altMsg) + fmt.Fprintf(os.Stderr, "\tFor more information, see https://golang.org/doc/go-get-install-deprecation\n\tor run 'go help get' or 'go help install'.\n") + } + work.InstallPackages(ctx, pkgPatterns, pkgs) - // TODO(#40276): After Go 1.16, print a deprecation notice when building and - // installing main packages. 'go install pkg' or 'go install pkg@version' - // should be used instead. Give the specific argument to use if possible. } if !modload.HasModRoot() { @@ -396,7 +422,7 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { oldReqs := reqsFromGoMod(modload.ModFile()) modload.AllowWriteGoMod() - modload.WriteGoMod() + modload.WriteGoMod(ctx) modload.DisallowWriteGoMod() newReqs := reqsFromGoMod(modload.ModFile()) @@ -460,9 +486,8 @@ type resolver struct { // that resolved the module to that version (the “reason”). resolvedVersion map[string]versionReason - buildList []module.Version - buildListResolvedVersions int // len(resolvedVersion) when buildList was computed - buildListVersion map[string]string // index of buildList (module path → version) + buildList []module.Version + buildListVersion map[string]string // index of buildList (module path → version) initialVersion map[string]string // index of the initial build list at the start of 'go get' @@ -479,7 +504,12 @@ type versionReason struct { } func newResolver(ctx context.Context, queries []*query) *resolver { - buildList := modload.LoadAllModules(ctx) + // LoadModGraph also sets modload.Target, which is needed by various resolver + // methods. + const defaultGoVersion = "" + mg := modload.LoadModGraph(ctx, defaultGoVersion) + + buildList := mg.BuildList() initialVersion := make(map[string]string, len(buildList)) for _, m := range buildList { initialVersion[m.Path] = m.Version @@ -688,7 +718,7 @@ func (r *resolver) performLocalQueries(ctx context.Context) { // Absolute paths like C:\foo and relative paths like ../foo... are // restricted to matching packages in the main module. - pkgPattern := modload.DirImportPath(q.pattern) + pkgPattern := modload.DirImportPath(ctx, q.pattern) if pkgPattern == "." { return errSet(fmt.Errorf("%s%s is not within module rooted at %s", q.pattern, absDetail, modload.ModRoot())) } @@ -1121,9 +1151,11 @@ func (r *resolver) findAndUpgradeImports(ctx context.Context, queries []*query) // build list. func (r *resolver) loadPackages(ctx context.Context, patterns []string, findPackage func(ctx context.Context, path string, m module.Version) (versionOk bool)) { opts := modload.PackageOpts{ - Tags: imports.AnyTags(), - LoadTests: *getT, - SilenceErrors: true, // May be fixed by subsequent upgrades or downgrades. + Tags: imports.AnyTags(), + VendorModulesInGOROOTSrc: true, + LoadTests: *getT, + AssumeRootsImported: true, // After 'go get foo', imports of foo should build. + SilencePackageErrors: true, // May be fixed by subsequent upgrades or downgrades. } opts.AllowPackage = func(ctx context.Context, path string, m module.Version) error { @@ -1176,24 +1208,19 @@ func (r *resolver) loadPackages(ctx context.Context, patterns []string, findPack // to be updated before its dependencies can be loaded. var errVersionChange = errors.New("version change needed") -// resolveCandidates resolves candidates sets that are attached to the given +// resolveQueries resolves candidate sets that are attached to the given // queries and/or needed to provide the given missing-package dependencies. // -// resolveCandidates starts by resolving one module version from each +// resolveQueries starts by resolving one module version from each // unambiguous pathSet attached to the given queries. // // If no unambiguous query results in a change to the build list, -// resolveCandidates modifies the build list by adding one module version from -// each pathSet in missing, but does not mark those versions as resolved -// (so they can still be modified by other queries). -// -// If that still does not result in any changes to the build list, -// resolveCandidates revisits the ambiguous query candidates and resolves them +// resolveQueries revisits the ambiguous query candidates and resolves them // arbitrarily in order to guarantee forward progress. // // If all pathSets are resolved without any changes to the build list, -// resolveCandidates returns with changed=false. -func (r *resolver) resolveCandidates(ctx context.Context, queries []*query, upgrades []pathSet) (changed bool) { +// resolveQueries returns with changed=false. +func (r *resolver) resolveQueries(ctx context.Context, queries []*query) (changed bool) { defer base.ExitIfErrors() // Note: this is O(N²) with the number of pathSets in the worst case. @@ -1247,12 +1274,52 @@ func (r *resolver) resolveCandidates(ctx context.Context, queries []*query, upgr } } - if changed := r.updateBuildList(ctx, nil); changed { - // The build list has changed, so disregard any missing packages: they might - // now be determined by requirements in the build list, which we would - // prefer to use instead of arbitrary "latest" versions. - return true + if resolved > 0 { + if changed = r.updateBuildList(ctx, nil); changed { + // The build list has changed, so disregard any remaining ambiguous queries: + // they might now be determined by requirements in the build list, which we + // would prefer to use instead of arbitrary versions. + return true + } + } + + // The build list will be the same on the next iteration as it was on this + // iteration, so any ambiguous queries will remain so. In order to make + // progress, resolve them arbitrarily but deterministically. + // + // If that results in conflicting versions, the user can re-run 'go get' + // with additional explicit versions for the conflicting packages or + // modules. + resolvedArbitrarily := 0 + for _, q := range queries { + for _, cs := range q.candidates { + isPackage, m := r.chooseArbitrarily(cs) + if isPackage { + q.matchesPackages = true + } + r.resolve(q, m) + resolvedArbitrarily++ + } } + if resolvedArbitrarily > 0 { + changed = r.updateBuildList(ctx, nil) + } + return changed +} + +// applyUpgrades disambiguates candidate sets that are needed to upgrade (or +// provide) transitive dependencies imported by previously-resolved packages. +// +// applyUpgrades modifies the build list by adding one module version from each +// pathSet in upgrades, then downgrading (or further upgrading) those modules as +// needed to maintain any already-resolved versions of other modules. +// applyUpgrades does not mark the new versions as resolved, so they can still +// be further modified by other queries (such as wildcards). +// +// If all pathSets are resolved without any changes to the build list, +// applyUpgrades returns with changed=false. +func (r *resolver) applyUpgrades(ctx context.Context, upgrades []pathSet) (changed bool) { + defer base.ExitIfErrors() // Arbitrarily add a "latest" version that provides each missing package, but // do not mark the version as resolved: we still want to allow the explicit @@ -1276,27 +1343,9 @@ func (r *resolver) resolveCandidates(ctx context.Context, queries []*query, upgr tentative = append(tentative, m) } base.ExitIfErrors() - if changed := r.updateBuildList(ctx, tentative); changed { - return true - } - // The build list will be the same on the next iteration as it was on this - // iteration, so any ambiguous queries will remain so. In order to make - // progress, resolve them arbitrarily but deterministically. - // - // If that results in conflicting versions, the user can re-run 'go get' - // with additional explicit versions for the conflicting packages or - // modules. - for _, q := range queries { - for _, cs := range q.candidates { - isPackage, m := r.chooseArbitrarily(cs) - if isPackage { - q.matchesPackages = true - } - r.resolve(q, m) - } - } - return r.updateBuildList(ctx, nil) + changed = r.updateBuildList(ctx, tentative) + return changed } // disambiguate eliminates candidates from cs that conflict with other module @@ -1417,25 +1466,33 @@ func (r *resolver) chooseArbitrarily(cs pathSet) (isPackage bool, m module.Versi return false, cs.mod } -// checkPackagesAndRetractions reloads packages for the given patterns and -// reports missing and ambiguous package errors. It also reports loads and -// reports retractions for resolved modules and modules needed to build -// named packages. +// checkPackageProblems reloads packages for the given patterns and reports +// missing and ambiguous package errors. It also reports retractions and +// deprecations for resolved modules and modules needed to build named packages. +// It also adds a sum for each updated module in the build list if we had one +// before and didn't get one while loading packages. // // We skip missing-package errors earlier in the process, since we want to // resolve pathSets ourselves, but at that point, we don't have enough context // to log the package-import chains leading to each error. -func (r *resolver) checkPackagesAndRetractions(ctx context.Context, pkgPatterns []string) { +func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []string) { defer base.ExitIfErrors() - // Build a list of modules to load retractions for. Start with versions - // selected based on command line queries. - // - // This is a subset of the build list. If the main module has a lot of - // dependencies, loading retractions for the entire build list would be slow. - relevantMods := make(map[module.Version]struct{}) + // Gather information about modules we might want to load retractions and + // deprecations for. Loading this metadata requires at least one version + // lookup per module, and we don't want to load information that's neither + // relevant nor actionable. + type modFlags int + const ( + resolved modFlags = 1 << iota // version resolved by 'go get' + named // explicitly named on command line or provides a named package + hasPkg // needed to build named packages + direct // provides a direct dependency of the main module + ) + relevantMods := make(map[module.Version]modFlags) for path, reason := range r.resolvedVersion { - relevantMods[module.Version{Path: path, Version: reason.version}] = struct{}{} + m := module.Version{Path: path, Version: reason.version} + relevantMods[m] |= resolved } // Reload packages, reporting errors for missing and ambiguous imports. @@ -1443,9 +1500,11 @@ func (r *resolver) checkPackagesAndRetractions(ctx context.Context, pkgPatterns // LoadPackages will print errors (since it has more context) but will not // exit, since we need to load retractions later. pkgOpts := modload.PackageOpts{ - LoadTests: *getT, - ResolveMissingImports: false, - AllowErrors: true, + VendorModulesInGOROOTSrc: true, + LoadTests: *getT, + ResolveMissingImports: false, + AllowErrors: true, + SilenceNoGoErrors: true, } matches, pkgs := modload.LoadPackages(ctx, pkgOpts, pkgPatterns...) for _, m := range matches { @@ -1461,53 +1520,141 @@ func (r *resolver) checkPackagesAndRetractions(ctx context.Context, pkgPatterns // associated with either the package or its test — ErrNoGo must // indicate that none of those source files happen to apply in this // configuration. If we are actually building the package (no -d - // flag), the compiler will report the problem; otherwise, assume that - // the user is going to build or test it in some other configuration - // and suppress the error. + // flag), we will report the problem then; otherwise, assume that the + // user is going to build or test this package in some other + // configuration and suppress the error. continue } base.SetExitStatus(1) if ambiguousErr := (*modload.AmbiguousImportError)(nil); errors.As(err, &ambiguousErr) { for _, m := range ambiguousErr.Modules { - relevantMods[m] = struct{}{} + relevantMods[m] |= hasPkg } } } if m := modload.PackageModule(pkg); m.Path != "" { - relevantMods[m] = struct{}{} + relevantMods[m] |= hasPkg + } + } + for _, match := range matches { + for _, pkg := range match.Pkgs { + m := modload.PackageModule(pkg) + relevantMods[m] |= named } } } - // Load and report retractions. - type retraction struct { - m module.Version - err error - } - retractions := make([]retraction, 0, len(relevantMods)) + reqs := modload.LoadModFile(ctx) for m := range relevantMods { - retractions = append(retractions, retraction{m: m}) + if reqs.IsDirect(m.Path) { + relevantMods[m] |= direct + } } - sort.Slice(retractions, func(i, j int) bool { - return retractions[i].m.Path < retractions[j].m.Path - }) - for i := 0; i < len(retractions); i++ { + + // Load retractions for modules mentioned on the command line and modules + // needed to build named packages. We care about retractions of indirect + // dependencies, since we might be able to upgrade away from them. + type modMessage struct { + m module.Version + message string + } + retractions := make([]modMessage, 0, len(relevantMods)) + for m, flags := range relevantMods { + if flags&(resolved|named|hasPkg) != 0 { + retractions = append(retractions, modMessage{m: m}) + } + } + sort.Slice(retractions, func(i, j int) bool { return retractions[i].m.Path < retractions[j].m.Path }) + for i := range retractions { i := i r.work.Add(func() { err := modload.CheckRetractions(ctx, retractions[i].m) if retractErr := (*modload.ModuleRetractedError)(nil); errors.As(err, &retractErr) { - retractions[i].err = err + retractions[i].message = err.Error() + } + }) + } + + // Load deprecations for modules mentioned on the command line. Only load + // deprecations for indirect dependencies if they're also direct dependencies + // of the main module. Deprecations of purely indirect dependencies are + // not actionable. + deprecations := make([]modMessage, 0, len(relevantMods)) + for m, flags := range relevantMods { + if flags&(resolved|named) != 0 || flags&(hasPkg|direct) == hasPkg|direct { + deprecations = append(deprecations, modMessage{m: m}) + } + } + sort.Slice(deprecations, func(i, j int) bool { return deprecations[i].m.Path < deprecations[j].m.Path }) + for i := range deprecations { + i := i + r.work.Add(func() { + deprecation, err := modload.CheckDeprecation(ctx, deprecations[i].m) + if err != nil || deprecation == "" { + return + } + deprecations[i].message = modload.ShortMessage(deprecation, "") + }) + } + + // Load sums for updated modules that had sums before. When we update a + // module, we may update another module in the build list that provides a + // package in 'all' that wasn't loaded as part of this 'go get' command. + // If we don't add a sum for that module, builds may fail later. + // Note that an incidentally updated package could still import packages + // from unknown modules or from modules in the build list that we didn't + // need previously. We can't handle that case without loading 'all'. + sumErrs := make([]error, len(r.buildList)) + for i := range r.buildList { + i := i + m := r.buildList[i] + mActual := m + if mRepl := modload.Replacement(m); mRepl.Path != "" { + mActual = mRepl + } + old := module.Version{Path: m.Path, Version: r.initialVersion[m.Path]} + if old.Version == "" { + continue + } + oldActual := old + if oldRepl := modload.Replacement(old); oldRepl.Path != "" { + oldActual = oldRepl + } + if mActual == oldActual || mActual.Version == "" || !modfetch.HaveSum(oldActual) { + continue + } + r.work.Add(func() { + if _, err := modfetch.DownloadZip(ctx, mActual); err != nil { + verb := "upgraded" + if semver.Compare(m.Version, old.Version) < 0 { + verb = "downgraded" + } + replaced := "" + if mActual != m { + replaced = fmt.Sprintf(" (replaced by %s)", mActual) + } + err = fmt.Errorf("%s %s %s => %s%s: error finding sum for %s: %v", verb, m.Path, old.Version, m.Version, replaced, mActual, err) + sumErrs[i] = err } }) } + <-r.work.Idle() + + // Report deprecations, then retractions, then errors fetching sums. + // Only errors fetching sums are hard errors. + for _, mm := range deprecations { + if mm.message != "" { + fmt.Fprintf(os.Stderr, "go: module %s is deprecated: %s\n", mm.m.Path, mm.message) + } + } var retractPath string - for _, r := range retractions { - if r.err != nil { - fmt.Fprintf(os.Stderr, "go: warning: %v\n", r.err) + for _, mm := range retractions { + if mm.message != "" { + fmt.Fprintf(os.Stderr, "go: warning: %v\n", mm.message) if retractPath == "" { - retractPath = r.m.Path + retractPath = mm.m.Path } else { retractPath = "<module>" } @@ -1516,6 +1663,12 @@ func (r *resolver) checkPackagesAndRetractions(ctx context.Context, pkgPatterns if retractPath != "" { fmt.Fprintf(os.Stderr, "go: to switch to the latest unretracted version, run:\n\tgo get %s@latest\n", retractPath) } + for _, err := range sumErrs { + if err != nil { + base.Errorf("go: %v", err) + } + } + base.ExitIfErrors() } // reportChanges logs version changes to os.Stderr. @@ -1614,11 +1767,10 @@ func (r *resolver) resolve(q *query, m module.Version) { // // If the additional modules conflict with the resolved versions, they will be // downgraded to a non-conflicting version (possibly "none"). +// +// If the resulting build list is the same as the one resulting from the last +// call to updateBuildList, updateBuildList returns with changed=false. func (r *resolver) updateBuildList(ctx context.Context, additions []module.Version) (changed bool) { - if len(additions) == 0 && len(r.resolvedVersion) == r.buildListResolvedVersions { - return false - } - defer base.ExitIfErrors() resolved := make([]module.Version, 0, len(r.resolvedVersion)) @@ -1628,7 +1780,8 @@ func (r *resolver) updateBuildList(ctx context.Context, additions []module.Versi } } - if err := modload.EditBuildList(ctx, additions, resolved); err != nil { + changed, err := modload.EditBuildList(ctx, additions, resolved) + if err != nil { var constraint *modload.ConstraintError if !errors.As(err, &constraint) { base.Errorf("go get: %v", err) @@ -1647,13 +1800,12 @@ func (r *resolver) updateBuildList(ctx context.Context, additions []module.Versi } return false } - - buildList := modload.LoadAllModules(ctx) - r.buildListResolvedVersions = len(r.resolvedVersion) - if reflect.DeepEqual(r.buildList, buildList) { + if !changed { return false } - r.buildList = buildList + + const defaultGoVersion = "" + r.buildList = modload.LoadModGraph(ctx, defaultGoVersion).BuildList() r.buildListVersion = make(map[string]string, len(r.buildList)) for _, m := range r.buildList { r.buildListVersion[m.Path] = m.Version diff --git a/libgo/go/cmd/go/internal/modinfo/info.go b/libgo/go/cmd/go/internal/modinfo/info.go index 897be56..1908835 100644 --- a/libgo/go/cmd/go/internal/modinfo/info.go +++ b/libgo/go/cmd/go/internal/modinfo/info.go @@ -10,19 +10,20 @@ import "time" // and the fields are documented in the help text in ../list/list.go type ModulePublic struct { - Path string `json:",omitempty"` // module path - Version string `json:",omitempty"` // module version - Versions []string `json:",omitempty"` // available module versions - Replace *ModulePublic `json:",omitempty"` // replaced by this module - Time *time.Time `json:",omitempty"` // time version was created - Update *ModulePublic `json:",omitempty"` // available update (with -u) - Main bool `json:",omitempty"` // is this the main module? - Indirect bool `json:",omitempty"` // module is only indirectly needed by main module - Dir string `json:",omitempty"` // directory holding local copy of files, if any - GoMod string `json:",omitempty"` // path to go.mod file describing module, if any - GoVersion string `json:",omitempty"` // go version used in module - Retracted []string `json:",omitempty"` // retraction information, if any (with -retracted or -u) - Error *ModuleError `json:",omitempty"` // error loading module + Path string `json:",omitempty"` // module path + Version string `json:",omitempty"` // module version + Versions []string `json:",omitempty"` // available module versions + Replace *ModulePublic `json:",omitempty"` // replaced by this module + Time *time.Time `json:",omitempty"` // time version was created + Update *ModulePublic `json:",omitempty"` // available update (with -u) + Main bool `json:",omitempty"` // is this the main module? + Indirect bool `json:",omitempty"` // module is only indirectly needed by main module + Dir string `json:",omitempty"` // directory holding local copy of files, if any + GoMod string `json:",omitempty"` // path to go.mod file describing module, if any + GoVersion string `json:",omitempty"` // go version used in module + Retracted []string `json:",omitempty"` // retraction information, if any (with -retracted or -u) + Deprecated string `json:",omitempty"` // deprecation message, if any (with -u) + Error *ModuleError `json:",omitempty"` // error loading module } type ModuleError struct { @@ -45,6 +46,9 @@ func (m *ModulePublic) String() string { s += " [" + versionString(m.Update) + "]" } } + if m.Deprecated != "" { + s += " (deprecated)" + } if m.Replace != nil { s += " => " + m.Replace.Path if m.Replace.Version != "" { @@ -53,6 +57,9 @@ func (m *ModulePublic) String() string { s += " [" + versionString(m.Replace.Update) + "]" } } + if m.Replace.Deprecated != "" { + s += " (deprecated)" + } } return s } diff --git a/libgo/go/cmd/go/internal/modload/build.go b/libgo/go/cmd/go/internal/modload/build.go index d2f8f86..becf6b8 100644 --- a/libgo/go/cmd/go/internal/modload/build.go +++ b/libgo/go/cmd/go/internal/modload/build.go @@ -11,6 +11,7 @@ import ( "errors" "fmt" "internal/goroot" + "io/fs" "os" "path/filepath" "strings" @@ -50,17 +51,17 @@ func findStandardImportPath(path string) string { // a given package. If modules are not enabled or if the package is in the // standard library or if the package was not successfully loaded with // LoadPackages or ImportFromFiles, nil is returned. -func PackageModuleInfo(pkgpath string) *modinfo.ModulePublic { +func PackageModuleInfo(ctx context.Context, pkgpath string) *modinfo.ModulePublic { if isStandardImportPath(pkgpath) || !Enabled() { return nil } - m, ok := findModule(pkgpath) + m, ok := findModule(loaded, pkgpath) if !ok { return nil } - fromBuildList := true - listRetracted := false - return moduleInfo(context.TODO(), m, fromBuildList, listRetracted) + + rs := LoadModFile(ctx) + return moduleInfo(ctx, rs, m, 0) } func ModuleInfo(ctx context.Context, path string) *modinfo.ModulePublic { @@ -68,26 +69,38 @@ func ModuleInfo(ctx context.Context, path string) *modinfo.ModulePublic { return nil } - listRetracted := false if i := strings.Index(path, "@"); i >= 0 { m := module.Version{Path: path[:i], Version: path[i+1:]} - fromBuildList := false - return moduleInfo(ctx, m, fromBuildList, listRetracted) + return moduleInfo(ctx, nil, m, 0) } - for _, m := range buildList { - if m.Path == path { - fromBuildList := true - return moduleInfo(ctx, m, fromBuildList, listRetracted) + rs := LoadModFile(ctx) + + var ( + v string + ok bool + ) + if rs.depth == lazy { + v, ok = rs.rootSelected(path) + } + if !ok { + mg, err := rs.Graph(ctx) + if err != nil { + base.Fatalf("go: %v", err) } + v = mg.Selected(path) } - return &modinfo.ModulePublic{ - Path: path, - Error: &modinfo.ModuleError{ - Err: "module not in current build", - }, + if v == "none" { + return &modinfo.ModulePublic{ + Path: path, + Error: &modinfo.ModuleError{ + Err: "module not in current build", + }, + } } + + return moduleInfo(ctx, rs, module.Version{Path: path, Version: v}, 0) } // addUpdate fills in m.Update if an updated version is available. @@ -96,7 +109,26 @@ func addUpdate(ctx context.Context, m *modinfo.ModulePublic) { return } - if info, err := Query(ctx, m.Path, "upgrade", m.Version, CheckAllowed); err == nil && semver.Compare(info.Version, m.Version) > 0 { + info, err := Query(ctx, m.Path, "upgrade", m.Version, CheckAllowed) + var noVersionErr *NoMatchingVersionError + if errors.Is(err, fs.ErrNotExist) || errors.As(err, &noVersionErr) { + // Ignore "not found" and "no matching version" errors. + // This means the proxy has no matching version or no versions at all. + // + // We should report other errors though. An attacker that controls the + // network shouldn't be able to hide versions by interfering with + // the HTTPS connection. An attacker that controls the proxy may still + // hide versions, since the "list" and "latest" endpoints are not + // authenticated. + return + } else if err != nil { + if m.Error == nil { + m.Error = &modinfo.ModuleError{Err: err.Error()} + } + return + } + + if semver.Compare(info.Version, m.Version) > 0 { m.Update = &modinfo.ModulePublic{ Path: m.Path, Version: info.Version, @@ -113,7 +145,11 @@ func addVersions(ctx context.Context, m *modinfo.ModulePublic, listRetracted boo if listRetracted { allowed = CheckExclusions } - m.Versions, _ = versions(ctx, m.Path, allowed) + var err error + m.Versions, err = versions(ctx, m.Path, allowed) + if err != nil && m.Error == nil { + m.Error = &modinfo.ModuleError{Err: err.Error()} + } } // addRetraction fills in m.Retracted if the module was retracted by its author. @@ -124,31 +160,72 @@ func addRetraction(ctx context.Context, m *modinfo.ModulePublic) { } err := CheckRetractions(ctx, module.Version{Path: m.Path, Version: m.Version}) - var rerr *ModuleRetractedError - if errors.As(err, &rerr) { - if len(rerr.Rationale) == 0 { + var noVersionErr *NoMatchingVersionError + var retractErr *ModuleRetractedError + if err == nil || errors.Is(err, fs.ErrNotExist) || errors.As(err, &noVersionErr) { + // Ignore "not found" and "no matching version" errors. + // This means the proxy has no matching version or no versions at all. + // + // We should report other errors though. An attacker that controls the + // network shouldn't be able to hide versions by interfering with + // the HTTPS connection. An attacker that controls the proxy may still + // hide versions, since the "list" and "latest" endpoints are not + // authenticated. + return + } else if errors.As(err, &retractErr) { + if len(retractErr.Rationale) == 0 { m.Retracted = []string{"retracted by module author"} } else { - m.Retracted = rerr.Rationale + m.Retracted = retractErr.Rationale } - } else if err != nil && m.Error == nil { + } else if m.Error == nil { m.Error = &modinfo.ModuleError{Err: err.Error()} } } -func moduleInfo(ctx context.Context, m module.Version, fromBuildList, listRetracted bool) *modinfo.ModulePublic { +// addDeprecation fills in m.Deprecated if the module was deprecated by its +// author. m.Error is set if there's an error loading deprecation information. +func addDeprecation(ctx context.Context, m *modinfo.ModulePublic) { + deprecation, err := CheckDeprecation(ctx, module.Version{Path: m.Path, Version: m.Version}) + var noVersionErr *NoMatchingVersionError + if errors.Is(err, fs.ErrNotExist) || errors.As(err, &noVersionErr) { + // Ignore "not found" and "no matching version" errors. + // This means the proxy has no matching version or no versions at all. + // + // We should report other errors though. An attacker that controls the + // network shouldn't be able to hide versions by interfering with + // the HTTPS connection. An attacker that controls the proxy may still + // hide versions, since the "list" and "latest" endpoints are not + // authenticated. + return + } + if err != nil { + if m.Error == nil { + m.Error = &modinfo.ModuleError{Err: err.Error()} + } + return + } + m.Deprecated = deprecation +} + +// moduleInfo returns information about module m, loaded from the requirements +// in rs (which may be nil to indicate that m was not loaded from a requirement +// graph). +func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode ListMode) *modinfo.ModulePublic { if m == Target { info := &modinfo.ModulePublic{ Path: m.Path, Version: m.Version, Main: true, } + if v, ok := rawGoVersion.Load(Target); ok { + info.GoVersion = v.(string) + } else { + panic("internal error: GoVersion not set for main module") + } if HasModRoot() { info.Dir = ModRoot() info.GoMod = ModFilePath() - if modFile.Go != nil { - info.GoVersion = modFile.Go.Version - } } return info } @@ -156,7 +233,7 @@ func moduleInfo(ctx context.Context, m module.Version, fromBuildList, listRetrac info := &modinfo.ModulePublic{ Path: m.Path, Version: m.Version, - Indirect: fromBuildList && loaded != nil && !loaded.direct[m.Path], + Indirect: rs != nil && !rs.direct[m.Path], } if v, ok := rawGoVersion.Load(m); ok { info.GoVersion = v.(string) @@ -164,7 +241,10 @@ func moduleInfo(ctx context.Context, m module.Version, fromBuildList, listRetrac // completeFromModCache fills in the extra fields in m using the module cache. completeFromModCache := func(m *modinfo.ModulePublic) { - mod := module.Version{Path: m.Path, Version: m.Version} + checksumOk := func(suffix string) bool { + return rs == nil || m.Version == "" || cfg.BuildMod == "mod" || + modfetch.HaveSum(module.Version{Path: m.Path, Version: m.Version + suffix}) + } if m.Version != "" { if q, err := Query(ctx, m.Path, m.Version, "", nil); err != nil { @@ -173,31 +253,40 @@ func moduleInfo(ctx context.Context, m module.Version, fromBuildList, listRetrac m.Version = q.Version m.Time = &q.Time } + } + mod := module.Version{Path: m.Path, Version: m.Version} + + if m.GoVersion == "" && checksumOk("/go.mod") { + // Load the go.mod file to determine the Go version, since it hasn't + // already been populated from rawGoVersion. + if summary, err := rawGoModSummary(mod); err == nil && summary.goVersion != "" { + m.GoVersion = summary.goVersion + } + } - gomod, err := modfetch.CachePath(mod, "mod") - if err == nil { - if info, err := os.Stat(gomod); err == nil && info.Mode().IsRegular() { - m.GoMod = gomod + if m.Version != "" { + if checksumOk("/go.mod") { + gomod, err := modfetch.CachePath(mod, "mod") + if err == nil { + if info, err := os.Stat(gomod); err == nil && info.Mode().IsRegular() { + m.GoMod = gomod + } } } - dir, err := modfetch.DownloadDir(mod) - if err == nil { - m.Dir = dir + if checksumOk("") { + dir, err := modfetch.DownloadDir(mod) + if err == nil { + m.Dir = dir + } } - if listRetracted { + if mode&ListRetracted != 0 { addRetraction(ctx, m) } } - - if m.GoVersion == "" { - if summary, err := rawGoModSummary(mod); err == nil && summary.goVersionV != "" { - m.GoVersion = summary.goVersionV[1:] - } - } } - if !fromBuildList { + if rs == nil { // If this was an explicitly-versioned argument to 'go mod download' or // 'go list -m', report the actual requested version, not its replacement. completeFromModCache(info) // Will set m.Error in vendor mode. @@ -255,11 +344,11 @@ func PackageBuildInfo(path string, deps []string) string { return "" } - target := mustFindModule(path, path) + target := mustFindModule(loaded, path, path) mdeps := make(map[module.Version]bool) for _, dep := range deps { if !isStandardImportPath(dep) { - mdeps[mustFindModule(path, dep)] = true + mdeps[mustFindModule(loaded, path, dep)] = true } } var mods []module.Version @@ -298,8 +387,8 @@ func PackageBuildInfo(path string, deps []string) string { // // TODO(jayconrod): remove this. Callers should use findModule and return // errors instead of relying on base.Fatalf. -func mustFindModule(target, path string) module.Version { - pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) +func mustFindModule(ld *loader, target, path string) module.Version { + pkg, ok := ld.pkgCache.Get(path).(*loadPkg) if ok { if pkg.err != nil { base.Fatalf("build %v: cannot load %v: %v", target, path, pkg.err) @@ -318,8 +407,8 @@ func mustFindModule(target, path string) module.Version { // findModule searches for the module that contains the package at path. // If the package was loaded, its containing module and true are returned. // Otherwise, module.Version{} and false are returend. -func findModule(path string) (module.Version, bool) { - if pkg, ok := loaded.pkgCache.Get(path).(*loadPkg); ok { +func findModule(ld *loader, path string) (module.Version, bool) { + if pkg, ok := ld.pkgCache.Get(path).(*loadPkg); ok { return pkg.mod, pkg.mod != module.Version{} } if path == "command-line-arguments" { diff --git a/libgo/go/cmd/go/internal/modload/buildlist.go b/libgo/go/cmd/go/internal/modload/buildlist.go index 0ed9853..604a57b 100644 --- a/libgo/go/cmd/go/internal/modload/buildlist.go +++ b/libgo/go/cmd/go/internal/modload/buildlist.go @@ -7,188 +7,501 @@ package modload import ( "cmd/go/internal/base" "cmd/go/internal/cfg" - "cmd/go/internal/imports" "cmd/go/internal/mvs" + "cmd/go/internal/par" "context" "fmt" - "go/build" "os" + "reflect" + "runtime" + "runtime/debug" "strings" + "sync" + "sync/atomic" - "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. -// It is initialized by calling LoadPackages or ImportFromFiles, -// each of which uses loaded.load. -// -// Ideally, exactly ONE of those functions would be called, -// and exactly once. Most of the time, that's true. -// During "go get" it may not be. TODO(rsc): Figure out if -// that restriction can be established, or else document why not. -// -var buildList []module.Version - -// additionalExplicitRequirements is a list of modules paths for which -// WriteGoMod should record explicit requirements, even if they would be -// selected without those requirements. Each path must also appear in buildList. -var additionalExplicitRequirements []string - // capVersionSlice returns s with its cap reduced to its length. func capVersionSlice(s []module.Version) []module.Version { return s[:len(s):len(s)] } -// LoadAllModules loads and returns the list of modules matching the "all" -// module pattern, starting with the Target module and in a deterministic -// (stable) order, without loading any packages. +// A Requirements represents a logically-immutable set of root module requirements. +type Requirements struct { + // depth is the depth at which the requirement graph is computed. + // + // If eager, the graph includes all transitive requirements regardless of depth. + // + // If lazy, the graph includes only the root modules, the explicit + // requirements of those root modules, and the transitive requirements of only + // the *non-lazy* root modules. + depth modDepth + + // rootModules is the set of module versions explicitly required by the main + // module, sorted and capped to length. It may contain duplicates, and may + // contain multiple versions for a given module path. + rootModules []module.Version + maxRootVersion map[string]string + + // direct is the set of module paths for which we believe the module provides + // a package directly imported by a package or test in the main module. + // + // The "direct" map controls which modules are annotated with "// indirect" + // comments in the go.mod file, and may impact which modules are listed as + // explicit roots (vs. indirect-only dependencies). However, it should not + // have a semantic effect on the build list overall. + // + // The initial direct map is populated from the existing "// indirect" + // comments (or lack thereof) in the go.mod file. It is updated by the + // package loader: dependencies may be promoted to direct if new + // direct imports are observed, and may be demoted to indirect during + // 'go mod tidy' or 'go mod vendor'. + // + // The direct map is keyed by module paths, not module versions. When a + // module's selected version changes, we assume that it remains direct if the + // previous version was a direct dependency. That assumption might not hold in + // rare cases (such as if a dependency splits out a nested module, or merges a + // nested module back into a parent module). + direct map[string]bool + + graphOnce sync.Once // guards writes to (but not reads from) graph + graph atomic.Value // cachedGraph +} + +// A cachedGraph is a non-nil *ModuleGraph, together with any error discovered +// while loading that graph. +type cachedGraph struct { + mg *ModuleGraph + err error // If err is non-nil, mg may be incomplete (but must still be non-nil). +} + +// requirements is the requirement graph for the main module. // -// Modules are loaded automatically (and lazily) in LoadPackages: -// LoadAllModules need only be called if LoadPackages is not, -// typically in commands that care about modules but no particular package. +// It is always non-nil if the main module's go.mod file has been loaded. +// +// This variable should only be read from the loadModFile function, and should +// only be written in the loadModFile and commitRequirements functions. +// All other functions that need or produce a *Requirements should +// accept and/or return an explicit parameter. +var requirements *Requirements + +// newRequirements returns a new requirement set with the given root modules. +// The dependencies of the roots will be loaded lazily at the first call to the +// Graph method. // -// The caller must not modify the returned list, but may append to it. -func LoadAllModules(ctx context.Context) []module.Version { - LoadModFile(ctx) - ReloadBuildList() - WriteGoMod() - return capVersionSlice(buildList) +// The rootModules slice must be sorted according to module.Sort. +// The caller must not modify the rootModules slice or direct map after passing +// them to newRequirements. +// +// If vendoring is in effect, the caller must invoke initVendor on the returned +// *Requirements before any other method. +func newRequirements(depth modDepth, rootModules []module.Version, direct map[string]bool) *Requirements { + for i, m := range rootModules { + if m == Target { + panic(fmt.Sprintf("newRequirements called with untrimmed build list: rootModules[%v] is Target", i)) + } + if m.Path == "" || m.Version == "" { + panic(fmt.Sprintf("bad requirement: rootModules[%v] = %v", i, m)) + } + if i > 0 { + prev := rootModules[i-1] + if prev.Path > m.Path || (prev.Path == m.Path && semver.Compare(prev.Version, m.Version) > 0) { + panic(fmt.Sprintf("newRequirements called with unsorted roots: %v", rootModules)) + } + } + } + + rs := &Requirements{ + depth: depth, + rootModules: capVersionSlice(rootModules), + maxRootVersion: make(map[string]string, len(rootModules)), + direct: direct, + } + + for _, m := range rootModules { + if v, ok := rs.maxRootVersion[m.Path]; ok && cmpVersion(v, m.Version) >= 0 { + continue + } + rs.maxRootVersion[m.Path] = m.Version + } + return rs } -// Selected returns the selected version of the module with the given path, or -// the empty string if the given module has no selected version -// (either because it is not required or because it is the Target module). -func Selected(path string) (version string) { +// initVendor initializes rs.graph from the given list of vendored module +// dependencies, overriding the graph that would normally be loaded from module +// requirements. +func (rs *Requirements) initVendor(vendorList []module.Version) { + rs.graphOnce.Do(func() { + mg := &ModuleGraph{ + g: mvs.NewGraph(cmpVersion, []module.Version{Target}), + } + + if rs.depth == lazy { + // The roots of a lazy module should already include every module in the + // vendor list, because the vendored modules are the same as those + // maintained as roots by the lazy loading “import invariant”. + // + // Just to be sure, we'll double-check that here. + inconsistent := false + for _, m := range vendorList { + if v, ok := rs.rootSelected(m.Path); !ok || v != m.Version { + base.Errorf("go: vendored module %v should be required explicitly in go.mod", m) + inconsistent = true + } + } + if inconsistent { + base.Fatalf("go: %v", errGoModDirty) + } + + // Now we can treat the rest of the module graph as effectively “pruned + // out”, like a more aggressive version of lazy loading: in vendor mode, + // the root requirements *are* the complete module graph. + mg.g.Require(Target, rs.rootModules) + } else { + // The transitive requirements of the main module are not in general available + // from the vendor directory, and we don't actually know how we got from + // the roots to the final build list. + // + // Instead, we'll inject a fake "vendor/modules.txt" module that provides + // those transitive dependencies, and mark it as a dependency of the main + // module. That allows us to elide the actual structure of the module + // graph, but still distinguishes between direct and indirect + // dependencies. + vendorMod := module.Version{Path: "vendor/modules.txt", Version: ""} + mg.g.Require(Target, append(rs.rootModules, vendorMod)) + mg.g.Require(vendorMod, vendorList) + } + + rs.graph.Store(cachedGraph{mg, nil}) + }) +} + +// rootSelected returns the version of the root dependency with the given module +// path, or the zero module.Version and ok=false if the module is not a root +// dependency. +func (rs *Requirements) rootSelected(path string) (version string, ok bool) { if path == Target.Path { - return "" + return Target.Version, true } - for _, m := range buildList { - if m.Path == path { - return m.Version - } + if v, ok := rs.maxRootVersion[path]; ok { + return v, true } - return "" + return "", false } -// EditBuildList edits the global build list by first adding every module in add -// to the existing build list, then adjusting versions (and adding or removing -// requirements as needed) until every module in mustSelect is selected at the -// given version. +// Graph returns the graph of module requirements loaded from the current +// root modules (as reported by RootModules). // -// (Note that the newly-added modules might not be selected in the resulting -// build list: they could be lower than existing requirements or conflict with -// versions in mustSelect.) +// Graph always makes a best effort to load the requirement graph despite any +// errors, and always returns a non-nil *ModuleGraph. // -// If the versions listed in mustSelect are mutually incompatible (due to one of -// the listed modules requiring a higher version of another), EditBuildList -// returns a *ConstraintError and leaves the build list in its previous state. -func EditBuildList(ctx context.Context, add, mustSelect []module.Version) error { - var upgraded = capVersionSlice(buildList) - if len(add) > 0 { - // First, upgrade the build list with any additions. - // In theory we could just append the additions to the build list and let - // mvs.Downgrade take care of resolving the upgrades too, but the - // diagnostics from Upgrade are currently much better in case of errors. - var err error - upgraded, err = mvs.Upgrade(Target, &mvsReqs{buildList: upgraded}, add...) - if err != nil { - return err +// If the requirements of any relevant module fail to load, Graph also +// returns a non-nil error of type *mvs.BuildListError. +func (rs *Requirements) Graph(ctx context.Context) (*ModuleGraph, error) { + rs.graphOnce.Do(func() { + mg, mgErr := readModGraph(ctx, rs.depth, rs.rootModules) + rs.graph.Store(cachedGraph{mg, mgErr}) + }) + cached := rs.graph.Load().(cachedGraph) + return cached.mg, cached.err +} + +// IsDirect returns whether the given module provides a package directly +// imported by a package or test in the main module. +func (rs *Requirements) IsDirect(path string) bool { + return rs.direct[path] +} + +// A ModuleGraph represents the complete graph of module dependencies +// of a main module. +// +// If the main module is lazily loaded, the graph does not include +// transitive dependencies of non-root (implicit) dependencies. +type ModuleGraph struct { + g *mvs.Graph + loadCache par.Cache // module.Version → summaryError + + buildListOnce sync.Once + buildList []module.Version +} + +// A summaryError is either a non-nil modFileSummary or a non-nil error +// encountered while reading or parsing that summary. +type summaryError struct { + summary *modFileSummary + err error +} + +var readModGraphDebugOnce sync.Once + +// readModGraph reads and returns the module dependency graph starting at the +// given roots. +// +// Unlike LoadModGraph, readModGraph does not attempt to diagnose or update +// inconsistent roots. +func readModGraph(ctx context.Context, depth modDepth, roots []module.Version) (*ModuleGraph, error) { + if depth == lazy { + readModGraphDebugOnce.Do(func() { + for _, f := range strings.Split(os.Getenv("GODEBUG"), ",") { + switch f { + case "lazymod=log": + debug.PrintStack() + fmt.Fprintf(os.Stderr, "go: read full module graph.\n") + case "lazymod=strict": + debug.PrintStack() + base.Fatalf("go: read full module graph (forbidden by GODEBUG=lazymod=strict).") + } + } + }) + } + + var ( + mu sync.Mutex // guards mg.g and hasError during loading + hasError bool + mg = &ModuleGraph{ + g: mvs.NewGraph(cmpVersion, []module.Version{Target}), } + ) + mg.g.Require(Target, roots) + + var ( + loadQueue = par.NewQueue(runtime.GOMAXPROCS(0)) + loadingEager sync.Map // module.Version → nil; the set of modules that have been or are being loaded via eager roots + ) + + // loadOne synchronously loads the explicit requirements for module m. + // It does not load the transitive requirements of m even if the go version in + // m's go.mod file indicates eager loading. + loadOne := func(m module.Version) (*modFileSummary, error) { + cached := mg.loadCache.Do(m, func() interface{} { + summary, err := goModSummary(m) + + mu.Lock() + if err == nil { + mg.g.Require(m, summary.require) + } else { + hasError = true + } + mu.Unlock() + + return summaryError{summary, err} + }).(summaryError) + + return cached.summary, cached.err } - downgraded, err := mvs.Downgrade(Target, &mvsReqs{buildList: append(upgraded, mustSelect...)}, mustSelect...) - if err != nil { - return err + var enqueue func(m module.Version, depth modDepth) + enqueue = func(m module.Version, depth modDepth) { + if m.Version == "none" { + return + } + + if depth == eager { + if _, dup := loadingEager.LoadOrStore(m, nil); dup { + // m has already been enqueued for loading. Since eager loading may + // follow cycles in the the requirement graph, we need to return early + // to avoid making the load queue infinitely long. + return + } + } + + loadQueue.Add(func() { + summary, err := loadOne(m) + if err != nil { + return // findError will report the error later. + } + + // If the version in m's go.mod file implies eager loading, then we cannot + // assume that the explicit requirements of m (added by loadOne) are + // sufficient to build the packages it contains. We must load its full + // transitive dependency graph to be sure that we see all relevant + // dependencies. + if depth == eager || summary.depth == eager { + for _, r := range summary.require { + enqueue(r, eager) + } + } + }) } - final, err := mvs.Upgrade(Target, &mvsReqs{buildList: downgraded}, mustSelect...) - if err != nil { - return err + for _, m := range roots { + enqueue(m, depth) } + <-loadQueue.Idle() - selected := make(map[string]module.Version, len(final)) - for _, m := range final { - selected[m.Path] = m + if hasError { + return mg, mg.findError() } - inconsistent := false - for _, m := range mustSelect { - s, ok := selected[m.Path] - if !ok { - if m.Version != "none" { - panic(fmt.Sprintf("internal error: mvs.BuildList lost %v", m)) - } - continue - } - if s.Version != m.Version { - inconsistent = true - break - } + return mg, nil +} + +// RequiredBy returns the dependencies required by module m in the graph, +// or ok=false if module m's dependencies are not relevant (such as if they +// are pruned out by lazy loading). +// +// The caller must not modify the returned slice, but may safely append to it +// and may rely on it not to be modified. +func (mg *ModuleGraph) RequiredBy(m module.Version) (reqs []module.Version, ok bool) { + return mg.g.RequiredBy(m) +} + +// Selected returns the selected version of the module with the given path. +// +// If no version is selected, Selected returns version "none". +func (mg *ModuleGraph) Selected(path string) (version string) { + return mg.g.Selected(path) +} + +// WalkBreadthFirst invokes f once, in breadth-first order, for each module +// version other than "none" that appears in the graph, regardless of whether +// that version is selected. +func (mg *ModuleGraph) WalkBreadthFirst(f func(m module.Version)) { + mg.g.WalkBreadthFirst(f) +} + +// BuildList returns the selected versions of all modules present in the graph, +// beginning with Target. +// +// The order of the remaining elements in the list is deterministic +// but arbitrary. +// +// The caller must not modify the returned list, but may safely append to it +// and may rely on it not to be modified. +func (mg *ModuleGraph) BuildList() []module.Version { + mg.buildListOnce.Do(func() { + mg.buildList = capVersionSlice(mg.g.BuildList()) + }) + return mg.buildList +} + +func (mg *ModuleGraph) findError() error { + errStack := mg.g.FindPath(func(m module.Version) bool { + cached := mg.loadCache.Get(m) + return cached != nil && cached.(summaryError).err != nil + }) + if len(errStack) > 0 { + err := mg.loadCache.Get(errStack[len(errStack)-1]).(summaryError).err + var noUpgrade func(from, to module.Version) bool + return mvs.NewBuildListError(err, errStack, noUpgrade) } - if !inconsistent { - buildList = final - additionalExplicitRequirements = make([]string, 0, len(mustSelect)) - for _, m := range mustSelect { - if m.Version != "none" { - additionalExplicitRequirements = append(additionalExplicitRequirements, m.Path) - } + return nil +} + +func (mg *ModuleGraph) allRootsSelected() bool { + roots, _ := mg.g.RequiredBy(Target) + for _, m := range roots { + if mg.Selected(m.Path) != m.Version { + return false } - return nil } + return true +} - // We overshot one or more of the modules in mustSelected, which means that - // Downgrade removed something in mustSelect because it conflicted with - // something else in mustSelect. - // - // Walk the requirement graph to find the conflict. - // - // TODO(bcmills): Ideally, mvs.Downgrade (or a replacement for it) would do - // this directly. +// LoadModGraph loads and returns the graph of module dependencies of the main module, +// without loading any packages. +// +// If the goVersion string is non-empty, the returned graph is the graph +// as interpreted by the given Go version (instead of the version indicated +// in the go.mod file). +// +// Modules are loaded automatically (and lazily) in LoadPackages: +// LoadModGraph need only be called if LoadPackages is not, +// typically in commands that care about modules but no particular package. +func LoadModGraph(ctx context.Context, goVersion string) *ModuleGraph { + rs := LoadModFile(ctx) - reqs := &mvsReqs{buildList: final} - reason := map[module.Version]module.Version{} - for _, m := range mustSelect { - reason[m] = m - } - queue := mustSelect[:len(mustSelect):len(mustSelect)] - for len(queue) > 0 { - var m module.Version - m, queue = queue[0], queue[1:] - required, err := reqs.Required(m) - if err != nil { - return err + if goVersion != "" { + depth := modDepthFromGoVersion(goVersion) + if depth == eager && rs.depth != eager { + // Use newRequirements instead of convertDepth because convertDepth + // also updates roots; here, we want to report the unmodified roots + // even though they may seem inconsistent. + rs = newRequirements(eager, rs.rootModules, rs.direct) } - for _, r := range required { - if _, ok := reason[r]; !ok { - reason[r] = reason[m] - queue = append(queue, r) - } + + mg, err := rs.Graph(ctx) + if err != nil { + base.Fatalf("go: %v", err) } + return mg } - var conflicts []Conflict - for _, m := range mustSelect { - s, ok := selected[m.Path] - if !ok { - if m.Version != "none" { - panic(fmt.Sprintf("internal error: mvs.BuildList lost %v", m)) - } - continue - } - if s.Version != m.Version { - conflicts = append(conflicts, Conflict{ - Source: reason[s], - Dep: s, - Constraint: m, - }) + rs, mg, err := expandGraph(ctx, rs) + if err != nil { + base.Fatalf("go: %v", err) + } + + commitRequirements(ctx, modFileGoVersion(), rs) + return mg +} + +// expandGraph loads the complete module graph from rs. +// +// If the complete graph reveals that some root of rs is not actually the +// selected version of its path, expandGraph computes a new set of roots that +// are consistent. (When lazy loading is implemented, this may result in +// upgrades to other modules due to requirements that were previously pruned +// out.) +// +// expandGraph returns the updated roots, along with the module graph loaded +// from those roots and any error encountered while loading that graph. +// expandGraph returns non-nil requirements and a non-nil graph regardless of +// errors. On error, the roots might not be updated to be consistent. +func expandGraph(ctx context.Context, rs *Requirements) (*Requirements, *ModuleGraph, error) { + mg, mgErr := rs.Graph(ctx) + if mgErr != nil { + // Without the graph, we can't update the roots: we don't know which + // versions of transitive dependencies would be selected. + return rs, mg, mgErr + } + + if !mg.allRootsSelected() { + // The roots of rs are not consistent with the rest of the graph. Update + // them. In an eager module this is a no-op for the build list as a whole — + // it just promotes what were previously transitive requirements to be + // roots — but in a lazy module it may pull in previously-irrelevant + // transitive dependencies. + + newRS, rsErr := updateRoots(ctx, rs.direct, rs, nil, nil, false) + if rsErr != nil { + // Failed to update roots, perhaps because of an error in a transitive + // dependency needed for the update. Return the original Requirements + // instead. + return rs, mg, rsErr } + rs = newRS + mg, mgErr = rs.Graph(ctx) } - return &ConstraintError{ - Conflicts: conflicts, + return rs, mg, mgErr +} + +// EditBuildList edits the global build list by first adding every module in add +// to the existing build list, then adjusting versions (and adding or removing +// requirements as needed) until every module in mustSelect is selected at the +// given version. +// +// (Note that the newly-added modules might not be selected in the resulting +// build list: they could be lower than existing requirements or conflict with +// versions in mustSelect.) +// +// If the versions listed in mustSelect are mutually incompatible (due to one of +// the listed modules requiring a higher version of another), EditBuildList +// returns a *ConstraintError and leaves the build list in its previous state. +// +// On success, EditBuildList reports whether the selected version of any module +// in the build list may have been changed (possibly to or from "none") as a +// result. +func EditBuildList(ctx context.Context, add, mustSelect []module.Version) (changed bool, err error) { + rs, changed, err := editRequirements(ctx, LoadModFile(ctx), add, mustSelect) + if err != nil { + return false, err } + commitRequirements(ctx, modFileGoVersion(), rs) + return changed, err } // A ConstraintError describes inconsistent constraints in EditBuildList @@ -216,93 +529,574 @@ type Conflict struct { Constraint module.Version } -// ReloadBuildList resets the state of loaded packages, then loads and returns -// the build list set by EditBuildList. -func ReloadBuildList() []module.Version { - loaded = loadFromRoots(loaderParams{ - PackageOpts: PackageOpts{ - Tags: imports.Tags(), - }, - listRoots: func() []string { return nil }, - allClosesOverTests: index.allPatternClosesOverTests(), // but doesn't matter because the root list is empty. - }) - return capVersionSlice(buildList) +// tidyRoots trims the root dependencies to the minimal requirements needed to +// both retain the same versions of all packages in pkgs and satisfy the +// lazy loading invariants (if applicable). +func tidyRoots(ctx context.Context, rs *Requirements, pkgs []*loadPkg) (*Requirements, error) { + if rs.depth == eager { + return tidyEagerRoots(ctx, rs.direct, pkgs) + } + return tidyLazyRoots(ctx, rs.direct, pkgs) +} + +func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) { + if rs.depth == eager { + return updateEagerRoots(ctx, direct, rs, add) + } + return updateLazyRoots(ctx, direct, rs, pkgs, add, rootsImported) +} + +// tidyLazyRoots returns a minimal set of root requirements that maintains the +// "lazy loading" invariants of the go.mod file for the given packages: +// +// 1. For each package marked with pkgInAll, the module path that provided that +// package is included as a root. +// 2. For all packages, the module that provided that package either remains +// selected at the same version or is upgraded by the dependencies of a +// root. +// +// If any module that provided a package has been upgraded above its previous, +// version, the caller may need to reload and recompute the package graph. +// +// To ensure that the loading process eventually converges, the caller should +// add any needed roots from the tidy root set (without removing existing untidy +// roots) until the set of roots has converged. +func tidyLazyRoots(ctx context.Context, direct map[string]bool, pkgs []*loadPkg) (*Requirements, error) { + var ( + roots []module.Version + pathIncluded = map[string]bool{Target.Path: true} + ) + // We start by adding roots for every package in "all". + // + // Once that is done, we may still need to add more roots to cover upgraded or + // otherwise-missing test dependencies for packages in "all". For those test + // dependencies, we prefer to add roots for packages with shorter import + // stacks first, on the theory that the module requirements for those will + // tend to fill in the requirements for their transitive imports (which have + // deeper import stacks). So we add the missing dependencies for one depth at + // a time, starting with the packages actually in "all" and expanding outwards + // until we have scanned every package that was loaded. + var ( + queue []*loadPkg + queued = map[*loadPkg]bool{} + ) + for _, pkg := range pkgs { + if !pkg.flags.has(pkgInAll) { + continue + } + if pkg.fromExternalModule() && !pathIncluded[pkg.mod.Path] { + roots = append(roots, pkg.mod) + pathIncluded[pkg.mod.Path] = true + } + queue = append(queue, pkg) + queued[pkg] = true + } + module.Sort(roots) + tidy := newRequirements(lazy, roots, direct) + + for len(queue) > 0 { + roots = tidy.rootModules + mg, err := tidy.Graph(ctx) + if err != nil { + return nil, err + } + + prevQueue := queue + queue = nil + for _, pkg := range prevQueue { + m := pkg.mod + if m.Path == "" { + continue + } + for _, dep := range pkg.imports { + if !queued[dep] { + queue = append(queue, dep) + queued[dep] = true + } + } + if pkg.test != nil && !queued[pkg.test] { + queue = append(queue, pkg.test) + queued[pkg.test] = true + } + if !pathIncluded[m.Path] { + if s := mg.Selected(m.Path); cmpVersion(s, m.Version) < 0 { + roots = append(roots, m) + } + pathIncluded[m.Path] = true + } + } + + if len(roots) > len(tidy.rootModules) { + module.Sort(roots) + tidy = newRequirements(lazy, roots, tidy.direct) + } + } + + _, err := tidy.Graph(ctx) + if err != nil { + return nil, err + } + return tidy, nil } -// 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. +// updateLazyRoots returns a set of root requirements that maintains the “lazy +// loading” invariants of the go.mod file: +// +// 1. The selected version of the module providing each package marked with +// either pkgInAll or pkgIsRoot is included as a root. +// Note that certain root patterns (such as '...') may explode the root set +// to contain every module that provides any package imported (or merely +// required) by any other module. +// 2. Each root appears only once, at the selected version of its path +// (if rs.graph is non-nil) or at the highest version otherwise present as a +// root (otherwise). +// 3. Every module path that appears as a root in rs remains a root. +// 4. Every version in add is selected at its given version unless upgraded by +// (the dependencies of) an existing root or another module in add. +// +// The packages in pkgs are assumed to have been loaded from either the roots of +// rs or the modules selected in the graph of rs. +// +// The above invariants together imply the “lazy loading” invariants for the +// go.mod file: +// +// 1. (The import invariant.) Every module that provides a package transitively +// imported by any package or test in the main module is included as a root. +// This follows by induction from (1) and (3) above. Transitively-imported +// packages loaded during this invocation are marked with pkgInAll (1), +// and by hypothesis any transitively-imported packages loaded in previous +// invocations were already roots in rs (3). +// +// 2. (The argument invariant.) Every module that provides a package matching +// an explicit package pattern is included as a root. This follows directly +// from (1): packages matching explicit package patterns are marked with +// pkgIsRoot. +// +// 3. (The completeness invariant.) Every module that contributed any package +// to the build is required by either the main module or one of the modules +// it requires explicitly. This invariant is left up to the caller, who must +// not load packages from outside the module graph but may add roots to the +// graph, but is facilited by (3). If the caller adds roots to the graph in +// order to resolve missing packages, then updateLazyRoots will retain them, +// the selected versions of those roots cannot regress, and they will +// eventually be written back to the main module's go.mod file. // -// If allowError is false, such an error terminates the program. -func CheckTidyVersion(ctx context.Context, allowError bool) { - LoadModFile(ctx) - if index.goVersionV == "" { - return +// (See https://golang.org/design/36460-lazy-module-loading#invariants for more +// detail.) +func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) { + roots := rs.rootModules + rootsUpgraded := false + + spotCheckRoot := map[module.Version]bool{} + + // “The selected version of the module providing each package marked with + // either pkgInAll or pkgIsRoot is included as a root.” + needSort := false + for _, pkg := range pkgs { + if !pkg.fromExternalModule() { + // pkg was not loaded from a module dependency, so we don't need + // to do anything special to maintain that dependency. + continue + } + + switch { + case pkg.flags.has(pkgInAll): + // pkg is transitively imported by a package or test in the main module. + // We need to promote the module that maintains it to a root: if some + // other module depends on the main module, and that other module also + // uses lazy loading, it will expect to find all of our transitive + // dependencies by reading just our go.mod file, not the go.mod files of + // everything we depend on. + // + // (This is the “import invariant” that makes lazy loading possible.) + + case rootsImported && pkg.flags.has(pkgFromRoot): + // pkg is a transitive dependency of some root, and we are treating the + // roots as if they are imported by the main module (as in 'go get'). + + case pkg.flags.has(pkgIsRoot): + // pkg is a root of the package-import graph. (Generally this means that + // it matches a command-line argument.) We want future invocations of the + // 'go' command — such as 'go test' on the same package — to continue to + // use the same versions of its dependencies that we are using right now. + // So we need to bring this package's dependencies inside the lazy-loading + // horizon. + // + // Making the module containing this package a root of the module graph + // does exactly that: if the module containing the package is lazy it + // should satisfy the import invariant itself, so all of its dependencies + // should be in its go.mod file, and if the module containing the package + // is eager then if we make it a root we will load all of its transitive + // dependencies into the module graph. + // + // (This is the “argument invariant” of lazy loading, and is important for + // reproducibility.) + + default: + // pkg is a dependency of some other package outside of the main module. + // As far as we know it's not relevant to the main module (and thus not + // relevant to consumers of the main module either), and its dependencies + // should already be in the module graph — included in the dependencies of + // the package that imported it. + continue + } + + if _, ok := rs.rootSelected(pkg.mod.Path); ok { + // It is possible that the main module's go.mod file is incomplete or + // otherwise erroneous — for example, perhaps the author forgot to 'git + // add' their updated go.mod file after adding a new package import, or + // perhaps they made an edit to the go.mod file using a third-party tool + // ('git merge'?) that doesn't maintain consistency for module + // dependencies. If that happens, ideally we want to detect the missing + // requirements and fix them up here. + // + // However, we also need to be careful not to be too aggressive. For + // transitive dependencies of external tests, the go.mod file for the + // module containing the test itself is expected to provide all of the + // relevant dependencies, and we explicitly don't want to pull in + // requirements on *irrelevant* requirements that happen to occur in the + // go.mod files for these transitive-test-only dependencies. (See the test + // in mod_lazy_test_horizon.txt for a concrete example. + // + // The “goldilocks zone” seems to be to spot-check exactly the same + // modules that we promote to explicit roots: namely, those that provide + // packages transitively imported by the main module, and those that + // provide roots of the package-import graph. That will catch erroneous + // edits to the main module's go.mod file and inconsistent requirements in + // dependencies that provide imported packages, but will ignore erroneous + // or misleading requirements in dependencies that aren't obviously + // relevant to the packages in the main module. + spotCheckRoot[pkg.mod] = true + } else { + roots = append(roots, pkg.mod) + rootsUpgraded = true + // The roots slice was initially sorted because rs.rootModules was sorted, + // but the root we just added could be out of order. + needSort = true + } } - 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) + for _, m := range add { + if v, ok := rs.rootSelected(m.Path); !ok || cmpVersion(v, m.Version) < 0 { + roots = append(roots, m) + rootsUpgraded = true + needSort = true + } + } + if needSort { + module.Sort(roots) } - 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) + // "Each root appears only once, at the selected version of its path ….” + for { + var mg *ModuleGraph + if rootsUpgraded { + // We've added or upgraded one or more roots, so load the full module + // graph so that we can update those roots to be consistent with other + // requirements. + if cfg.BuildMod != "mod" { + // Our changes to the roots may have moved dependencies into or out of + // the lazy-loading horizon, which could in turn change the selected + // versions of other modules. (Unlike for eager modules, for lazy + // modules adding or removing an explicit root is a semantic change, not + // just a cosmetic one.) + return rs, errGoModDirty + } + + rs = newRequirements(lazy, roots, direct) + var err error + mg, err = rs.Graph(ctx) + if err != nil { + return rs, err + } } else { - base.Fatalf("go mod tidy: go.mod file indicates go %s, but maximum supported version is %s\n", have, max) + // Since none of the roots have been upgraded, we have no reason to + // suspect that they are inconsistent with the requirements of any other + // roots. Only look at the full module graph if we've already loaded it; + // otherwise, just spot-check the explicit requirements of the roots from + // which we loaded packages. + if rs.graph.Load() != nil { + // We've already loaded the full module graph, which includes the + // requirements of all of the root modules — even the transitive + // requirements, if they are eager! + mg, _ = rs.Graph(ctx) + } else if cfg.BuildMod == "vendor" { + // We can't spot-check the requirements of other modules because we + // don't in general have their go.mod files available in the vendor + // directory. (Fortunately this case is impossible, because mg.graph is + // always non-nil in vendor mode!) + panic("internal error: rs.graph is unexpectedly nil with -mod=vendor") + } else if !spotCheckRoots(ctx, rs, spotCheckRoot) { + // We spot-checked the explicit requirements of the roots that are + // relevant to the packages we've loaded. Unfortunately, they're + // inconsistent in some way; we need to load the full module graph + // so that we can fix the roots properly. + var err error + mg, err = rs.Graph(ctx) + if err != nil { + return rs, err + } + } + } + + roots = make([]module.Version, 0, len(rs.rootModules)) + rootsUpgraded = false + inRootPaths := make(map[string]bool, len(rs.rootModules)+1) + inRootPaths[Target.Path] = true + for _, m := range rs.rootModules { + if inRootPaths[m.Path] { + // This root specifies a redundant path. We already retained the + // selected version of this path when we saw it before, so omit the + // redundant copy regardless of its version. + // + // When we read the full module graph, we include the dependencies of + // every root even if that root is redundant. That better preserves + // reproducibility if, say, some automated tool adds a redundant + // 'require' line and then runs 'go mod tidy' to try to make everything + // consistent, since the requirements of the older version are carried + // over. + // + // So omitting a root that was previously present may *reduce* the + // selected versions of non-roots, but merely removing a requirement + // cannot *increase* the selected versions of other roots as a result — + // we don't need to mark this change as an upgrade. (This particular + // change cannot invalidate any other roots.) + continue + } + + var v string + if mg == nil { + v, _ = rs.rootSelected(m.Path) + } else { + v = mg.Selected(m.Path) + } + roots = append(roots, module.Version{Path: m.Path, Version: v}) + inRootPaths[m.Path] = true + if v != m.Version { + rootsUpgraded = true + } } + // Note that rs.rootModules was already sorted by module path and version, + // and we appended to the roots slice in the same order and guaranteed that + // each path has only one version, so roots is also sorted by module path + // and (trivially) version. + + if !rootsUpgraded { + // The root set has converged: every root going into this iteration was + // already at its selected version, although we have have removed other + // (redundant) roots for the same path. + break + } + } + + if rs.depth == lazy && reflect.DeepEqual(roots, rs.rootModules) && reflect.DeepEqual(direct, rs.direct) { + // The root set is unchanged and rs was already lazy, so keep rs to + // preserve its cached ModuleGraph (if any). + return rs, nil } + return newRequirements(lazy, roots, direct), nil } -// TidyBuildList trims the build list to the minimal requirements needed to -// retain the same versions of all packages from the preceding call to -// LoadPackages. -func TidyBuildList() { - used := map[module.Version]bool{Target: true} - for _, pkg := range loaded.pkgs { - used[pkg.mod] = true +// spotCheckRoots reports whether the versions of the roots in rs satisfy the +// explicit requirements of the modules in mods. +func spotCheckRoots(ctx context.Context, rs *Requirements, mods map[module.Version]bool) bool { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + work := par.NewQueue(runtime.GOMAXPROCS(0)) + for m := range mods { + m := m + work.Add(func() { + if ctx.Err() != nil { + return + } + + summary, err := goModSummary(m) + if err != nil { + cancel() + return + } + + for _, r := range summary.require { + if v, ok := rs.rootSelected(r.Path); ok && cmpVersion(v, r.Version) < 0 { + cancel() + return + } + } + }) + } + <-work.Idle() + + if ctx.Err() != nil { + // Either we failed a spot-check, or the caller no longer cares about our + // answer anyway. + return false } - keep := []module.Version{Target} - var direct []string - for _, m := range buildList[1:] { - if used[m] { + return true +} + +// tidyEagerRoots returns a minimal set of root requirements that maintains the +// selected version of every module that provided a package in pkgs, and +// includes the selected version of every such module in direct as a root. +func tidyEagerRoots(ctx context.Context, direct map[string]bool, pkgs []*loadPkg) (*Requirements, error) { + var ( + keep []module.Version + keptPath = map[string]bool{} + ) + var ( + rootPaths []string // module paths that should be included as roots + inRootPaths = map[string]bool{} + ) + for _, pkg := range pkgs { + if !pkg.fromExternalModule() { + continue + } + if m := pkg.mod; !keptPath[m.Path] { keep = append(keep, m) - if loaded.direct[m.Path] { - direct = append(direct, m.Path) - } - } else if cfg.BuildV { - if _, ok := index.require[m]; ok { - fmt.Fprintf(os.Stderr, "unused %s\n", m.Path) + keptPath[m.Path] = true + if direct[m.Path] && !inRootPaths[m.Path] { + rootPaths = append(rootPaths, m.Path) + inRootPaths[m.Path] = true } } } - min, err := mvs.Req(Target, direct, &mvsReqs{buildList: keep}) + min, err := mvs.Req(Target, rootPaths, &mvsReqs{roots: keep}) if err != nil { - base.Fatalf("go: %v", err) + return nil, err } - buildList = append([]module.Version{Target}, min...) + return newRequirements(eager, min, direct), nil } -// checkMultiplePaths verifies that a given module path is used as itself -// or as a replacement for another module, but not both at the same time. +// updateEagerRoots returns a set of root requirements that includes the selected +// version of every module path in direct as a root, and maintains the selected +// version of every module selected in the graph of rs. // -// (See https://golang.org/issue/26607 and https://golang.org/issue/34650.) -func checkMultiplePaths() { - firstPath := make(map[module.Version]string, len(buildList)) - for _, mod := range buildList { - src := mod - if rep := Replacement(mod); rep.Path != "" { - src = rep +// The roots are updated such that: +// +// 1. The selected version of every module path in direct is included as a root +// (if it is not "none"). +// 2. Each root is the selected version of its path. (We say that such a root +// set is “consistent”.) +// 3. Every version selected in the graph of rs remains selected unless upgraded +// by a dependency in add. +// 4. Every version in add is selected at its given version unless upgraded by +// (the dependencies of) an existing root or another module in add. +func updateEagerRoots(ctx context.Context, direct map[string]bool, rs *Requirements, add []module.Version) (*Requirements, error) { + mg, err := rs.Graph(ctx) + if err != nil { + // We can't ignore errors in the module graph even if the user passed the -e + // flag to try to push past them. If we can't load the complete module + // dependencies, then we can't reliably compute a minimal subset of them. + return rs, err + } + + if cfg.BuildMod != "mod" { + // Instead of actually updating the requirements, just check that no updates + // are needed. + if rs == nil { + // We're being asked to reconstruct the requirements from scratch, + // but we aren't even allowed to modify them. + return rs, errGoModDirty } - if prev, ok := firstPath[src]; !ok { - firstPath[src] = mod.Path - } else if prev != mod.Path { - base.Errorf("go: %s@%s used for two different module paths (%s and %s)", src.Path, src.Version, prev, mod.Path) + for _, m := range rs.rootModules { + if m.Version != mg.Selected(m.Path) { + // The root version v is misleading: the actual selected version is higher. + return rs, errGoModDirty + } } + for _, m := range add { + if m.Version != mg.Selected(m.Path) { + return rs, errGoModDirty + } + } + for mPath := range direct { + if _, ok := rs.rootSelected(mPath); !ok { + // Module m is supposed to be listed explicitly, but isn't. + // + // Note that this condition is also detected (and logged with more + // detail) earlier during package loading, so it shouldn't actually be + // possible at this point — this is just a defense in depth. + return rs, errGoModDirty + } + } + + // No explicit roots are missing and all roots are already at the versions + // we want to keep. Any other changes we would make are purely cosmetic, + // such as pruning redundant indirect dependencies. Per issue #34822, we + // ignore cosmetic changes when we cannot update the go.mod file. + return rs, nil + } + + var ( + rootPaths []string // module paths that should be included as roots + inRootPaths = map[string]bool{} + ) + for _, root := range rs.rootModules { + // If the selected version of the root is the same as what was already + // listed in the go.mod file, retain it as a root (even if redundant) to + // avoid unnecessary churn. (See https://golang.org/issue/34822.) + // + // We do this even for indirect requirements, since we don't know why they + // were added and they could become direct at any time. + if !inRootPaths[root.Path] && mg.Selected(root.Path) == root.Version { + rootPaths = append(rootPaths, root.Path) + inRootPaths[root.Path] = true + } + } + + // “The selected version of every module path in direct is included as a root.” + // + // This is only for convenience and clarity for end users: in an eager module, + // the choice of explicit vs. implicit dependency has no impact on MVS + // selection (for itself or any other module). + keep := append(mg.BuildList()[1:], add...) + for _, m := range keep { + if direct[m.Path] && !inRootPaths[m.Path] { + rootPaths = append(rootPaths, m.Path) + inRootPaths[m.Path] = true + } + } + + min, err := mvs.Req(Target, rootPaths, &mvsReqs{roots: keep}) + if err != nil { + return rs, err + } + if rs.depth == eager && reflect.DeepEqual(min, rs.rootModules) && reflect.DeepEqual(direct, rs.direct) { + // The root set is unchanged and rs was already eager, so keep rs to + // preserve its cached ModuleGraph (if any). + return rs, nil + } + return newRequirements(eager, min, direct), nil +} + +// convertDepth returns a version of rs with the given depth. +// If rs already has the given depth, convertDepth returns rs unmodified. +func convertDepth(ctx context.Context, rs *Requirements, depth modDepth) (*Requirements, error) { + if rs.depth == depth { + return rs, nil + } + + if depth == eager { + // We are converting a lazy module to an eager one. The roots of an eager + // module graph are a superset of the roots of a lazy graph, so we don't + // need to add any new roots — we just need to prune away the ones that are + // redundant given eager loading, which is exactly what updateEagerRoots + // does. + return updateEagerRoots(ctx, rs.direct, rs, nil) + } + + // We are converting an eager module to a lazy one. The module graph of an + // eager module includes the transitive dependencies of every module in the + // build list. + // + // Hey, we can express that as a lazy root set! “Include the transitive + // dependencies of every module in the build list” is exactly what happens in + // a lazy module if we promote every module in the build list to a root! + mg, err := rs.Graph(ctx) + if err != nil { + return rs, err } - base.ExitIfErrors() + return newRequirements(lazy, mg.BuildList()[1:], rs.direct), nil } diff --git a/libgo/go/cmd/go/internal/modload/edit.go b/libgo/go/cmd/go/internal/modload/edit.go new file mode 100644 index 0000000..c350b9d --- /dev/null +++ b/libgo/go/cmd/go/internal/modload/edit.go @@ -0,0 +1,569 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package modload + +import ( + "cmd/go/internal/mvs" + "context" + "reflect" + "sort" + + "golang.org/x/mod/module" + "golang.org/x/mod/semver" +) + +// editRequirements returns an edited version of rs such that: +// +// 1. Each module version in mustSelect is selected. +// +// 2. Each module version in tryUpgrade is upgraded toward the indicated +// version as far as can be done without violating (1). +// +// 3. Each module version in rs.rootModules (or rs.graph, if rs.depth is eager) +// is downgraded from its original version only to the extent needed to +// satisfy (1), or upgraded only to the extent needed to satisfy (1) and +// (2). +// +// 4. No module is upgraded above the maximum version of its path found in the +// dependency graph of rs, the combined dependency graph of the versions in +// mustSelect, or the dependencies of each individual module version in +// tryUpgrade. +// +// Generally, the module versions in mustSelect are due to the module or a +// package within the module matching an explicit command line argument to 'go +// get', and the versions in tryUpgrade are transitive dependencies that are +// either being upgraded by 'go get -u' or being added to satisfy some +// otherwise-missing package import. +func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSelect []module.Version) (edited *Requirements, changed bool, err error) { + limiter, err := limiterForEdit(ctx, rs, tryUpgrade, mustSelect) + if err != nil { + return rs, false, err + } + + var conflicts []Conflict + for _, m := range mustSelect { + conflict, err := limiter.Select(m) + if err != nil { + return rs, false, err + } + if conflict.Path != "" { + conflicts = append(conflicts, Conflict{ + Source: m, + Dep: conflict, + Constraint: module.Version{ + Path: conflict.Path, + Version: limiter.max[conflict.Path], + }, + }) + } + } + if len(conflicts) > 0 { + return rs, false, &ConstraintError{Conflicts: conflicts} + } + + mods, changed, err := selectPotentiallyImportedModules(ctx, limiter, rs, tryUpgrade) + if err != nil { + return rs, false, err + } + + var roots []module.Version + if rs.depth == eager { + // In an eager module, modules that provide packages imported by the main + // module may either be explicit roots or implicit transitive dependencies. + // We promote the modules in mustSelect to be explicit requirements. + var rootPaths []string + for _, m := range mustSelect { + if m.Version != "none" && m.Path != Target.Path { + rootPaths = append(rootPaths, m.Path) + } + } + if !changed && len(rootPaths) == 0 { + // The build list hasn't changed and we have no new roots to add. + // We don't need to recompute the minimal roots for the module. + return rs, false, nil + } + + for _, m := range mods { + if v, ok := rs.rootSelected(m.Path); ok && (v == m.Version || rs.direct[m.Path]) { + // m.Path was formerly a root, and either its version hasn't changed or + // we believe that it provides a package directly imported by a package + // or test in the main module. For now we'll assume that it is still + // relevant enough to remain a root. If we actually load all of the + // packages and tests in the main module (which we are not doing here), + // we can revise the explicit roots at that point. + rootPaths = append(rootPaths, m.Path) + } + } + + roots, err = mvs.Req(Target, rootPaths, &mvsReqs{roots: mods}) + if err != nil { + return nil, false, err + } + } else { + // In a lazy module, every module that provides a package imported by the + // main module must be retained as a root. + roots = mods + if !changed { + // Because the roots we just computed are unchanged, the entire graph must + // be the same as it was before. Save the original rs, since we have + // probably already loaded its requirement graph. + return rs, false, nil + } + } + + // A module that is not even in the build list necessarily cannot provide + // any imported packages. Mark as direct only the direct modules that are + // still in the build list. + // + // TODO(bcmills): Would it make more sense to leave the direct map as-is + // but allow it to refer to modules that are no longer in the build list? + // That might complicate updateRoots, but it may be cleaner in other ways. + direct := make(map[string]bool, len(rs.direct)) + for _, m := range roots { + if rs.direct[m.Path] { + direct[m.Path] = true + } + } + return newRequirements(rs.depth, roots, direct), changed, nil +} + +// limiterForEdit returns a versionLimiter with its max versions set such that +// the max version for every module path in mustSelect is the version listed +// there, and the max version for every other module path is the maximum version +// of its path found in the dependency graph of rs, the combined dependency +// graph of the versions in mustSelect, or the dependencies of each individual +// module version in tryUpgrade. +func limiterForEdit(ctx context.Context, rs *Requirements, tryUpgrade, mustSelect []module.Version) (*versionLimiter, error) { + mg, err := rs.Graph(ctx) + if err != nil { + return nil, err + } + + maxVersion := map[string]string{} // module path → version + restrictTo := func(m module.Version) { + v, ok := maxVersion[m.Path] + if !ok || cmpVersion(v, m.Version) > 0 { + maxVersion[m.Path] = m.Version + } + } + + if rs.depth == eager { + // Eager go.mod files don't indicate which transitive dependencies are + // actually relevant to the main module, so we have to assume that any module + // that could have provided any package — that is, any module whose selected + // version was not "none" — may be relevant. + for _, m := range mg.BuildList() { + restrictTo(m) + } + } else { + // The go.mod file explicitly records every module that provides a package + // imported by the main module. + // + // If we need to downgrade an existing root or a new root found in + // tryUpgrade, we don't want to allow that downgrade to incidentally upgrade + // a module imported by the main module to some arbitrary version. + // However, we don't particularly care about arbitrary upgrades to modules + // that are (at best) only providing packages imported by tests of + // dependencies outside the main module. + for _, m := range rs.rootModules { + restrictTo(module.Version{ + Path: m.Path, + Version: mg.Selected(m.Path), + }) + } + } + + if err := raiseLimitsForUpgrades(ctx, maxVersion, rs.depth, tryUpgrade, mustSelect); err != nil { + return nil, err + } + + // The versions in mustSelect override whatever we would naively select — + // we will downgrade other modules as needed in order to meet them. + for _, m := range mustSelect { + restrictTo(m) + } + + return newVersionLimiter(rs.depth, maxVersion), nil +} + +// raiseLimitsForUpgrades increases the module versions in maxVersions to the +// versions that would be needed to allow each of the modules in tryUpgrade +// (individually) and all of the modules in mustSelect (simultaneously) to be +// added as roots. +// +// Versions not present in maxVersion are unrestricted, and it is assumed that +// they will not be promoted to root requirements (and thus will not contribute +// their own dependencies if the main module is lazy). +// +// These limits provide an upper bound on how far a module may be upgraded as +// part of an incidental downgrade, if downgrades are needed in order to select +// the versions in mustSelect. +func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, depth modDepth, tryUpgrade []module.Version, mustSelect []module.Version) error { + // allow raises the limit for m.Path to at least m.Version. + // If m.Path was already unrestricted, it remains unrestricted. + allow := func(m module.Version) { + v, ok := maxVersion[m.Path] + if !ok { + return // m.Path is unrestricted. + } + if cmpVersion(v, m.Version) < 0 { + maxVersion[m.Path] = m.Version + } + } + + var eagerUpgrades []module.Version + if depth == eager { + eagerUpgrades = tryUpgrade + } else { + for _, m := range tryUpgrade { + if m.Path == Target.Path { + // Target is already considered to be higher than any possible m, so we + // won't be upgrading to it anyway and there is no point scanning its + // dependencies. + continue + } + + summary, err := goModSummary(m) + if err != nil { + return err + } + if summary.depth == eager { + // For efficiency, we'll load all of the eager upgrades as one big + // graph, rather than loading the (potentially-overlapping) subgraph for + // each upgrade individually. + eagerUpgrades = append(eagerUpgrades, m) + continue + } + + for _, r := range summary.require { + allow(r) + } + } + } + + if len(eagerUpgrades) > 0 { + // Compute the max versions for eager upgrades all together. + // Since these modules are eager, we'll end up scanning all of their + // transitive dependencies no matter which versions end up selected, + // and since we have a large dependency graph to scan we might get + // a significant benefit from not revisiting dependencies that are at + // common versions among multiple upgrades. + upgradeGraph, err := readModGraph(ctx, eager, eagerUpgrades) + if err != nil { + if go117LazyTODO { + // Compute the requirement path from a module path in tryUpgrade to the + // error, and the requirement path (if any) from rs.rootModules to the + // tryUpgrade module path. Return a *mvs.BuildListError showing the + // concatenation of the paths (with an upgrade in the middle). + } + return err + } + + for _, r := range upgradeGraph.BuildList() { + // Upgrading to m would upgrade to r, and the caller requested that we + // try to upgrade to m, so it's ok to upgrade to r. + allow(r) + } + } + + if len(mustSelect) > 0 { + mustGraph, err := readModGraph(ctx, depth, mustSelect) + if err != nil { + return err + } + + for _, r := range mustGraph.BuildList() { + // Some module in mustSelect requires r, so we must allow at least r.Version + // unless it conflicts with an entry in mustSelect. + allow(r) + } + } + + return nil +} + +// selectPotentiallyImportedModules increases the limiter-selected version of +// every module in rs that potentially provides a package imported (directly or +// indirectly) by the main module, and every module in tryUpgrade, toward the +// highest version seen in rs or tryUpgrade, but not above the maximums enforced +// by the limiter. +// +// It returns the list of module versions selected by the limiter, sorted by +// path, along with a boolean indicating whether that list is different from the +// list of modules read from rs. +func selectPotentiallyImportedModules(ctx context.Context, limiter *versionLimiter, rs *Requirements, tryUpgrade []module.Version) (mods []module.Version, changed bool, err error) { + for _, m := range tryUpgrade { + if err := limiter.UpgradeToward(ctx, m); err != nil { + return nil, false, err + } + } + + var initial []module.Version + if rs.depth == eager { + mg, err := rs.Graph(ctx) + if err != nil { + return nil, false, err + } + initial = mg.BuildList()[1:] + } else { + initial = rs.rootModules + } + for _, m := range initial { + if err := limiter.UpgradeToward(ctx, m); err != nil { + return nil, false, err + } + } + + mods = make([]module.Version, 0, len(limiter.selected)) + for path, v := range limiter.selected { + if v != "none" && path != Target.Path { + mods = append(mods, module.Version{Path: path, Version: v}) + } + } + + // We've identified acceptable versions for each of the modules, but those + // versions are not necessarily consistent with each other: one upgraded or + // downgraded module may require a higher (but still allowed) version of + // another. The lower version may require extraneous dependencies that aren't + // actually relevant, so we need to compute the actual selected versions. + mg, err := readModGraph(ctx, rs.depth, mods) + if err != nil { + return nil, false, err + } + mods = make([]module.Version, 0, len(limiter.selected)) + for path, _ := range limiter.selected { + if path != Target.Path { + if v := mg.Selected(path); v != "none" { + mods = append(mods, module.Version{Path: path, Version: v}) + } + } + } + module.Sort(mods) + + changed = !reflect.DeepEqual(mods, initial) + + return mods, changed, err +} + +// A versionLimiter tracks the versions that may be selected for each module +// subject to constraints on the maximum versions of transitive dependencies. +type versionLimiter struct { + // depth is the depth at which the dependencies of the modules passed to + // Select and UpgradeToward are loaded. + depth modDepth + + // max maps each module path to the maximum version that may be selected for + // that path. + // + // Paths with no entry are unrestricted, and we assume that they will not be + // promoted to root dependencies (so will not contribute dependencies if the + // main module is lazy). + max map[string]string + + // selected maps each module path to a version of that path (if known) whose + // transitive dependencies do not violate any max version. The version kept + // is the highest one found during any call to UpgradeToward for the given + // module path. + // + // If a higher acceptable version is found during a call to UpgradeToward for + // some *other* module path, that does not update the selected version. + // Ignoring those versions keeps the downgrades computed for two modules + // together close to the individual downgrades that would be computed for each + // module in isolation. (The only way one module can affect another is if the + // final downgraded version of the one module explicitly requires a higher + // version of the other.) + // + // Version "none" of every module is always known not to violate any max + // version, so paths at version "none" are omitted. + selected map[string]string + + // dqReason records whether and why each each encountered version is + // disqualified. + dqReason map[module.Version]dqState + + // requiring maps each not-yet-disqualified module version to the versions + // that directly require it. If that version becomes disqualified, the + // disqualification will be propagated to all of the versions in the list. + requiring map[module.Version][]module.Version +} + +// A dqState indicates whether and why a module version is “disqualified” from +// being used in a way that would incorporate its requirements. +// +// The zero dqState indicates that the module version is not known to be +// disqualified, either because it is ok or because we are currently traversing +// a cycle that includes it. +type dqState struct { + err error // if non-nil, disqualified because the requirements of the module could not be read + conflict module.Version // disqualified because the module (transitively) requires dep, which exceeds the maximum version constraint for its path +} + +func (dq dqState) isDisqualified() bool { + return dq != dqState{} +} + +// newVersionLimiter returns a versionLimiter that restricts the module paths +// that appear as keys in max. +// +// max maps each module path to its maximum version; paths that are not present +// in the map are unrestricted. The limiter assumes that unrestricted paths will +// not be promoted to root dependencies. +// +// If depth is lazy, then if a module passed to UpgradeToward or Select is +// itself lazy, its unrestricted dependencies are skipped when scanning +// requirements. +func newVersionLimiter(depth modDepth, max map[string]string) *versionLimiter { + return &versionLimiter{ + depth: depth, + max: max, + selected: map[string]string{Target.Path: Target.Version}, + dqReason: map[module.Version]dqState{}, + requiring: map[module.Version][]module.Version{}, + } +} + +// UpgradeToward attempts to upgrade the selected version of m.Path as close as +// possible to m.Version without violating l's maximum version limits. +// +// If depth is lazy and m itself is lazy, the the dependencies of unrestricted +// dependencies of m will not be followed. +func (l *versionLimiter) UpgradeToward(ctx context.Context, m module.Version) error { + selected, ok := l.selected[m.Path] + if ok { + if cmpVersion(selected, m.Version) >= 0 { + // The selected version is already at least m, so no upgrade is needed. + return nil + } + } else { + selected = "none" + } + + if l.check(m, l.depth).isDisqualified() { + candidates, err := versions(ctx, m.Path, CheckAllowed) + if err != nil { + // This is likely a transient error reaching the repository, + // rather than a permanent error with the retrieved version. + // + // TODO(golang.org/issue/31730, golang.org/issue/30134): + // decode what to do based on the actual error. + return err + } + + // Skip to candidates < m.Version. + i := sort.Search(len(candidates), func(i int) bool { + return semver.Compare(candidates[i], m.Version) >= 0 + }) + candidates = candidates[:i] + + for l.check(m, l.depth).isDisqualified() { + n := len(candidates) + if n == 0 || cmpVersion(selected, candidates[n-1]) >= 0 { + // We couldn't find a suitable candidate above the already-selected version. + // Retain that version unmodified. + return nil + } + m.Version, candidates = candidates[n-1], candidates[:n-1] + } + } + + l.selected[m.Path] = m.Version + return nil +} + +// Select attempts to set the selected version of m.Path to exactly m.Version. +func (l *versionLimiter) Select(m module.Version) (conflict module.Version, err error) { + dq := l.check(m, l.depth) + if !dq.isDisqualified() { + l.selected[m.Path] = m.Version + } + return dq.conflict, dq.err +} + +// check determines whether m (or its transitive dependencies) would violate l's +// maximum version limits if added to the module requirement graph. +// +// If depth is lazy and m itself is lazy, then the dependencies of unrestricted +// dependencies of m will not be followed. If the lazy loading invariants hold +// for the main module up to this point, the packages in those modules are at +// best only imported by tests of dependencies that are themselves loaded from +// outside modules. Although we would like to keep 'go test all' as reproducible +// as is feasible, we don't want to retain test dependencies that are only +// marginally relevant at best. +func (l *versionLimiter) check(m module.Version, depth modDepth) dqState { + if m.Version == "none" || m == Target { + // version "none" has no requirements, and the dependencies of Target are + // tautological. + return dqState{} + } + + if dq, seen := l.dqReason[m]; seen { + return dq + } + l.dqReason[m] = dqState{} + + if max, ok := l.max[m.Path]; ok && cmpVersion(m.Version, max) > 0 { + return l.disqualify(m, dqState{conflict: m}) + } + + summary, err := goModSummary(m) + if err != nil { + // If we can't load the requirements, we couldn't load the go.mod file. + // There are a number of reasons this can happen, but this usually + // means an older version of the module had a missing or invalid + // go.mod file. For example, if example.com/mod released v2.0.0 before + // migrating to modules (v2.0.0+incompatible), then added a valid go.mod + // in v2.0.1, downgrading from v2.0.1 would cause this error. + // + // TODO(golang.org/issue/31730, golang.org/issue/30134): if the error + // is transient (we couldn't download go.mod), return the error from + // Downgrade. Currently, we can't tell what kind of error it is. + return l.disqualify(m, dqState{err: err}) + } + + if summary.depth == eager { + depth = eager + } + for _, r := range summary.require { + if depth == lazy { + if _, restricted := l.max[r.Path]; !restricted { + // r.Path is unrestricted, so we don't care at what version it is + // selected. We assume that r.Path will not become a root dependency, so + // since m is lazy, r's dependencies won't be followed. + continue + } + } + + if dq := l.check(r, depth); dq.isDisqualified() { + return l.disqualify(m, dq) + } + + // r and its dependencies are (perhaps provisionally) ok. + // + // However, if there are cycles in the requirement graph, we may have only + // checked a portion of the requirement graph so far, and r (and thus m) may + // yet be disqualified by some path we have not yet visited. Remember this edge + // so that we can disqualify m and its dependents if that occurs. + l.requiring[r] = append(l.requiring[r], m) + } + + return dqState{} +} + +// disqualify records that m (or one of its transitive dependencies) +// violates l's maximum version limits. +func (l *versionLimiter) disqualify(m module.Version, dq dqState) dqState { + if dq := l.dqReason[m]; dq.isDisqualified() { + return dq + } + l.dqReason[m] = dq + + for _, p := range l.requiring[m] { + l.disqualify(p, dqState{conflict: m}) + } + // Now that we have disqualified the modules that depend on m, we can forget + // about them — we won't need to disqualify them again. + delete(l.requiring, m) + return dq +} diff --git a/libgo/go/cmd/go/internal/modload/help.go b/libgo/go/cmd/go/internal/modload/help.go index fd39ddd..886ad62 100644 --- a/libgo/go/cmd/go/internal/modload/help.go +++ b/libgo/go/cmd/go/internal/modload/help.go @@ -46,7 +46,7 @@ marking the root of the main (current) module. The go.mod file format is described in detail at https://golang.org/ref/mod#go-mod-file. -To create a new go.mod file, use 'go help init'. For details see +To create a new go.mod file, use 'go mod init'. For details see 'go help mod init' or https://golang.org/ref/mod#go-mod-init. To add missing module requirements or remove unneeded requirements, diff --git a/libgo/go/cmd/go/internal/modload/import.go b/libgo/go/cmd/go/internal/modload/import.go index 995641c..d2bbe5c 100644 --- a/libgo/go/cmd/go/internal/modload/import.go +++ b/libgo/go/cmd/go/internal/modload/import.go @@ -12,6 +12,7 @@ import ( "internal/goroot" "io/fs" "os" + pathpkg "path" "path/filepath" "sort" "strings" @@ -60,7 +61,7 @@ func (e *ImportMissingError) Error() string { if e.replaced.Path != "" { suggestArg := e.replaced.Path - if !modfetch.IsZeroPseudoVersion(e.replaced.Version) { + if !module.IsZeroPseudoVersion(e.replaced.Version) { suggestArg = e.replaced.String() } return fmt.Sprintf("module %s provides package %s and is replaced but not required; to add it:\n\tgo get %s", e.replaced.Path, e.Path, suggestArg) @@ -127,6 +128,23 @@ func (e *AmbiguousImportError) Error() string { return buf.String() } +// A DirectImportFromImplicitDependencyError indicates a package directly +// imported by a package or test in the main module that is satisfied by a +// dependency that is not explicit in the main module's go.mod file. +type DirectImportFromImplicitDependencyError struct { + ImporterPath string + ImportedPath string + Module module.Version +} + +func (e *DirectImportFromImplicitDependencyError) Error() string { + return fmt.Sprintf("package %s imports %s from implicitly required module; to add missing requirements, run:\n\tgo get %s@%s", e.ImporterPath, e.ImportedPath, e.Module.Path, e.Module.Version) +} + +func (e *DirectImportFromImplicitDependencyError) ImportPath() string { + return e.ImporterPath +} + // ImportMissingSumError is reported in readonly mode when we need to check // if a module contains a package, but we don't have a sum for its .zip file. // We might need sums for multiple modules to verify the package is unique. @@ -160,11 +178,13 @@ func (e *ImportMissingSumError) Error() string { // Importing package is unknown, or the missing package was named on the // command line. Recommend 'go mod download' for the modules that could // provide the package, since that shouldn't change go.mod. - args := make([]string, len(e.mods)) - for i, mod := range e.mods { - args[i] = mod.Path + if len(e.mods) > 0 { + args := make([]string, len(e.mods)) + for i, mod := range e.mods { + args[i] = mod.Path + } + hint = fmt.Sprintf("; to add:\n\tgo mod download %s", strings.Join(args, " ")) } - hint = fmt.Sprintf("; to add:\n\tgo mod download %s", strings.Join(args, " ")) } else { // Importing package is known (common case). Recommend 'go get' on the // current version of the importing package. @@ -202,28 +222,31 @@ func (e *invalidImportError) Unwrap() error { return e.err } -// importFromBuildList finds the module and directory in the build list -// containing the package with the given import path. The answer must be unique: -// importFromBuildList returns an error if multiple modules attempt to provide -// the same package. +// importFromModules finds the module and directory in the dependency graph of +// rs containing the package with the given import path. If mg is nil, +// importFromModules attempts to locate the module using only the main module +// and the roots of rs before it loads the full graph. // -// importFromBuildList can return a module with an empty m.Path, for packages in +// The answer must be unique: importFromModules returns an error if multiple +// modules are observed to provide the same package. +// +// importFromModules can return a module with an empty m.Path, for packages in // the standard library. // -// importFromBuildList can return an empty directory string, for fake packages +// importFromModules can return an empty directory string, for fake packages // like "C" and "unsafe". // -// If the package cannot be found in buildList, -// importFromBuildList returns an *ImportMissingError. -func importFromBuildList(ctx context.Context, path string, buildList []module.Version) (m module.Version, dir string, err error) { +// If the package is not present in any module selected from the requirement +// graph, importFromModules returns an *ImportMissingError. +func importFromModules(ctx context.Context, path string, rs *Requirements, mg *ModuleGraph) (m module.Version, dir string, err error) { if strings.Contains(path, "@") { return module.Version{}, "", fmt.Errorf("import path should not have @version") } if build.IsLocalImport(path) { return module.Version{}, "", fmt.Errorf("relative import not supported") } - if path == "C" || path == "unsafe" { - // There's no directory for import "C" or import "unsafe". + if path == "C" { + // There's no directory for import "C". return module.Version{}, "", nil } // Before any further lookup, check that the path is valid. @@ -269,58 +292,114 @@ func importFromBuildList(ctx context.Context, path string, buildList []module.Ve // Check each module on the build list. var dirs []string var mods []module.Version - var sumErrMods []module.Version - for _, m := range buildList { - if !maybeInModule(path, m.Path) { - // Avoid possibly downloading irrelevant modules. - continue - } - needSum := true - root, isLocal, err := fetch(ctx, m, needSum) - if err != nil { - if sumErr := (*sumMissingError)(nil); errors.As(err, &sumErr) { - // We are missing a sum needed to fetch a module in the build list. - // We can't verify that the package is unique, and we may not find - // the package at all. Keep checking other modules to decide which - // error to report. Multiple sums may be missing if we need to look in - // multiple nested modules to resolve the import. - sumErrMods = append(sumErrMods, m) + + // Iterate over possible modules for the path, not all selected modules. + // Iterating over selected modules would make the overall loading time + // O(M × P) for M modules providing P imported packages, whereas iterating + // over path prefixes is only O(P × k) with maximum path depth k. For + // large projects both M and P may be very large (note that M ≤ P), but k + // will tend to remain smallish (if for no other reason than filesystem + // path limitations). + // + // We perform this iteration either one or two times. If mg is initially nil, + // then we first attempt to load the package using only the main module and + // its root requirements. If that does not identify the package, or if mg is + // already non-nil, then we attempt to load the package using the full + // requirements in mg. + for { + var sumErrMods []module.Version + for prefix := path; prefix != "."; prefix = pathpkg.Dir(prefix) { + var ( + v string + ok bool + ) + if mg == nil { + v, ok = rs.rootSelected(prefix) + } else { + v, ok = mg.Selected(prefix), true + } + if !ok || v == "none" { continue } - // Report fetch error. - // Note that we don't know for sure this module is necessary, - // but it certainly _could_ provide the package, and even if we - // continue the loop and find the package in some other module, - // we need to look at this module to make sure the import is - // not ambiguous. - return module.Version{}, "", err + m := module.Version{Path: prefix, Version: v} + + needSum := true + root, isLocal, err := fetch(ctx, m, needSum) + if err != nil { + if sumErr := (*sumMissingError)(nil); errors.As(err, &sumErr) { + // We are missing a sum needed to fetch a module in the build list. + // We can't verify that the package is unique, and we may not find + // the package at all. Keep checking other modules to decide which + // error to report. Multiple sums may be missing if we need to look in + // multiple nested modules to resolve the import; we'll report them all. + sumErrMods = append(sumErrMods, m) + continue + } + // Report fetch error. + // Note that we don't know for sure this module is necessary, + // but it certainly _could_ provide the package, and even if we + // continue the loop and find the package in some other module, + // we need to look at this module to make sure the import is + // not ambiguous. + return module.Version{}, "", err + } + if dir, ok, err := dirInModule(path, m.Path, root, isLocal); err != nil { + return module.Version{}, "", err + } else if ok { + mods = append(mods, m) + dirs = append(dirs, dir) + } } - if dir, ok, err := dirInModule(path, m.Path, root, isLocal); err != nil { - return module.Version{}, "", err - } else if ok { - mods = append(mods, m) - dirs = append(dirs, dir) + + if len(mods) > 1 { + // We produce the list of directories from longest to shortest candidate + // module path, but the AmbiguousImportError should report them from + // shortest to longest. Reverse them now. + for i := 0; i < len(mods)/2; i++ { + j := len(mods) - 1 - i + mods[i], mods[j] = mods[j], mods[i] + dirs[i], dirs[j] = dirs[j], dirs[i] + } + return module.Version{}, "", &AmbiguousImportError{importPath: path, Dirs: dirs, Modules: mods} } - } - if len(mods) > 1 { - return module.Version{}, "", &AmbiguousImportError{importPath: path, Dirs: dirs, Modules: mods} - } - if len(sumErrMods) > 0 { - return module.Version{}, "", &ImportMissingSumError{ - importPath: path, - mods: sumErrMods, - found: len(mods) > 0, + + if len(sumErrMods) > 0 { + for i := 0; i < len(sumErrMods)/2; i++ { + j := len(sumErrMods) - 1 - i + sumErrMods[i], sumErrMods[j] = sumErrMods[j], sumErrMods[i] + } + return module.Version{}, "", &ImportMissingSumError{ + importPath: path, + mods: sumErrMods, + found: len(mods) > 0, + } } - } - if len(mods) == 1 { - return mods[0], dirs[0], nil - } - var queryErr error - if !HasModRoot() { - queryErr = ErrNoModRoot + if len(mods) == 1 { + return mods[0], dirs[0], nil + } + + if mg != nil { + // We checked the full module graph and still didn't find the + // requested package. + var queryErr error + if !HasModRoot() { + queryErr = ErrNoModRoot + } + return module.Version{}, "", &ImportMissingError{Path: path, QueryErr: queryErr, isStd: pathIsStd} + } + + // So far we've checked the root dependencies. + // Load the full module graph and try again. + mg, err = rs.Graph(ctx) + if err != nil { + // We might be missing one or more transitive (implicit) dependencies from + // the module graph, so we can't return an ImportMissingError here — one + // of the missing modules might actually contain the package in question, + // in which case we shouldn't go looking for it in some new dependency. + return module.Version{}, "", err + } } - return module.Version{}, "", &ImportMissingError{Path: path, QueryErr: queryErr, isStd: pathIsStd} } // queryImport attempts to locate a module that can be added to the current @@ -328,7 +407,7 @@ func importFromBuildList(ctx context.Context, path string, buildList []module.Ve // // Unlike QueryPattern, queryImport prefers to add a replaced version of a // module *before* checking the proxies for a version to add. -func queryImport(ctx context.Context, path string) (module.Version, error) { +func queryImport(ctx context.Context, path string, rs *Requirements) (module.Version, error) { // To avoid spurious remote fetches, try the latest replacement for each // module (golang.org/issue/26241). if index != nil { @@ -344,11 +423,20 @@ func queryImport(ctx context.Context, path string) (module.Version, error) { // used from within some other module, the user will be able to upgrade // the requirement to any real version they choose. if _, pathMajor, ok := module.SplitPathVersion(mp); ok && len(pathMajor) > 0 { - mv = modfetch.ZeroPseudoVersion(pathMajor[1:]) + mv = module.ZeroPseudoVersion(pathMajor[1:]) } else { - mv = modfetch.ZeroPseudoVersion("v0") + mv = module.ZeroPseudoVersion("v0") } } + mg, err := rs.Graph(ctx) + if err != nil { + return module.Version{}, err + } + if cmpVersion(mg.Selected(mp), mv) >= 0 { + // We can't resolve the import by adding mp@mv to the module graph, + // because the selected version of mp is already at least mv. + continue + } mods = append(mods, module.Version{Path: mp, Version: mv}) } @@ -417,7 +505,12 @@ func queryImport(ctx context.Context, path string) (module.Version, error) { // and return m, dir, ImpportMissingError. fmt.Fprintf(os.Stderr, "go: finding module for package %s\n", path) - candidates, err := QueryPackages(ctx, path, "latest", Selected, CheckAllowed) + mg, err := rs.Graph(ctx) + if err != nil { + return module.Version{}, err + } + + candidates, err := QueryPackages(ctx, path, "latest", mg.Selected, CheckAllowed) if err != nil { if errors.Is(err, fs.ErrNotExist) { // Return "cannot find module providing package […]" instead of whatever @@ -430,28 +523,21 @@ func queryImport(ctx context.Context, path string) (module.Version, error) { candidate0MissingVersion := "" for i, c := range candidates { - cm := c.Mod - canAdd := true - for _, bm := range buildList { - if bm.Path == cm.Path && semver.Compare(bm.Version, cm.Version) > 0 { - // QueryPattern proposed that we add module cm to provide the package, - // but we already depend on a newer version of that module (and we don't - // have the package). - // - // This typically happens when a package is present at the "@latest" - // version (e.g., v1.0.0) of a module, but we have a newer version - // of the same module in the build list (e.g., v1.0.1-beta), and - // the package is not present there. - canAdd = false - if i == 0 { - candidate0MissingVersion = bm.Version - } - break + if v := mg.Selected(c.Mod.Path); semver.Compare(v, c.Mod.Version) > 0 { + // QueryPattern proposed that we add module c.Mod to provide the package, + // but we already depend on a newer version of that module (and that + // version doesn't have the package). + // + // This typically happens when a package is present at the "@latest" + // version (e.g., v1.0.0) of a module, but we have a newer version + // of the same module in the build list (e.g., v1.0.1-beta), and + // the package is not present there. + if i == 0 { + candidate0MissingVersion = v } + continue } - if canAdd { - return cm, nil - } + return c.Mod, nil } return module.Version{}, &ImportMissingError{ Path: path, diff --git a/libgo/go/cmd/go/internal/modload/import_test.go b/libgo/go/cmd/go/internal/modload/import_test.go index 9420dc5..9814588 100644 --- a/libgo/go/cmd/go/internal/modload/import_test.go +++ b/libgo/go/cmd/go/internal/modload/import_test.go @@ -69,11 +69,12 @@ func TestQueryImport(t *testing.T) { RootMode = NoRoot ctx := context.Background() + rs := newRequirements(eager, nil, nil) for _, tt := range importTests { t.Run(strings.ReplaceAll(tt.path, "/", "_"), func(t *testing.T) { // Note that there is no build list, so Import should always fail. - m, err := queryImport(ctx, tt.path) + m, err := queryImport(ctx, tt.path, rs) if tt.err == "" { if err != nil { diff --git a/libgo/go/cmd/go/internal/modload/init.go b/libgo/go/cmd/go/internal/modload/init.go index 8ec1c86..a8cbd9f 100644 --- a/libgo/go/cmd/go/internal/modload/init.go +++ b/libgo/go/cmd/go/internal/modload/init.go @@ -15,10 +15,8 @@ import ( "os" "path" "path/filepath" - "sort" "strconv" "strings" - "sync" "cmd/go/internal/base" "cmd/go/internal/cfg" @@ -26,20 +24,37 @@ import ( "cmd/go/internal/lockedfile" "cmd/go/internal/modconv" "cmd/go/internal/modfetch" - "cmd/go/internal/mvs" "cmd/go/internal/search" - "cmd/go/internal/str" "golang.org/x/mod/modfile" "golang.org/x/mod/module" "golang.org/x/mod/semver" ) +// Variables set by other packages. +// +// TODO(#40775): See if these can be plumbed as explicit parameters. +var ( + // RootMode determines whether a module root is needed. + RootMode Root + + // ForceUseModules may be set to force modules to be enabled when + // GO111MODULE=auto or to report an error when GO111MODULE=off. + ForceUseModules bool + + allowMissingModuleImports bool +) + +// Variables set in Init. var ( initialized bool + modRoot string + gopath string +) - modRoot string - Target module.Version +// Variables set in initTarget (during {Load,Create}ModFile). +var ( + Target module.Version // targetPrefix is the path prefix for packages in Target, without a trailing // slash. For most modules, targetPrefix is just Target.Path, but the @@ -49,17 +64,6 @@ var ( // targetInGorootSrc caches whether modRoot is within GOROOT/src. // The "std" module is special within GOROOT/src, but not otherwise. targetInGorootSrc bool - - gopath string - - // RootMode determines whether a module root is needed. - RootMode Root - - // ForceUseModules may be set to force modules to be enabled when - // GO111MODULE=auto or to report an error when GO111MODULE=off. - ForceUseModules bool - - allowMissingModuleImports bool ) type Root int @@ -67,7 +71,7 @@ type Root int const ( // AutoRoot is the default for most commands. modload.Init will look for // a go.mod file in the current directory or any parent. If none is found, - // modules may be disabled (GO111MODULE=on) or commands may run in a + // modules may be disabled (GO111MODULE=auto) or commands may run in a // limited module mode. AutoRoot Root = iota @@ -82,7 +86,7 @@ const ( // ModFile returns the parsed go.mod file. // -// Note that after calling LoadPackages or LoadAllModules, +// Note that after calling LoadPackages or LoadModGraph, // the require statements in the modfile.File are no longer // the source of truth and will be ignored: edits made directly // will be lost at the next call to WriteGoMod. @@ -131,7 +135,7 @@ func Init() { return } - if err := fsys.Init(base.Cwd); err != nil { + if err := fsys.Init(base.Cwd()); err != nil { base.Fatalf("go: %v", err) } @@ -159,7 +163,11 @@ func Init() { // assume they know what they are doing and don't step on it. // But default to turning off ControlMaster. if os.Getenv("GIT_SSH") == "" && os.Getenv("GIT_SSH_COMMAND") == "" { - os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no") + os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no -o BatchMode=yes") + } + + if os.Getenv("GCM_INTERACTIVE") == "" { + os.Setenv("GCM_INTERACTIVE", "never") } if modRoot != "" { @@ -171,7 +179,7 @@ func Init() { } modRoot = "" } else { - modRoot = findModuleRoot(base.Cwd) + modRoot = findModuleRoot(base.Cwd()) if modRoot == "" { if cfg.ModFile != "" { base.Fatalf("go: cannot find main module, but -modfile was set.\n\t-modfile cannot be used to set the module root directory.") @@ -268,7 +276,7 @@ func WillBeEnabled() bool { return false } - if modRoot := findModuleRoot(base.Cwd); modRoot == "" { + if modRoot := findModuleRoot(base.Cwd()); modRoot == "" { // GO111MODULE is 'auto', and we can't find a module root. // Stay in GOPATH mode. return false @@ -327,8 +335,8 @@ func die() { if cfg.Getenv("GO111MODULE") == "off" { base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'") } - if dir, name := findAltConfig(base.Cwd); dir != "" { - rel, err := filepath.Rel(base.Cwd, dir) + if dir, name := findAltConfig(base.Cwd()); dir != "" { + rel, err := filepath.Rel(base.Cwd(), dir) if err != nil { rel = dir } @@ -343,30 +351,77 @@ func die() { var ErrNoModRoot = errors.New("go.mod file not found in current directory or any parent directory; see 'go help modules'") +type goModDirtyError struct{} + +func (goModDirtyError) Error() string { + if cfg.BuildModExplicit { + return fmt.Sprintf("updates to go.mod needed, disabled by -mod=%v; to update it:\n\tgo mod tidy", cfg.BuildMod) + } + if cfg.BuildModReason != "" { + return fmt.Sprintf("updates to go.mod needed, disabled by -mod=%s\n\t(%s)\n\tto update it:\n\tgo mod tidy", cfg.BuildMod, cfg.BuildModReason) + } + return "updates to go.mod needed; to update it:\n\tgo mod tidy" +} + +var errGoModDirty error = goModDirtyError{} + // LoadModFile sets Target and, if there is a main module, parses the initial // build list from its go.mod file. // // LoadModFile may make changes in memory, like adding a go directive and -// ensuring requirements are consistent. WriteGoMod should be called later to -// write changes out to disk or report errors in readonly mode. +// ensuring requirements are consistent, and will write those changes back to +// disk unless DisallowWriteGoMod is in effect. // // As a side-effect, LoadModFile may change cfg.BuildMod to "vendor" if // -mod wasn't set explicitly and automatic vendoring should be enabled. -func LoadModFile(ctx context.Context) { - if len(buildList) > 0 { - return +// +// If LoadModFile or CreateModFile has already been called, LoadModFile returns +// the existing in-memory requirements (rather than re-reading them from disk). +// +// LoadModFile checks the roots of the module graph for consistency with each +// other, but unlike LoadModGraph does not load the full module graph or check +// it for global consistency. Most callers outside of the modload package should +// use LoadModGraph instead. +func LoadModFile(ctx context.Context) *Requirements { + rs, needCommit := loadModFile(ctx) + if needCommit { + commitRequirements(ctx, modFileGoVersion(), rs) + } + return rs +} + +// loadModFile is like LoadModFile, but does not implicitly commit the +// requirements back to disk after fixing inconsistencies. +// +// If needCommit is true, after the caller makes any other needed changes to the +// returned requirements they should invoke commitRequirements to fix any +// inconsistencies that may be present in the on-disk go.mod file. +func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) { + if requirements != nil { + return requirements, false } Init() if modRoot == "" { Target = module.Version{Path: "command-line-arguments"} targetPrefix = "command-line-arguments" - buildList = []module.Version{Target} - return + goVersion := LatestGoVersion() + rawGoVersion.Store(Target, goVersion) + requirements = newRequirements(modDepthFromGoVersion(goVersion), nil, nil) + return requirements, false } gomod := ModFilePath() - data, err := lockedfile.Read(gomod) + var data []byte + var err error + if gomodActual, ok := fsys.OverlayPath(gomod); ok { + // Don't lock go.mod if it's part of the overlay. + // On Plan 9, locking requires chmod, and we don't want to modify any file + // in the overlay. See #44700. + data, err = os.ReadFile(gomodActual) + } else { + data, err = lockedfile.Read(gomodActual) + } if err != nil { base.Fatalf("go: %v", err) } @@ -377,24 +432,53 @@ func LoadModFile(ctx context.Context) { // Errors returned by modfile.Parse begin with file:line. base.Fatalf("go: errors parsing go.mod:\n%s\n", err) } - modFile = f - index = indexModFile(data, f, fixed) - if f.Module == nil { // No module declaration. Must add module path. base.Fatalf("go: no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod") } - if err := checkModulePathLax(f.Module.Mod.Path); err != nil { + modFile = f + initTarget(f.Module.Mod) + index = indexModFile(data, f, fixed) + + if err := module.CheckImportPath(f.Module.Mod.Path); err != nil { + if pathErr, ok := err.(*module.InvalidPathError); ok { + pathErr.Kind = "module" + } base.Fatalf("go: %v", err) } setDefaultBuildMod() // possibly enable automatic vendoring - modFileToBuildList() + rs = requirementsFromModFile(ctx) + if cfg.BuildMod == "vendor" { readVendorList() checkVendorConsistency() + rs.initVendor(vendorList) + } + if index.goVersionV == "" { + // TODO(#45551): Do something more principled instead of checking + // cfg.CmdName directly here. + if cfg.BuildMod == "mod" && cfg.CmdName != "mod graph" && cfg.CmdName != "mod why" { + addGoStmt(LatestGoVersion()) + if go117EnableLazyLoading { + // We need to add a 'go' version to the go.mod file, but we must assume + // that its existing contents match something between Go 1.11 and 1.16. + // Go 1.11 through 1.16 have eager requirements, but the latest Go + // version uses lazy requirements instead — so we need to cnvert the + // requirements to be lazy. + rs, err = convertDepth(ctx, rs, lazy) + if err != nil { + base.Fatalf("go: %v", err) + } + } + } else { + rawGoVersion.Store(Target, modFileGoVersion()) + } } + + requirements = rs + return requirements, true } // CreateModFile initializes a new module by creating a go.mod file. @@ -407,7 +491,7 @@ func LoadModFile(ctx context.Context) { // exactly the same as in the legacy configuration (for example, we can't get // packages at multiple versions from the same module). func CreateModFile(ctx context.Context, modPath string) { - modRoot = base.Cwd + modRoot = base.Cwd() Init() modFilePath := ModFilePath() if _, err := fsys.Stat(modFilePath); err == nil { @@ -420,14 +504,23 @@ func CreateModFile(ctx context.Context, modPath string) { if err != nil { base.Fatalf("go: %v", err) } - } else if err := checkModulePathLax(modPath); err != nil { + } else if err := module.CheckImportPath(modPath); err != nil { + if pathErr, ok := err.(*module.InvalidPathError); ok { + pathErr.Kind = "module" + // Same as build.IsLocalPath() + if pathErr.Path == "." || pathErr.Path == ".." || + strings.HasPrefix(pathErr.Path, "./") || strings.HasPrefix(pathErr.Path, "../") { + pathErr.Err = errors.New("is a local import path") + } + } base.Fatalf("go: %v", err) } fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", modPath) modFile = new(modfile.File) modFile.AddModuleStmt(modPath) - addGoStmt() // Add the go directive before converted module requirements. + initTarget(modFile.Module.Mod) + addGoStmt(LatestGoVersion()) // Add the go directive before converted module requirements. convertedFrom, err := convertLegacyConfig(modPath) if convertedFrom != "" { @@ -437,8 +530,7 @@ func CreateModFile(ctx context.Context, modPath string) { base.Fatalf("go: %v", err) } - modFileToBuildList() - WriteGoMod() + commitRequirements(ctx, modFileGoVersion(), requirementsFromModFile(ctx)) // Suggest running 'go mod tidy' unless the project is empty. Even if we // imported all the correct requirements above, we're probably missing @@ -464,49 +556,6 @@ func CreateModFile(ctx context.Context, modPath string) { } } -// checkModulePathLax checks that the path meets some minimum requirements -// to avoid confusing users or the module cache. The requirements are weaker -// than those of module.CheckPath to allow room for weakening module path -// requirements in the future, but strong enough to help users avoid significant -// problems. -func checkModulePathLax(p string) error { - // TODO(matloob): Replace calls of this function in this CL with calls - // to module.CheckImportPath once it's been laxened, if it becomes laxened. - // See golang.org/issue/29101 for a discussion about whether to make CheckImportPath - // more lax or more strict. - - errorf := func(format string, args ...interface{}) error { - return fmt.Errorf("invalid module path %q: %s", p, fmt.Sprintf(format, args...)) - } - - // Disallow shell characters " ' * < > ? ` | to avoid triggering bugs - // with file systems and subcommands. Disallow file path separators : and \ - // because path separators other than / will confuse the module cache. - // See fileNameOK in golang.org/x/mod/module/module.go. - shellChars := "`" + `\"'*<>?|` - fsChars := `\:` - if i := strings.IndexAny(p, shellChars); i >= 0 { - return errorf("contains disallowed shell character %q", p[i]) - } - if i := strings.IndexAny(p, fsChars); i >= 0 { - return errorf("contains disallowed path separator character %q", p[i]) - } - - // Ensure path.IsAbs and build.IsLocalImport are false, and that the path is - // invariant under path.Clean, also to avoid confusing the module cache. - if path.IsAbs(p) { - return errorf("is an absolute path") - } - if build.IsLocalImport(p) { - return errorf("is a local import path") - } - if path.Clean(p) != p { - return errorf("is not clean") - } - - return nil -} - // fixVersion returns a modfile.VersionFixer implemented using the Query function. // // It resolves commit hashes and branch names to versions, @@ -559,22 +608,43 @@ func fixVersion(ctx context.Context, fixed *bool) modfile.VersionFixer { // when there is no module root. Normally, this is forbidden because it's slow // and there's no way to make the result reproducible, but some commands // like 'go get' are expected to do this. +// +// This function affects the default cfg.BuildMod when outside of a module, +// so it can only be called prior to Init. func AllowMissingModuleImports() { + if initialized { + panic("AllowMissingModuleImports after Init") + } allowMissingModuleImports = true } -// modFileToBuildList initializes buildList from the modFile. -func modFileToBuildList() { - Target = modFile.Module.Mod - targetPrefix = Target.Path - if rel := search.InDir(base.Cwd, cfg.GOROOTsrc); rel != "" { +// initTarget sets Target and associated variables according to modFile, +func initTarget(m module.Version) { + Target = m + targetPrefix = m.Path + + if rel := search.InDir(base.Cwd(), cfg.GOROOTsrc); rel != "" { targetInGorootSrc = true - if Target.Path == "std" { + if m.Path == "std" { + // The "std" module in GOROOT/src is the Go standard library. Unlike other + // modules, the packages in the "std" module have no import-path prefix. + // + // Modules named "std" outside of GOROOT/src do not receive this special + // treatment, so it is possible to run 'go test .' in other GOROOTs to + // test individual packages using a combination of the modified package + // and the ordinary standard library. + // (See https://golang.org/issue/30756.) targetPrefix = "" } } +} - list := []module.Version{Target} +// requirementsFromModFile returns the set of non-excluded requirements from +// the global modFile. +func requirementsFromModFile(ctx context.Context) *Requirements { + roots := make([]module.Version, 0, len(modFile.Require)) + mPathCount := map[string]int{Target.Path: 1} + direct := map[string]bool{} for _, r := range modFile.Require { if index != nil && index.exclude[r.Mod] { if cfg.BuildMod == "mod" { @@ -582,11 +652,33 @@ func modFileToBuildList() { } else { fmt.Fprintf(os.Stderr, "go: ignoring requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version) } - } else { - list = append(list, r.Mod) + continue + } + + roots = append(roots, r.Mod) + mPathCount[r.Mod.Path]++ + if !r.Indirect { + direct[r.Mod.Path] = true + } + } + module.Sort(roots) + rs := newRequirements(modDepthFromGoVersion(modFileGoVersion()), roots, direct) + + // If any module path appears more than once in the roots, we know that the + // go.mod file needs to be updated even though we have not yet loaded any + // transitive dependencies. + for _, n := range mPathCount { + if n > 1 { + var err error + rs, err = updateRoots(ctx, rs.direct, rs, nil, nil, false) + if err != nil { + base.Fatalf("go: %v", err) + } + break } } - buildList = list + + return rs } // setDefaultBuildMod sets a default value for cfg.BuildMod if the -mod flag @@ -605,7 +697,11 @@ func setDefaultBuildMod() { return } if modRoot == "" { - cfg.BuildMod = "readonly" + if allowMissingModuleImports { + cfg.BuildMod = "mod" + } else { + cfg.BuildMod = "readonly" + } return } @@ -634,6 +730,17 @@ func setDefaultBuildMod() { // convertLegacyConfig imports module requirements from a legacy vendoring // configuration file, if one is present. func convertLegacyConfig(modPath string) (from string, err error) { + noneSelected := func(path string) (version string) { return "none" } + queryPackage := func(path, rev string) (module.Version, error) { + pkgMods, modOnly, err := QueryPattern(context.Background(), path, rev, noneSelected, nil) + if err != nil { + return module.Version{}, err + } + if len(pkgMods) > 0 { + return pkgMods[0].Mod, nil + } + return modOnly.Mod, nil + } for _, name := range altConfigs { cfg := filepath.Join(modRoot, name) data, err := os.ReadFile(cfg) @@ -643,27 +750,57 @@ func convertLegacyConfig(modPath string) (from string, err error) { return "", nil } cfg = filepath.ToSlash(cfg) - err := modconv.ConvertLegacyConfig(modFile, cfg, data) + err := modconv.ConvertLegacyConfig(modFile, cfg, data, queryPackage) return name, err } } return "", nil } -// addGoStmt adds a go directive to the go.mod file if it does not already include one. -// The 'go' version added, if any, is the latest version supported by this toolchain. -func addGoStmt() { +// addGoStmt adds a go directive to the go.mod file if it does not already +// include one. The 'go' version added, if any, is the latest version supported +// by this toolchain. +func addGoStmt(v string) { if modFile.Go != nil && modFile.Go.Version != "" { return } + if err := modFile.AddGoStmt(v); err != nil { + base.Fatalf("go: internal error: %v", err) + } + rawGoVersion.Store(Target, v) +} + +// LatestGoVersion returns the latest version of the Go language supported by +// this toolchain, like "1.17". +func LatestGoVersion() string { tags := build.Default.ReleaseTags version := tags[len(tags)-1] if !strings.HasPrefix(version, "go") || !modfile.GoVersionRE.MatchString(version[2:]) { - base.Fatalf("go: unrecognized default version %q", version) + base.Fatalf("go: internal error: unrecognized default version %q", version) } - if err := modFile.AddGoStmt(version[2:]); err != nil { - base.Fatalf("go: internal error: %v", err) + return version[2:] +} + +// priorGoVersion returns the Go major release immediately preceding v, +// or v itself if v is the first Go major release (1.0) or not a supported +// Go version. +func priorGoVersion(v string) string { + vTag := "go" + v + tags := build.Default.ReleaseTags + for i, tag := range tags { + if tag == vTag { + if i == 0 { + return v + } + + version := tags[i-1] + if !strings.HasPrefix(version, "go") || !modfile.GoVersionRE.MatchString(version[2:]) { + base.Fatalf("go: internal error: unrecognized version %q", version) + } + return version[2:] + } } + return v } var altConfigs = []string{ @@ -780,14 +917,8 @@ func findModulePath(dir string) (string, error) { } if rel := search.InDir(dir, filepath.Join(gpdir, "src")); rel != "" && rel != "." { path := filepath.ToSlash(rel) - // TODO(matloob): replace this with module.CheckImportPath - // once it's been laxened. - // Only checkModulePathLax here. There are some unpublishable - // module names that are compatible with checkModulePathLax - // but they already work in GOPATH so don't break users - // trying to do a build with modules. gorelease will alert users - // publishing their modules to fix their paths. - if err := checkModulePathLax(path); err != nil { + // gorelease will alert users publishing their modules to fix their paths. + if err := module.CheckImportPath(path); err != nil { badPathErr = err break } @@ -847,71 +978,51 @@ func AllowWriteGoMod() { allowWriteGoMod = true } -// MinReqs returns a Reqs with minimal additional dependencies of Target, -// as will be written to go.mod. -func MinReqs() mvs.Reqs { - retain := append([]string{}, additionalExplicitRequirements...) - for _, m := range buildList[1:] { - _, explicit := index.require[m] - if explicit || loaded.direct[m.Path] { - retain = append(retain, m.Path) - } - } - sort.Strings(retain) - str.Uniq(&retain) - min, err := mvs.Req(Target, retain, &mvsReqs{buildList: buildList}) - if err != nil { - base.Fatalf("go: %v", err) +// WriteGoMod writes the current build list back to go.mod. +func WriteGoMod(ctx context.Context) { + if !allowWriteGoMod { + panic("WriteGoMod called while disallowed") } - return &mvsReqs{buildList: append([]module.Version{Target}, min...)} + commitRequirements(ctx, modFileGoVersion(), LoadModFile(ctx)) } -// WriteGoMod writes the current build list back to go.mod. -func WriteGoMod() { - // If we're using -mod=vendor we basically ignored - // go.mod, so definitely don't try to write back our - // incomplete view of the world. - if !allowWriteGoMod || cfg.BuildMod == "vendor" { +// commitRequirements writes sets the global requirements variable to rs and +// writes its contents back to the go.mod file on disk. +func commitRequirements(ctx context.Context, goVersion string, rs *Requirements) { + requirements = rs + + if !allowWriteGoMod { + // Some package outside of modload promised to update the go.mod file later. return } - // If we aren't in a module, we don't have anywhere to write a go.mod file. if modRoot == "" { + // We aren't in a module, so we don't have anywhere to write a go.mod file. return } - if cfg.BuildMod != "readonly" { - addGoStmt() + var list []*modfile.Require + for _, m := range rs.rootModules { + list = append(list, &modfile.Require{ + Mod: m, + Indirect: !rs.direct[m.Path], + }) } - - if loaded != nil { - reqs := MinReqs() - min, err := reqs.Required(Target) - if err != nil { - base.Fatalf("go: %v", err) - } - var list []*modfile.Require - for _, m := range min { - list = append(list, &modfile.Require{ - Mod: m, - Indirect: !loaded.direct[m.Path], - }) - } + if goVersion != "" { + modFile.AddGoStmt(goVersion) + } + if semver.Compare("v"+modFileGoVersion(), separateIndirectVersionV) < 0 { modFile.SetRequire(list) + } else { + modFile.SetRequireSeparateIndirect(list) } modFile.Cleanup() dirty := index.modFileIsDirty(modFile) - if dirty && cfg.BuildMod == "readonly" { + if dirty && cfg.BuildMod != "mod" { // If we're about to fail due to -mod=readonly, // prefer to report a dirty go.mod over a dirty go.sum - if cfg.BuildModExplicit { - base.Fatalf("go: updates to go.mod needed, disabled by -mod=readonly") - } else if cfg.BuildModReason != "" { - base.Fatalf("go: updates to go.mod needed, disabled by -mod=readonly\n\t(%s)", cfg.BuildModReason) - } else { - base.Fatalf("go: updates to go.mod needed; to update it:\n\tgo mod tidy") - } + base.Fatalf("go: %v", errGoModDirty) } if !dirty && cfg.CmdName != "mod tidy" { @@ -920,7 +1031,14 @@ func WriteGoMod() { // Don't write go.mod, but write go.sum in case we added or trimmed sums. // 'go mod init' shouldn't write go.sum, since it will be incomplete. if cfg.CmdName != "mod init" { - modfetch.WriteGoSum(keepSums(true)) + modfetch.WriteGoSum(keepSums(ctx, loaded, rs, addBuildListZipSums)) + } + return + } + gomod := ModFilePath() + if _, ok := fsys.OverlayPath(gomod); ok { + if dirty { + base.Fatalf("go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay") } return } @@ -936,7 +1054,7 @@ func WriteGoMod() { // Update go.sum after releasing the side lock and refreshing the index. // 'go mod init' shouldn't write go.sum, since it will be incomplete. if cfg.CmdName != "mod init" { - modfetch.WriteGoSum(keepSums(true)) + modfetch.WriteGoSum(keepSums(ctx, loaded, rs, addBuildListZipSums)) } }() @@ -973,100 +1091,99 @@ func WriteGoMod() { } } -// keepSums returns a set of module sums to preserve in go.sum. The set -// includes entries for all modules used to load packages (according to -// the last load function such as LoadPackages or ImportFromFiles). -// It also contains entries for go.mod files needed for MVS (the version -// of these entries ends with "/go.mod"). -// -// If keepBuildListZips is true, the set also includes sums for zip files for -// all modules in the build list with replacements applied. 'go get' and -// 'go mod download' may add sums to this set when adding a requirement on a -// module without a root package or when downloading a direct or indirect -// dependency. -func keepSums(keepBuildListZips bool) map[module.Version]bool { - // Re-derive the build list using the current list of direct requirements. - // Keep the sum for the go.mod of each visited module version (or its - // replacement). - modkey := func(m module.Version) module.Version { - return module.Version{Path: m.Path, Version: m.Version + "/go.mod"} - } +// keepSums returns the set of modules (and go.mod file entries) for which +// checksums would be needed in order to reload the same set of packages +// loaded by the most recent call to LoadPackages or ImportFromFiles, +// including any go.mod files needed to reconstruct the MVS result, +// in addition to the checksums for every module in keepMods. +func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums) map[module.Version]bool { + // Every module in the full module graph contributes its requirements, + // so in order to ensure that the build list itself is reproducible, + // we need sums for every go.mod in the graph (regardless of whether + // that version is selected). keep := make(map[module.Version]bool) - var mu sync.Mutex - reqs := &keepSumReqs{ - Reqs: &mvsReqs{buildList: buildList}, - visit: func(m module.Version) { - // If we build using a replacement module, keep the sum for the replacement, - // since that's the code we'll actually use during a build. - mu.Lock() - r := Replacement(m) - if r.Path == "" { - keep[modkey(m)] = true - } else { - keep[modkey(r)] = true - } - mu.Unlock() - }, - } - buildList, err := mvs.BuildList(Target, reqs) - if err != nil { - panic(fmt.Sprintf("unexpected error reloading build list: %v", err)) - } - - actualMods := make(map[string]module.Version) - for _, m := range buildList[1:] { - if r := Replacement(m); r.Path != "" { - actualMods[m.Path] = r - } else { - actualMods[m.Path] = m - } - } // Add entries for modules in the build list with paths that are prefixes of - // paths of loaded packages. We need to retain sums for modules needed to - // report ambiguous import errors. We use our re-derived build list, - // since the global build list may have been tidied. - if loaded != nil { - for _, pkg := range loaded.pkgs { - if pkg.testOf != nil || pkg.inStd || module.CheckImportPath(pkg.path) != nil { + // paths of loaded packages. We need to retain sums for all of these modules — + // not just the modules containing the actual packages — in order to rule out + // ambiguous import errors the next time we load the package. + if ld != nil { + for _, pkg := range ld.pkgs { + // We check pkg.mod.Path here instead of pkg.inStd because the + // pseudo-package "C" is not in std, but not provided by any module (and + // shouldn't force loading the whole module graph). + if pkg.testOf != nil || (pkg.mod.Path == "" && pkg.err == nil) || module.CheckImportPath(pkg.path) != nil { continue } + + if rs.depth == lazy && pkg.mod.Path != "" { + if v, ok := rs.rootSelected(pkg.mod.Path); ok && v == pkg.mod.Version { + // pkg was loaded from a root module, and because the main module is + // lazy we do not check non-root modules for conflicts for packages + // that can be found in roots. So we only need the checksums for the + // root modules that may contain pkg, not all possible modules. + for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) { + if v, ok := rs.rootSelected(prefix); ok && v != "none" { + m := module.Version{Path: prefix, Version: v} + keep[resolveReplacement(m)] = true + } + } + continue + } + } + + mg, _ := rs.Graph(ctx) for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) { - if m, ok := actualMods[prefix]; ok { - keep[m] = true + if v := mg.Selected(prefix); v != "none" { + m := module.Version{Path: prefix, Version: v} + keep[resolveReplacement(m)] = true } } } } - // Add entries for the zip of each module in the build list. - // We might not need all of these (tidy does not add them), but they may be - // added by a specific 'go get' or 'go mod download' command to resolve - // missing import sum errors. - if keepBuildListZips { - for _, m := range actualMods { - keep[m] = true + if rs.graph.Load() == nil { + // The module graph was not loaded, possibly because the main module is lazy + // or possibly because we haven't needed to load the graph yet. + // Save sums for the root modules (or their replacements), but don't + // incur the cost of loading the graph just to find and retain the sums. + for _, m := range rs.rootModules { + r := resolveReplacement(m) + keep[modkey(r)] = true + if which == addBuildListZipSums { + keep[r] = true + } + } + } else { + mg, _ := rs.Graph(ctx) + mg.WalkBreadthFirst(func(m module.Version) { + if _, ok := mg.RequiredBy(m); ok { + // The requirements from m's go.mod file are present in the module graph, + // so they are relevant to the MVS result regardless of whether m was + // actually selected. + keep[modkey(resolveReplacement(m))] = true + } + }) + + if which == addBuildListZipSums { + for _, m := range mg.BuildList() { + keep[resolveReplacement(m)] = true + } } } return keep } -// keepSumReqs embeds another Reqs implementation. The Required method -// calls visit for each version in the module graph. -type keepSumReqs struct { - mvs.Reqs - visit func(module.Version) -} +type whichSums int8 -func (r *keepSumReqs) Required(m module.Version) ([]module.Version, error) { - r.visit(m) - return r.Reqs.Required(m) -} +const ( + loadedZipSumsOnly = whichSums(iota) + addBuildListZipSums +) -func TrimGoSum() { - // Don't retain sums for the zip file of every module in the build list. - // We may not need them all to build the main module's packages. - keepBuildListZips := false - modfetch.TrimGoSum(keepSums(keepBuildListZips)) +// modKey returns the module.Version under which the checksum for m's go.mod +// file is stored in the go.sum file. +func modkey(m module.Version) module.Version { + return module.Version{Path: m.Path, Version: m.Version + "/go.mod"} } diff --git a/libgo/go/cmd/go/internal/modload/list.go b/libgo/go/cmd/go/internal/modload/list.go index 7b1aa7f..ccdeb9b 100644 --- a/libgo/go/cmd/go/internal/modload/list.go +++ b/libgo/go/cmd/go/internal/modload/list.go @@ -20,25 +20,42 @@ import ( "golang.org/x/mod/module" ) -func ListModules(ctx context.Context, args []string, listU, listVersions, listRetracted bool) []*modinfo.ModulePublic { - mods := listModules(ctx, args, listVersions, listRetracted) +type ListMode int + +const ( + ListU ListMode = 1 << iota + ListRetracted + ListDeprecated + ListVersions + ListRetractedVersions +) + +// ListModules returns a description of the modules matching args, if known, +// along with any error preventing additional matches from being identified. +// +// The returned slice can be nonempty even if the error is non-nil. +func ListModules(ctx context.Context, args []string, mode ListMode) ([]*modinfo.ModulePublic, error) { + rs, mods, err := listModules(ctx, LoadModFile(ctx), args, mode) type token struct{} sem := make(chan token, runtime.GOMAXPROCS(0)) - if listU || listVersions || listRetracted { + if mode != 0 { for _, m := range mods { add := func(m *modinfo.ModulePublic) { sem <- token{} go func() { - if listU { + if mode&ListU != 0 { addUpdate(ctx, m) } - if listVersions { - addVersions(ctx, m, listRetracted) + if mode&ListVersions != 0 { + addVersions(ctx, m, mode&ListRetractedVersions != 0) } - if listRetracted || listU { + if mode&ListRetracted != 0 { addRetraction(ctx, m) } + if mode&ListDeprecated != 0 { + addDeprecation(ctx, m) + } <-sem }() } @@ -54,17 +71,18 @@ func ListModules(ctx context.Context, args []string, listU, listVersions, listRe sem <- token{} } - return mods + if err == nil { + commitRequirements(ctx, modFileGoVersion(), rs) + } + return mods, err } -func listModules(ctx context.Context, args []string, listVersions, listRetracted bool) []*modinfo.ModulePublic { - LoadAllModules(ctx) +func listModules(ctx context.Context, rs *Requirements, args []string, mode ListMode) (_ *Requirements, mods []*modinfo.ModulePublic, mgErr error) { if len(args) == 0 { - return []*modinfo.ModulePublic{moduleInfo(ctx, buildList[0], true, listRetracted)} + return rs, []*modinfo.ModulePublic{moduleInfo(ctx, rs, Target, mode)}, nil } - var mods []*modinfo.ModulePublic - matchedBuildList := make([]bool, len(buildList)) + needFullGraph := false for _, arg := range args { if strings.Contains(arg, `\`) { base.Fatalf("go: module paths never use backslash") @@ -72,22 +90,62 @@ func listModules(ctx context.Context, args []string, listVersions, listRetracted if search.IsRelativePath(arg) { base.Fatalf("go: cannot use relative path %s to specify module", arg) } - if !HasModRoot() && (arg == "all" || strings.Contains(arg, "...")) { - base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot) + if arg == "all" || strings.Contains(arg, "...") { + needFullGraph = true + if !HasModRoot() { + base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot) + } + continue } if i := strings.Index(arg, "@"); i >= 0 { path := arg[:i] vers := arg[i+1:] + if vers == "upgrade" || vers == "patch" { + if _, ok := rs.rootSelected(path); !ok || rs.depth == eager { + needFullGraph = true + if !HasModRoot() { + base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot) + } + } + } + continue + } + if _, ok := rs.rootSelected(arg); !ok || rs.depth == eager { + needFullGraph = true + if mode&ListVersions == 0 && !HasModRoot() { + base.Fatalf("go: cannot match %q without -versions or an explicit version: %v", arg, ErrNoModRoot) + } + } + } + + var mg *ModuleGraph + if needFullGraph { + rs, mg, mgErr = expandGraph(ctx, rs) + } + + matchedModule := map[module.Version]bool{} + for _, arg := range args { + if i := strings.Index(arg, "@"); i >= 0 { + path := arg[:i] + vers := arg[i+1:] + var current string - for _, m := range buildList { - if m.Path == path { - current = m.Version - break + if mg == nil { + current, _ = rs.rootSelected(path) + } else { + current = mg.Selected(path) + } + if current == "none" && mgErr != nil { + if vers == "upgrade" || vers == "patch" { + // The module graph is incomplete, so we don't know what version we're + // actually upgrading from. + // mgErr is already set, so just skip this module. + continue } } allowed := CheckAllowed - if IsRevisionQuery(vers) || listRetracted { + if IsRevisionQuery(vers) || mode&ListRetracted != 0 { // Allow excluded and retracted versions if the user asked for a // specific revision or used 'go list -retracted'. allowed = nil @@ -101,75 +159,79 @@ func listModules(ctx context.Context, args []string, listVersions, listRetracted }) continue } - mod := moduleInfo(ctx, module.Version{Path: path, Version: info.Version}, false, listRetracted) + + // Indicate that m was resolved from outside of rs by passing a nil + // *Requirements instead. + var noRS *Requirements + + mod := moduleInfo(ctx, noRS, module.Version{Path: path, Version: info.Version}, mode) mods = append(mods, mod) continue } // Module path or pattern. var match func(string) bool - var literal bool if arg == "all" { match = func(string) bool { return true } } else if strings.Contains(arg, "...") { match = search.MatchPattern(arg) } else { - match = func(p string) bool { return arg == p } - literal = true - } - matched := false - for i, m := range buildList { - if i == 0 && !HasModRoot() { - // The root module doesn't actually exist: omit it. + var v string + if mg == nil { + var ok bool + v, ok = rs.rootSelected(arg) + if !ok { + // We checked rootSelected(arg) in the earlier args loop, so if there + // is no such root we should have loaded a non-nil mg. + panic(fmt.Sprintf("internal error: root requirement expected but not found for %v", arg)) + } + } else { + v = mg.Selected(arg) + } + if v == "none" && mgErr != nil { + // mgErr is already set, so just skip this module. continue } + if v != "none" { + mods = append(mods, moduleInfo(ctx, rs, module.Version{Path: arg, Version: v}, mode)) + } else if cfg.BuildMod == "vendor" { + // In vendor mode, we can't determine whether a missing module is “a + // known dependency” because the module graph is incomplete. + // Give a more explicit error message. + mods = append(mods, &modinfo.ModulePublic{ + Path: arg, + Error: modinfoError(arg, "", errors.New("can't resolve module using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)")), + }) + } else if mode&ListVersions != 0 { + // Don't make the user provide an explicit '@latest' when they're + // explicitly asking what the available versions are. Instead, return a + // module with version "none", to which we can add the requested list. + mods = append(mods, &modinfo.ModulePublic{Path: arg}) + } else { + mods = append(mods, &modinfo.ModulePublic{ + Path: arg, + Error: modinfoError(arg, "", errors.New("not a known dependency")), + }) + } + continue + } + + matched := false + for _, m := range mg.BuildList() { if match(m.Path) { matched = true - if !matchedBuildList[i] { - matchedBuildList[i] = true - mods = append(mods, moduleInfo(ctx, m, true, listRetracted)) + if !matchedModule[m] { + matchedModule[m] = true + mods = append(mods, moduleInfo(ctx, rs, m, mode)) } } } if !matched { - if literal { - if listVersions { - // Don't make the user provide an explicit '@latest' when they're - // explicitly asking what the available versions are. - // Instead, resolve the module, even if it isn't an existing dependency. - info, err := Query(ctx, arg, "latest", "", nil) - if err == nil { - mod := moduleInfo(ctx, module.Version{Path: arg, Version: info.Version}, false, listRetracted) - mods = append(mods, mod) - } else { - mods = append(mods, &modinfo.ModulePublic{ - Path: arg, - Error: modinfoError(arg, "", err), - }) - } - continue - } - if cfg.BuildMod == "vendor" { - // In vendor mode, we can't determine whether a missing module is “a - // known dependency” because the module graph is incomplete. - // Give a more explicit error message. - mods = append(mods, &modinfo.ModulePublic{ - Path: arg, - Error: modinfoError(arg, "", errors.New("can't resolve module using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)")), - }) - } else { - mods = append(mods, &modinfo.ModulePublic{ - Path: arg, - Error: modinfoError(arg, "", errors.New("not a known dependency")), - }) - } - } else { - fmt.Fprintf(os.Stderr, "warning: pattern %q matched no module dependencies\n", arg) - } + fmt.Fprintf(os.Stderr, "warning: pattern %q matched no module dependencies\n", arg) } } - return mods + return rs, mods, mgErr } // modinfoError wraps an error to create an error message in diff --git a/libgo/go/cmd/go/internal/modload/load.go b/libgo/go/cmd/go/internal/modload/load.go index 154fc3c..bce9ad8 100644 --- a/libgo/go/cmd/go/internal/modload/load.go +++ b/libgo/go/cmd/go/internal/modload/load.go @@ -49,7 +49,7 @@ package modload // Because "go mod vendor" prunes out the tests of vendored packages, the // behavior of the "all" pattern with -mod=vendor in Go 1.11–1.15 is the same // as the "all" pattern (regardless of the -mod flag) in 1.16+. -// The allClosesOverTests parameter to the loader indicates whether the "all" +// The loader uses the GoVersion parameter to determine whether the "all" // pattern should close over tests (as in Go 1.11–1.15) or stop at only those // packages transitively imported by the packages and tests in the main module // ("all" in Go 1.16+ and "go mod vendor" in Go 1.11+). @@ -121,19 +121,49 @@ import ( "cmd/go/internal/str" "golang.org/x/mod/module" + "golang.org/x/mod/semver" ) // loaded is the most recently-used package loader. // It holds details about individual packages. +// +// This variable should only be accessed directly in top-level exported +// functions. All other functions that require or produce a *loader should pass +// or return it as an explicit parameter. var loaded *loader // PackageOpts control the behavior of the LoadPackages function. type PackageOpts struct { + // GoVersion is the Go version to which the go.mod file should be updated + // after packages have been loaded. + // + // An empty GoVersion means to use the Go version already specified in the + // main module's go.mod file, or the latest Go version if there is no main + // module. + GoVersion string + // Tags are the build tags in effect (as interpreted by the // cmd/go/internal/imports package). // If nil, treated as equivalent to imports.Tags(). Tags map[string]bool + // Tidy, if true, requests that the build list and go.sum file be reduced to + // the minimial dependencies needed to reproducibly reload the requested + // packages. + Tidy bool + + // TidyCompatibleVersion is the oldest Go version that must be able to + // reproducibly reload the requested packages. + // + // If empty, the compatible version is the Go version immediately prior to the + // 'go' version listed in the go.mod file. + TidyCompatibleVersion string + + // VendorModulesInGOROOTSrc indicates that if we are within a module in + // GOROOT/src, packages in the module's vendor directory should be resolved as + // actual module dependencies (instead of standard-library packages). + VendorModulesInGOROOTSrc bool + // ResolveMissingImports indicates that we should attempt to add module // dependencies as needed to resolve imports of packages that are not found. // @@ -141,6 +171,11 @@ type PackageOpts struct { // if the flag is set to "readonly" (the default) or "vendor". ResolveMissingImports bool + // AssumeRootsImported indicates that the transitive dependencies of the root + // packages should be treated as if those roots will be imported by the main + // module. + AssumeRootsImported bool + // AllowPackage, if non-nil, is called after identifying the module providing // each package. If AllowPackage returns a non-nil error, that error is set // for the package, and the imports and test of that package will not be @@ -166,9 +201,16 @@ type PackageOpts struct { // an error occurs. AllowErrors bool - // SilenceErrors indicates that LoadPackages should not print errors - // that occur while loading packages. SilenceErrors implies AllowErrors. - SilenceErrors bool + // SilencePackageErrors indicates that LoadPackages should not print errors + // that occur while matching or loading packages, and should not terminate the + // process if such an error occurs. + // + // Errors encountered in the module graph will still be reported. + // + // The caller may retrieve the silenced package errors using the Lookup + // function, and matching errors are still populated in the Errs field of the + // associated search.Match.) + SilencePackageErrors bool // SilenceMissingStdImports indicates that LoadPackages should not print // errors or terminate the process if an imported package is missing, and the @@ -176,6 +218,15 @@ type PackageOpts struct { // future version). SilenceMissingStdImports bool + // SilenceNoGoErrors indicates that LoadPackages should not print + // imports.ErrNoGo errors. + // This allows the caller to invoke LoadPackages (and report other errors) + // without knowing whether the requested packages exist for the given tags. + // + // Note that if a requested package does not exist *at all*, it will fail + // during module resolution and the error will not be suppressed. + SilenceNoGoErrors bool + // SilenceUnmatchedWarnings suppresses the warnings normally emitted for // patterns that did not match any packages. SilenceUnmatchedWarnings bool @@ -184,7 +235,6 @@ type PackageOpts struct { // LoadPackages identifies the set of packages matching the given patterns and // loads the packages in the import graph rooted at that set. func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (matches []*search.Match, loadedPackages []string) { - LoadModFile(ctx) if opts.Tags == nil { opts.Tags = imports.Tags() } @@ -199,13 +249,13 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma } } - updateMatches := func(ld *loader) { + updateMatches := func(rs *Requirements, ld *loader) { for _, m := range matches { switch { case m.IsLocal(): // Evaluate list of file system directories on first iteration. if m.Dirs == nil { - matchLocalDirs(m) + matchLocalDirs(ctx, m, rs) } // Make a copy of the directory list and translate to import paths. @@ -216,7 +266,7 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma // the loader iterations. m.Pkgs = m.Pkgs[:0] for _, dir := range m.Dirs { - pkg, err := resolveLocalPackage(dir) + pkg, err := resolveLocalPackage(ctx, dir, rs) if err != nil { if !m.IsLiteral() && (err == errPkgIsBuiltin || err == errPkgIsGorootSrc) { continue // Don't include "builtin" or GOROOT/src in wildcard patterns. @@ -239,7 +289,17 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma case strings.Contains(m.Pattern(), "..."): m.Errs = m.Errs[:0] - matchPackages(ctx, m, opts.Tags, includeStd, buildList) + mg, err := rs.Graph(ctx) + if err != nil { + // The module graph is (or may be) incomplete — perhaps we failed to + // load the requirements of some module. This is an error in matching + // the patterns to packages, because we may be missing some packages + // or we may erroneously match packages in the wrong versions of + // modules. However, for cases like 'go list -e', the error should not + // necessarily prevent us from loading the packages we could find. + m.Errs = append(m.Errs, err) + } + matchPackages(ctx, m, opts.Tags, includeStd, mg.BuildList()) case m.Pattern() == "all": if ld == nil { @@ -264,14 +324,16 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma } } - loaded = loadFromRoots(loaderParams{ - PackageOpts: opts, + initialRS, _ := loadModFile(ctx) // Ignore needCommit — we're going to commit at the end regardless. - allClosesOverTests: index.allPatternClosesOverTests() && !opts.UseVendorAll, - allPatternIsRoot: allPatternIsRoot, + ld := loadFromRoots(ctx, loaderParams{ + PackageOpts: opts, + requirements: initialRS, - listRoots: func() (roots []string) { - updateMatches(nil) + allPatternIsRoot: allPatternIsRoot, + + listRoots: func(rs *Requirements) (roots []string) { + updateMatches(rs, nil) for _, m := range matches { roots = append(roots, m.Pkgs...) } @@ -280,47 +342,14 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma }) // One last pass to finalize wildcards. - updateMatches(loaded) - - // Report errors, if any. - checkMultiplePaths() - for _, pkg := range loaded.pkgs { - if pkg.err != nil { - if sumErr := (*ImportMissingSumError)(nil); errors.As(pkg.err, &sumErr) { - if importer := pkg.stack; importer != nil { - sumErr.importer = importer.path - sumErr.importerVersion = importer.mod.Version - sumErr.importerIsTest = importer.testOf != nil - } - } - silence := opts.SilenceErrors - if stdErr := (*ImportMissingError)(nil); errors.As(pkg.err, &stdErr) && - stdErr.isStd && opts.SilenceMissingStdImports { - silence = true - } + updateMatches(ld.requirements, ld) - if !silence { - if opts.AllowErrors { - fmt.Fprintf(os.Stderr, "%s: %v\n", pkg.stackText(), pkg.err) - } else { - base.Errorf("%s: %v", pkg.stackText(), pkg.err) - } - } - } - if !pkg.isTest() { - loadedPackages = append(loadedPackages, pkg.path) - } - } - if !opts.SilenceErrors { - // Also list errors in matching patterns (such as directory permission - // errors for wildcard patterns). + // List errors in matching patterns (such as directory permission + // errors for wildcard patterns). + if !ld.SilencePackageErrors { for _, match := range matches { for _, err := range match.Errs { - if opts.AllowErrors { - fmt.Fprintf(os.Stderr, "%v\n", err) - } else { - base.Errorf("%v", err) - } + ld.errorf("%v\n", err) } } } @@ -330,15 +359,68 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma search.WarnUnmatched(matches) } - // Success! Update go.mod (if needed) and return the results. - WriteGoMod() + if opts.Tidy { + if cfg.BuildV { + mg, _ := ld.requirements.Graph(ctx) + + for _, m := range initialRS.rootModules { + var unused bool + if ld.requirements.depth == eager { + // m is unused if it was dropped from the module graph entirely. If it + // was only demoted from direct to indirect, it may still be in use via + // a transitive import. + unused = mg.Selected(m.Path) == "none" + } else { + // m is unused if it was dropped from the roots. If it is still present + // as a transitive dependency, that transitive dependency is not needed + // by any package or test in the main module. + _, ok := ld.requirements.rootSelected(m.Path) + unused = !ok + } + if unused { + fmt.Fprintf(os.Stderr, "unused %s\n", m.Path) + } + } + } + + keep := keepSums(ctx, ld, ld.requirements, loadedZipSumsOnly) + if compatDepth := modDepthFromGoVersion(ld.TidyCompatibleVersion); compatDepth != ld.requirements.depth { + compatRS := newRequirements(compatDepth, ld.requirements.rootModules, ld.requirements.direct) + ld.checkTidyCompatibility(ctx, compatRS) + + for m := range keepSums(ctx, ld, compatRS, loadedZipSumsOnly) { + keep[m] = true + } + } + + if allowWriteGoMod { + modfetch.TrimGoSum(keep) + + // commitRequirements below will also call WriteGoSum, but the "keep" map + // we have here could be strictly larger: commitRequirements only commits + // loaded.requirements, but here we may have also loaded (and want to + // preserve checksums for) additional entities from compatRS, which are + // only needed for compatibility with ld.TidyCompatibleVersion. + modfetch.WriteGoSum(keep) + } + } + + // Success! Update go.mod and go.sum (if needed) and return the results. + loaded = ld + commitRequirements(ctx, loaded.GoVersion, loaded.requirements) + + for _, pkg := range ld.pkgs { + if !pkg.isTest() { + loadedPackages = append(loadedPackages, pkg.path) + } + } sort.Strings(loadedPackages) return matches, loadedPackages } // matchLocalDirs is like m.MatchDirs, but tries to avoid scanning directories // outside of the standard library and active modules. -func matchLocalDirs(m *search.Match) { +func matchLocalDirs(ctx context.Context, m *search.Match, rs *Requirements) { if !m.IsLocal() { panic(fmt.Sprintf("internal error: resolveLocalDirs on non-local pattern %s", m.Pattern())) } @@ -352,9 +434,9 @@ func matchLocalDirs(m *search.Match) { dir := filepath.Dir(filepath.Clean(m.Pattern()[:i+3])) absDir := dir if !filepath.IsAbs(dir) { - absDir = filepath.Join(base.Cwd, dir) + absDir = filepath.Join(base.Cwd(), dir) } - if search.InDir(absDir, cfg.GOROOTsrc) == "" && search.InDir(absDir, ModRoot()) == "" && pathInModuleCache(absDir) == "" { + if search.InDir(absDir, cfg.GOROOTsrc) == "" && search.InDir(absDir, ModRoot()) == "" && pathInModuleCache(ctx, absDir, rs) == "" { m.Dirs = []string{} m.AddError(fmt.Errorf("directory prefix %s outside available modules", base.ShortPath(absDir))) return @@ -365,12 +447,12 @@ func matchLocalDirs(m *search.Match) { } // resolveLocalPackage resolves a filesystem path to a package path. -func resolveLocalPackage(dir string) (string, error) { +func resolveLocalPackage(ctx context.Context, dir string, rs *Requirements) (string, error) { var absDir string if filepath.IsAbs(dir) { absDir = filepath.Clean(dir) } else { - absDir = filepath.Join(base.Cwd, dir) + absDir = filepath.Join(base.Cwd(), dir) } bp, err := cfg.BuildContext.ImportDir(absDir, 0) @@ -456,7 +538,7 @@ func resolveLocalPackage(dir string) (string, error) { return pkg, nil } - pkg := pathInModuleCache(absDir) + pkg := pathInModuleCache(ctx, absDir, rs) if pkg == "" { return "", fmt.Errorf("directory %s outside available modules", base.ShortPath(absDir)) } @@ -471,7 +553,7 @@ var ( // pathInModuleCache returns the import path of the directory dir, // if dir is in the module cache copy of a module in our build list. -func pathInModuleCache(dir string) string { +func pathInModuleCache(ctx context.Context, dir string, rs *Requirements) string { tryMod := func(m module.Version) (string, bool) { var root string var err error @@ -501,20 +583,48 @@ func pathInModuleCache(dir string) string { return path.Join(m.Path, filepath.ToSlash(sub)), true } - for _, m := range buildList[1:] { - if importPath, ok := tryMod(m); ok { - // checkMultiplePaths ensures that a module can be used for at most one - // requirement, so this must be it. - return importPath + if rs.depth == lazy { + for _, m := range rs.rootModules { + if v, _ := rs.rootSelected(m.Path); v != m.Version { + continue // m is a root, but we have a higher root for the same path. + } + if importPath, ok := tryMod(m); ok { + // checkMultiplePaths ensures that a module can be used for at most one + // requirement, so this must be it. + return importPath + } + } + } + + // None of the roots contained dir, or we're in eager mode and want to load + // the full module graph more aggressively. Either way, check the full graph + // to see if the directory is a non-root dependency. + // + // If the roots are not consistent with the full module graph, the selected + // versions of root modules may differ from what we already checked above. + // Re-check those paths too. + + mg, _ := rs.Graph(ctx) + var importPath string + for _, m := range mg.BuildList() { + var found bool + importPath, found = tryMod(m) + if found { + break } } - return "" + return importPath } // ImportFromFiles adds modules to the build list as needed // to satisfy the imports in the named Go source files. +// +// Errors in missing dependencies are silenced. +// +// TODO(bcmills): Silencing errors seems off. Take a closer look at this and +// figure out what the error-reporting actually ought to be. func ImportFromFiles(ctx context.Context, gofiles []string) { - LoadModFile(ctx) + rs := LoadModFile(ctx) tags := imports.Tags() imports, testImports, err := imports.ScanFiles(gofiles, tags) @@ -522,31 +632,32 @@ func ImportFromFiles(ctx context.Context, gofiles []string) { base.Fatalf("go: %v", err) } - loaded = loadFromRoots(loaderParams{ + loaded = loadFromRoots(ctx, loaderParams{ PackageOpts: PackageOpts{ Tags: tags, ResolveMissingImports: true, + SilencePackageErrors: true, }, - allClosesOverTests: index.allPatternClosesOverTests(), - listRoots: func() (roots []string) { + requirements: rs, + listRoots: func(*Requirements) (roots []string) { roots = append(roots, imports...) roots = append(roots, testImports...) return roots }, }) - WriteGoMod() + commitRequirements(ctx, loaded.GoVersion, loaded.requirements) } // DirImportPath returns the effective import path for dir, // provided it is within the main module, or else returns ".". -func DirImportPath(dir string) string { +func DirImportPath(ctx context.Context, dir string) string { if !HasModRoot() { return "." } - LoadModFile(context.TODO()) + LoadModFile(ctx) // Sets targetPrefix. if !filepath.IsAbs(dir) { - dir = filepath.Join(base.Cwd, dir) + dir = filepath.Join(base.Cwd(), dir) } else { dir = filepath.Clean(dir) } @@ -564,20 +675,6 @@ func DirImportPath(dir string) string { return "." } -// TargetPackages returns the list of packages in the target (top-level) module -// matching pattern, which may be relative to the working directory, under all -// build tag settings. -func TargetPackages(ctx context.Context, pattern string) *search.Match { - // TargetPackages is relative to the main module, so ensure that the main - // module is a thing that can contain packages. - LoadModFile(ctx) - ModRoot() - - m := search.NewMatch(pattern) - matchPackages(ctx, m, imports.AnyTags(), omitStd, []module.Version{Target}) - return m -} - // ImportMap returns the actual package import path // for an import path found in source code. // If the given import path does not appear in the source code @@ -609,29 +706,6 @@ func PackageModule(path string) module.Version { return pkg.mod } -// PackageImports returns the imports for the package named by the import path. -// Test imports will be returned as well if tests were loaded for the package -// (i.e., if "all" was loaded or if LoadTests was set and the path was matched -// by a command line argument). PackageImports will return nil for -// unknown package paths. -func PackageImports(path string) (imports, testImports []string) { - pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) - if !ok { - return nil, nil - } - imports = make([]string, len(pkg.imports)) - for i, p := range pkg.imports { - imports[i] = p.path - } - if pkg.test != nil { - testImports = make([]string, len(pkg.test.imports)) - for i, p := range pkg.test.imports { - testImports[i] = p.path - } - } - return imports, testImports -} - // Lookup returns the source directory, import path, and any loading error for // the package at path as imported from the package in parentDir. // Lookup requires that one of the Load functions in this package has already @@ -670,26 +744,29 @@ func Lookup(parentPath string, parentIsStd bool, path string) (dir, realPath str type loader struct { loaderParams + // allClosesOverTests indicates whether the "all" pattern includes + // dependencies of tests outside the main module (as in Go 1.11–1.15). + // (Otherwise — as in Go 1.16+ — the "all" pattern includes only the packages + // transitively *imported by* the packages and tests in the main module.) + allClosesOverTests bool + work *par.Queue // reset on each iteration roots []*loadPkg pkgCache *par.Cache // package path (string) → *loadPkg pkgs []*loadPkg // transitive closure of loaded packages and tests; populated in buildStacks - - // computed at end of iterations - direct map[string]bool // imported directly by main module } // loaderParams configure the packages loaded by, and the properties reported // by, a loader instance. type loaderParams struct { PackageOpts + requirements *Requirements - allClosesOverTests bool // Does the "all" pattern include the transitive closure of tests of packages in "all"? - allPatternIsRoot bool // Is the "all" pattern an additional root? + allPatternIsRoot bool // Is the "all" pattern an additional root? - listRoots func() []string + listRoots func(rs *Requirements) []string } func (ld *loader) reset() { @@ -704,6 +781,16 @@ func (ld *loader) reset() { ld.pkgs = nil } +// errorf reports an error via either os.Stderr or base.Errorf, +// according to whether ld.AllowErrors is set. +func (ld *loader) errorf(format string, args ...interface{}) { + if ld.AllowErrors { + fmt.Fprintf(os.Stderr, format, args...) + } else { + base.Errorf(format, args...) + } +} + // A loadPkg records information about a single loaded package. type loadPkg struct { // Populated at construction time: @@ -756,6 +843,11 @@ const ( // are also roots (and must be marked pkgIsRoot). pkgIsRoot + // pkgFromRoot indicates that the package is in the transitive closure of + // imports starting at the roots. (Note that every package marked as pkgIsRoot + // is also trivially marked pkgFromRoot.) + pkgFromRoot + // pkgImportsLoaded indicates that the imports and testImports fields of a // loadPkg have been populated. pkgImportsLoaded @@ -796,6 +888,18 @@ func (pkg *loadPkg) isTest() bool { return pkg.testOf != nil } +// fromExternalModule reports whether pkg was loaded from a module other than +// the main module. +func (pkg *loadPkg) fromExternalModule() bool { + if pkg.mod.Path == "" { + return false // loaded from the standard library, not a module + } + if pkg.mod.Path == Target.Path { + return false // loaded from the main module. + } + return true +} + var errMissing = errors.New("cannot find package") // loadFromRoots attempts to load the build graph needed to process a set of @@ -804,20 +908,52 @@ var errMissing = errors.New("cannot find package") // The set of root packages is returned by the params.listRoots function, and // expanded to the full set of packages by tracing imports (and possibly tests) // as needed. -func loadFromRoots(params loaderParams) *loader { +func loadFromRoots(ctx context.Context, params loaderParams) *loader { ld := &loader{ loaderParams: params, work: par.NewQueue(runtime.GOMAXPROCS(0)), } + if ld.GoVersion == "" { + ld.GoVersion = modFileGoVersion() + + if ld.Tidy && semver.Compare("v"+ld.GoVersion, "v"+LatestGoVersion()) > 0 { + ld.errorf("go mod tidy: go.mod file indicates go %s, but maximum supported version is %s\n", ld.GoVersion, LatestGoVersion()) + base.ExitIfErrors() + } + } + + if ld.Tidy { + if ld.TidyCompatibleVersion == "" { + ld.TidyCompatibleVersion = priorGoVersion(ld.GoVersion) + } else if semver.Compare("v"+ld.TidyCompatibleVersion, "v"+ld.GoVersion) > 0 { + // Each version of the Go toolchain knows how to interpret go.mod and + // go.sum files produced by all previous versions, so a compatibility + // version higher than the go.mod version adds nothing. + ld.TidyCompatibleVersion = ld.GoVersion + } + } + + if semver.Compare("v"+ld.GoVersion, narrowAllVersionV) < 0 && !ld.UseVendorAll { + // The module's go version explicitly predates the change in "all" for lazy + // loading, so continue to use the older interpretation. + ld.allClosesOverTests = true + } + var err error - reqs := &mvsReqs{buildList: buildList} - buildList, err = mvs.BuildList(Target, reqs) + ld.requirements, err = convertDepth(ctx, ld.requirements, modDepthFromGoVersion(ld.GoVersion)) if err != nil { - base.Fatalf("go: %v", err) + ld.errorf("go: %v\n", err) + } + + if ld.requirements.depth == eager { + var err error + ld.requirements, _, err = expandGraph(ctx, ld.requirements) + if err != nil { + ld.errorf("go: %v\n", err) + } } - addedModuleFor := make(map[string]bool) for { ld.reset() @@ -825,9 +961,29 @@ func loadFromRoots(params loaderParams) *loader { // Note: the returned roots can change on each iteration, // since the expansion of package patterns depends on the // build list we're using. + rootPkgs := ld.listRoots(ld.requirements) + + if ld.requirements.depth == lazy && cfg.BuildMod == "mod" { + // Before we start loading transitive imports of packages, locate all of + // the root packages and promote their containing modules to root modules + // dependencies. If their go.mod files are tidy (the common case) and the + // set of root packages does not change then we can select the correct + // versions of all transitive imports on the first try and complete + // loading in a single iteration. + changedBuildList := ld.preloadRootModules(ctx, rootPkgs) + if changedBuildList { + // The build list has changed, so the set of root packages may have also + // changed. Start over to pick up the changes. (Preloading roots is much + // cheaper than loading the full import graph, so we would rather pay + // for an extra iteration of preloading than potentially end up + // discarding the result of a full iteration of loading.) + continue + } + } + inRoots := map[*loadPkg]bool{} - for _, path := range ld.listRoots() { - root := ld.pkg(path, pkgIsRoot) + for _, path := range rootPkgs { + root := ld.pkg(ctx, path, pkgIsRoot) if !inRoots[root] { ld.roots = append(ld.roots, root) inRoots[root] = true @@ -843,77 +999,314 @@ func loadFromRoots(params loaderParams) *loader { ld.buildStacks() + changed, err := ld.updateRequirements(ctx) + if err != nil { + ld.errorf("go: %v\n", err) + break + } + if changed { + // Don't resolve missing imports until the module graph have stabilized. + // If the roots are still changing, they may turn out to specify a + // requirement on the missing package(s), and we would rather use a + // version specified by a new root than add a new dependency on an + // unrelated version. + continue + } + if !ld.ResolveMissingImports || (!HasModRoot() && !allowMissingModuleImports) { // We've loaded as much as we can without resolving missing imports. break } - modAddedBy := ld.resolveMissingImports(addedModuleFor) + + modAddedBy := ld.resolveMissingImports(ctx) if len(modAddedBy) == 0 { + // The roots are stable, and we've resolved all of the missing packages + // that we can. break } - // Recompute buildList with all our additions. - reqs = &mvsReqs{buildList: buildList} - buildList, err = mvs.BuildList(Target, reqs) + toAdd := make([]module.Version, 0, len(modAddedBy)) + for m, _ := range modAddedBy { + toAdd = append(toAdd, m) + } + module.Sort(toAdd) // to make errors deterministic + + // We ran updateRequirements before resolving missing imports and it didn't + // make any changes, so we know that the requirement graph is already + // consistent with ld.pkgs: we don't need to pass ld.pkgs to updateRoots + // again. (That would waste time looking for changes that we have already + // applied.) + var noPkgs []*loadPkg + // We also know that we're going to call updateRequirements again next + // iteration so we don't need to also update it here. (That would waste time + // computing a "direct" map that we'll have to recompute later anyway.) + direct := ld.requirements.direct + rs, err := updateRoots(ctx, direct, ld.requirements, noPkgs, toAdd, ld.AssumeRootsImported) if err != nil { // If an error was found in a newly added module, report the package // import stack instead of the module requirement stack. Packages // are more descriptive. if err, ok := err.(*mvs.BuildListError); ok { if pkg := modAddedBy[err.Module()]; pkg != nil { - base.Fatalf("go: %s: %v", pkg.stackText(), err.Err) + ld.errorf("go: %s: %v\n", pkg.stackText(), err.Err) + break } } - base.Fatalf("go: %v", err) + ld.errorf("go: %v\n", err) + break } + if reflect.DeepEqual(rs.rootModules, ld.requirements.rootModules) { + // Something is deeply wrong. resolveMissingImports gave us a non-empty + // set of modules to add to the graph, but adding those modules had no + // effect — either they were already in the graph, or updateRoots did not + // add them as requested. + panic(fmt.Sprintf("internal error: adding %v to module graph had no effect on root requirements (%v)", toAdd, rs.rootModules)) + } + ld.requirements = rs } - base.ExitIfErrors() + base.ExitIfErrors() // TODO(bcmills): Is this actually needed? - // Compute directly referenced dependency modules. - ld.direct = make(map[string]bool) - for _, pkg := range ld.pkgs { - if pkg.mod == Target { - for _, dep := range pkg.imports { - if dep.mod.Path != "" && dep.mod.Path != Target.Path && index != nil { - _, explicit := index.require[dep.mod] - if allowWriteGoMod && cfg.BuildMod == "readonly" && !explicit { - // TODO(#40775): attach error to package instead of using - // base.Errorf. Ideally, 'go list' should not fail because of this, - // but today, LoadPackages calls WriteGoMod unconditionally, which - // would fail with a less clear message. - base.Errorf("go: %[1]s: package %[2]s imported from implicitly required module; to add missing requirements, run:\n\tgo get %[2]s@%[3]s", pkg.path, dep.path, dep.mod.Version) - } - ld.direct[dep.mod.Path] = true + // Tidy the build list, if applicable, before we report errors. + // (The process of tidying may remove errors from irrelevant dependencies.) + if ld.Tidy { + rs, err := tidyRoots(ctx, ld.requirements, ld.pkgs) + if err != nil { + ld.errorf("go: %v\n", err) + } + + if ld.requirements.depth == lazy { + // We continuously add tidy roots to ld.requirements during loading, so at + // this point the tidy roots should be a subset of the roots of + // ld.requirements, ensuring that no new dependencies are brought inside + // the lazy-loading horizon. + // If that is not the case, there is a bug in the loading loop above. + for _, m := range rs.rootModules { + if v, ok := ld.requirements.rootSelected(m.Path); !ok || v != m.Version { + ld.errorf("go mod tidy: internal error: a requirement on %v is needed but was not added during package loading\n", m) + base.ExitIfErrors() } } } + ld.requirements = rs } - base.ExitIfErrors() + + // Report errors, if any. + for _, pkg := range ld.pkgs { + if pkg.err == nil { + continue + } + + // Add importer information to checksum errors. + if sumErr := (*ImportMissingSumError)(nil); errors.As(pkg.err, &sumErr) { + if importer := pkg.stack; importer != nil { + sumErr.importer = importer.path + sumErr.importerVersion = importer.mod.Version + sumErr.importerIsTest = importer.testOf != nil + } + } + + if ld.SilencePackageErrors { + continue + } + if stdErr := (*ImportMissingError)(nil); errors.As(pkg.err, &stdErr) && + stdErr.isStd && ld.SilenceMissingStdImports { + continue + } + if ld.SilenceNoGoErrors && errors.Is(pkg.err, imports.ErrNoGo) { + continue + } + + ld.errorf("%s: %v\n", pkg.stackText(), pkg.err) + } + + ld.checkMultiplePaths() + return ld +} + +// updateRequirements ensures that ld.requirements is consistent with the +// information gained from ld.pkgs and includes the modules in add as roots at +// at least the given versions. +// +// In particular: +// +// - Modules that provide packages directly imported from the main module are +// marked as direct, and are promoted to explicit roots. If a needed root +// cannot be promoted due to -mod=readonly or -mod=vendor, the importing +// package is marked with an error. +// +// - If ld scanned the "all" pattern independent of build constraints, it is +// guaranteed to have seen every direct import. Module dependencies that did +// not provide any directly-imported package are then marked as indirect. +// +// - Root dependencies are updated to their selected versions. +// +// The "changed" return value reports whether the update changed the selected +// version of any module that either provided a loaded package or may now +// provide a package that was previously unresolved. +func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err error) { + rs := ld.requirements + + // direct contains the set of modules believed to provide packages directly + // imported by the main module. + var direct map[string]bool // If we didn't scan all of the imports from the main module, or didn't use // imports.AnyTags, then we didn't necessarily load every package that - // contributes “direct” imports — so we can't safely mark existing - // dependencies as indirect-only. - // Conservatively mark those dependencies as direct. - if modFile != nil && (!ld.allPatternIsRoot || !reflect.DeepEqual(ld.Tags, imports.AnyTags())) { - for _, r := range modFile.Require { - if !r.Indirect { - ld.direct[r.Mod.Path] = true + // contributes “direct” imports — so we can't safely mark existing direct + // dependencies in ld.requirements as indirect-only. Propagate them as direct. + loadedDirect := ld.allPatternIsRoot && reflect.DeepEqual(ld.Tags, imports.AnyTags()) + if loadedDirect { + direct = make(map[string]bool) + } else { + // TODO(bcmills): It seems like a shame to allocate and copy a map here when + // it will only rarely actually vary from rs.direct. Measure this cost and + // maybe avoid the copy. + direct = make(map[string]bool, len(rs.direct)) + for mPath := range rs.direct { + direct[mPath] = true + } + } + + for _, pkg := range ld.pkgs { + if pkg.mod != Target { + continue + } + for _, dep := range pkg.imports { + if !dep.fromExternalModule() { + continue + } + + if pkg.err == nil && cfg.BuildMod != "mod" { + if v, ok := rs.rootSelected(dep.mod.Path); !ok || v != dep.mod.Version { + // dep.mod is not an explicit dependency, but needs to be. + // Because we are not in "mod" mode, we will not be able to update it. + // Instead, mark the importing package with an error. + // + // TODO(#41688): The resulting error message fails to include the file + // position of the import statement (because that information is not + // tracked by the module loader). Figure out how to plumb the import + // position through. + pkg.err = &DirectImportFromImplicitDependencyError{ + ImporterPath: pkg.path, + ImportedPath: dep.path, + Module: dep.mod, + } + // cfg.BuildMod does not allow us to change dep.mod to be a direct + // dependency, so don't mark it as such. + continue + } } + + // dep is a package directly imported by a package or test in the main + // module and loaded from some other module (not the standard library). + // Mark its module as a direct dependency. + direct[dep.mod.Path] = true } } - return ld + var addRoots []module.Version + if ld.Tidy { + // When we are tidying a lazy module, we may need to add roots to preserve + // the versions of indirect, test-only dependencies that are upgraded + // above or otherwise missing from the go.mod files of direct + // dependencies. (For example, the direct dependency might be a very + // stable codebase that predates modules and thus lacks a go.mod file, or + // the author of the direct dependency may have forgotten to commit a + // change to the go.mod file, or may have made an erroneous hand-edit that + // causes it to be untidy.) + // + // Promoting an indirect dependency to a root adds the next layer of its + // dependencies to the module graph, which may increase the selected + // versions of other modules from which we have already loaded packages. + // So after we promote an indirect dependency to a root, we need to reload + // packages, which means another iteration of loading. + // + // As an extra wrinkle, the upgrades due to promoting a root can cause + // previously-resolved packages to become unresolved. For example, the + // module providing an unstable package might be upgraded to a version + // that no longer contains that package. If we then resolve the missing + // package, we might add yet another root that upgrades away some other + // dependency. (The tests in mod_tidy_convergence*.txt illustrate some + // particularly worrisome cases.) + // + // To ensure that this process of promoting, adding, and upgrading roots + // eventually terminates, during iteration we only ever add modules to the + // root set — we only remove irrelevant roots at the very end of + // iteration, after we have already added every root that we plan to need + // in the (eventual) tidy root set. + // + // Since we do not remove any roots during iteration, even if they no + // longer provide any imported packages, the selected versions of the + // roots can only increase and the set of roots can only expand. The set + // of extant root paths is finite and the set of versions of each path is + // finite, so the iteration *must* reach a stable fixed-point. + tidy, err := tidyRoots(ctx, rs, ld.pkgs) + if err != nil { + return false, err + } + addRoots = tidy.rootModules + } + + rs, err = updateRoots(ctx, direct, rs, ld.pkgs, addRoots, ld.AssumeRootsImported) + if err != nil { + // We don't actually know what even the root requirements are supposed to be, + // so we can't proceed with loading. Return the error to the caller + return false, err + } + + if rs != ld.requirements && !reflect.DeepEqual(rs.rootModules, ld.requirements.rootModules) { + // The roots of the module graph have changed in some way (not just the + // "direct" markings). Check whether the changes affected any of the loaded + // packages. + mg, err := rs.Graph(ctx) + if err != nil { + return false, err + } + for _, pkg := range ld.pkgs { + if pkg.fromExternalModule() && mg.Selected(pkg.mod.Path) != pkg.mod.Version { + changed = true + break + } + if pkg.err != nil { + // Promoting a module to a root may resolve an import that was + // previously missing (by pulling in a previously-prune dependency that + // provides it) or ambiguous (by promoting exactly one of the + // alternatives to a root and ignoring the second-level alternatives) or + // otherwise errored out (by upgrading from a version that cannot be + // fetched to one that can be). + // + // Instead of enumerating all of the possible errors, we'll just check + // whether importFromModules returns nil for the package. + // False-positives are ok: if we have a false-positive here, we'll do an + // extra iteration of package loading this time, but we'll still + // converge when the root set stops changing. + // + // In some sense, we can think of this as ‘upgraded the module providing + // pkg.path from "none" to a version higher than "none"’. + if _, _, err = importFromModules(ctx, pkg.path, rs, nil); err == nil { + changed = true + break + } + } + } + } + + ld.requirements = rs + return changed, nil } -// resolveMissingImports adds module dependencies to the global build list -// in order to resolve missing packages from pkgs. +// resolveMissingImports returns a set of modules that could be added as +// dependencies in order to resolve missing packages from pkgs. // // The newly-resolved packages are added to the addedModuleFor map, and -// resolveMissingImports returns a map from each newly-added module version to -// the first package for which that module was added. -func (ld *loader) resolveMissingImports(addedModuleFor map[string]bool) (modAddedBy map[module.Version]*loadPkg) { - var needPkgs []*loadPkg +// resolveMissingImports returns a map from each new module version to +// the first missing package that module would resolve. +func (ld *loader) resolveMissingImports(ctx context.Context) (modAddedBy map[module.Version]*loadPkg) { + type pkgMod struct { + pkg *loadPkg + mod *module.Version + } + var pkgMods []pkgMod for _, pkg := range ld.pkgs { if pkg.err == nil { continue @@ -928,30 +1321,47 @@ func (ld *loader) resolveMissingImports(addedModuleFor map[string]bool) (modAdde continue } - needPkgs = append(needPkgs, pkg) - pkg := pkg + var mod module.Version ld.work.Add(func() { - pkg.mod, pkg.err = queryImport(context.TODO(), pkg.path) + var err error + mod, err = queryImport(ctx, pkg.path, ld.requirements) + if err != nil { + // pkg.err was already non-nil, so we can reasonably attribute the error + // for pkg to either the original error or the one returned by + // queryImport. The existing error indicates only that we couldn't find + // the package, whereas the query error also explains why we didn't fix + // the problem — so we prefer the latter. + pkg.err = err + } + + // err is nil, but we intentionally leave pkg.err non-nil and pkg.mod + // unset: we still haven't satisfied other invariants of a + // successfully-loaded package, such as scanning and loading the imports + // of that package. If we succeed in resolving the new dependency graph, + // the caller can reload pkg and update the error at that point. + // + // Even then, the package might not be loaded from the version we've + // identified here. The module may be upgraded by some other dependency, + // or by a transitive dependency of mod itself, or — less likely — the + // package may be rejected by an AllowPackage hook or rendered ambiguous + // by some other newly-added or newly-upgraded dependency. }) + + pkgMods = append(pkgMods, pkgMod{pkg: pkg, mod: &mod}) } <-ld.work.Idle() modAddedBy = map[module.Version]*loadPkg{} - for _, pkg := range needPkgs { - if pkg.err != nil { + for _, pm := range pkgMods { + pkg, mod := pm.pkg, *pm.mod + if mod.Path == "" { continue } - fmt.Fprintf(os.Stderr, "go: found %s in %s %s\n", pkg.path, pkg.mod.Path, pkg.mod.Version) - if addedModuleFor[pkg.path] { - // TODO(bcmills): This should only be an error if pkg.mod is the same - // version we already tried to add previously. - base.Fatalf("go: %s: looping trying to add package", pkg.stackText()) - } - if modAddedBy[pkg.mod] == nil { - modAddedBy[pkg.mod] = pkg - buildList = append(buildList, pkg.mod) + fmt.Fprintf(os.Stderr, "go: found %s in %s %s\n", pkg.path, mod.Path, mod.Version) + if modAddedBy[mod] == nil { + modAddedBy[mod] = pkg } } @@ -965,7 +1375,7 @@ func (ld *loader) resolveMissingImports(addedModuleFor map[string]bool) (modAdde // ld.work queue, and its test (if requested) will also be populated once // imports have been resolved. When ld.work goes idle, all transitive imports of // the requested package (and its test, if requested) will have been loaded. -func (ld *loader) pkg(path string, flags loadPkgFlags) *loadPkg { +func (ld *loader) pkg(ctx context.Context, path string, flags loadPkgFlags) *loadPkg { if flags.has(pkgImportsLoaded) { panic("internal error: (*loader).pkg called with pkgImportsLoaded flag set") } @@ -974,20 +1384,20 @@ func (ld *loader) pkg(path string, flags loadPkgFlags) *loadPkg { pkg := &loadPkg{ path: path, } - ld.applyPkgFlags(pkg, flags) + ld.applyPkgFlags(ctx, pkg, flags) - ld.work.Add(func() { ld.load(pkg) }) + ld.work.Add(func() { ld.load(ctx, pkg) }) return pkg }).(*loadPkg) - ld.applyPkgFlags(pkg, flags) + ld.applyPkgFlags(ctx, pkg, flags) return pkg } // applyPkgFlags updates pkg.flags to set the given flags and propagate the // (transitive) effects of those flags, possibly loading or enqueueing further // packages as a result. -func (ld *loader) applyPkgFlags(pkg *loadPkg, flags loadPkgFlags) { +func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkgFlags) { if flags == 0 { return } @@ -996,6 +1406,9 @@ func (ld *loader) applyPkgFlags(pkg *loadPkg, flags loadPkgFlags) { // This package matches a root pattern by virtue of being in "all". flags |= pkgIsRoot } + if flags.has(pkgIsRoot) { + flags |= pkgFromRoot + } old := pkg.flags.update(flags) new := old | flags @@ -1039,7 +1452,7 @@ func (ld *loader) applyPkgFlags(pkg *loadPkg, flags loadPkgFlags) { // of packages in "all" if "all" closes over test dependencies. testFlags |= pkgInAll } - ld.pkgTest(pkg, testFlags) + ld.pkgTest(ctx, pkg, testFlags) } } @@ -1047,13 +1460,100 @@ func (ld *loader) applyPkgFlags(pkg *loadPkg, flags loadPkgFlags) { // We have just marked pkg with pkgInAll, or we have just loaded its // imports, or both. Now is the time to propagate pkgInAll to the imports. for _, dep := range pkg.imports { - ld.applyPkgFlags(dep, pkgInAll) + ld.applyPkgFlags(ctx, dep, pkgInAll) } } + + if new.has(pkgFromRoot) && !old.has(pkgFromRoot|pkgImportsLoaded) { + for _, dep := range pkg.imports { + ld.applyPkgFlags(ctx, dep, pkgFromRoot) + } + } +} + +// preloadRootModules loads the module requirements needed to identify the +// selected version of each module providing a package in rootPkgs, +// adding new root modules to the module graph if needed. +func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (changedBuildList bool) { + needc := make(chan map[module.Version]bool, 1) + needc <- map[module.Version]bool{} + for _, path := range rootPkgs { + path := path + ld.work.Add(func() { + // First, try to identify the module containing the package using only roots. + // + // If the main module is tidy and the package is in "all" — or if we're + // lucky — we can identify all of its imports without actually loading the + // full module graph. + m, _, err := importFromModules(ctx, path, ld.requirements, nil) + if err != nil { + var missing *ImportMissingError + if errors.As(err, &missing) && ld.ResolveMissingImports { + // This package isn't provided by any selected module. + // If we can find it, it will be a new root dependency. + m, err = queryImport(ctx, path, ld.requirements) + } + if err != nil { + // We couldn't identify the root module containing this package. + // Leave it unresolved; we will report it during loading. + return + } + } + if m.Path == "" { + // The package is in std or cmd. We don't need to change the root set. + return + } + + v, ok := ld.requirements.rootSelected(m.Path) + if !ok || v != m.Version { + // We found the requested package in m, but m is not a root, so + // loadModGraph will not load its requirements. We need to promote the + // module to a root to ensure that any other packages this package + // imports are resolved from correct dependency versions. + // + // (This is the “argument invariant” from the lazy loading design.) + need := <-needc + need[m] = true + needc <- need + } + }) + } + <-ld.work.Idle() + + need := <-needc + if len(need) == 0 { + return false // No roots to add. + } + + toAdd := make([]module.Version, 0, len(need)) + for m := range need { + toAdd = append(toAdd, m) + } + module.Sort(toAdd) + + rs, err := updateRoots(ctx, ld.requirements.direct, ld.requirements, nil, toAdd, ld.AssumeRootsImported) + if err != nil { + // We are missing some root dependency, and for some reason we can't load + // enough of the module dependency graph to add the missing root. Package + // loading is doomed to fail, so fail quickly. + ld.errorf("go: %v\n", err) + base.ExitIfErrors() + return false + } + if reflect.DeepEqual(rs.rootModules, ld.requirements.rootModules) { + // Something is deeply wrong. resolveMissingImports gave us a non-empty + // set of modules to add to the graph, but adding those modules had no + // effect — either they were already in the graph, or updateRoots did not + // add them as requested. + panic(fmt.Sprintf("internal error: adding %v to module graph had no effect on root requirements (%v)", toAdd, rs.rootModules)) + } + + ld.requirements = rs + return true } // load loads an individual package. -func (ld *loader) load(pkg *loadPkg) { +func (ld *loader) load(ctx context.Context, pkg *loadPkg) { if strings.Contains(pkg.path, "@") { // Leave for error during load. return @@ -1072,7 +1572,24 @@ func (ld *loader) load(pkg *loadPkg) { return } - pkg.mod, pkg.dir, pkg.err = importFromBuildList(context.TODO(), pkg.path, buildList) + var mg *ModuleGraph + if ld.requirements.depth == eager { + var err error + mg, err = ld.requirements.Graph(ctx) + if err != nil { + // We already checked the error from Graph in loadFromRoots and/or + // updateRequirements, so we ignored the error on purpose and we should + // keep trying to push past it. + // + // However, because mg may be incomplete (and thus may select inaccurate + // versions), we shouldn't use it to load packages. Instead, we pass a nil + // *ModuleGraph, which will cause mg to first try loading from only the + // main module and root dependencies. + mg = nil + } + } + + pkg.mod, pkg.dir, pkg.err = importFromModules(ctx, pkg.path, ld.requirements, mg) if pkg.dir == "" { return } @@ -1086,10 +1603,10 @@ func (ld *loader) load(pkg *loadPkg) { // about (by reducing churn on the flag bits of dependencies), and costs // essentially nothing (these atomic flag ops are essentially free compared // to scanning source code for imports). - ld.applyPkgFlags(pkg, pkgInAll) + ld.applyPkgFlags(ctx, pkg, pkgInAll) } if ld.AllowPackage != nil { - if err := ld.AllowPackage(context.TODO(), pkg.path, pkg.mod); err != nil { + if err := ld.AllowPackage(ctx, pkg.path, pkg.mod); err != nil { pkg.err = err } } @@ -1120,11 +1637,11 @@ func (ld *loader) load(pkg *loadPkg) { // GOROOT/src/vendor even when "std" is not the main module. path = ld.stdVendor(pkg.path, path) } - pkg.imports = append(pkg.imports, ld.pkg(path, importFlags)) + pkg.imports = append(pkg.imports, ld.pkg(ctx, path, importFlags)) } pkg.testImports = testImports - ld.applyPkgFlags(pkg, pkgImportsLoaded) + ld.applyPkgFlags(ctx, pkg, pkgImportsLoaded) } // pkgTest locates the test of pkg, creating it if needed, and updates its state @@ -1132,7 +1649,7 @@ func (ld *loader) load(pkg *loadPkg) { // // pkgTest requires that the imports of pkg have already been loaded (flagged // with pkgImportsLoaded). -func (ld *loader) pkgTest(pkg *loadPkg, testFlags loadPkgFlags) *loadPkg { +func (ld *loader) pkgTest(ctx context.Context, pkg *loadPkg, testFlags loadPkgFlags) *loadPkg { if pkg.isTest() { panic("pkgTest called on a test package") } @@ -1147,7 +1664,7 @@ func (ld *loader) pkgTest(pkg *loadPkg, testFlags loadPkgFlags) *loadPkg { err: pkg.err, inStd: pkg.inStd, } - ld.applyPkgFlags(pkg.test, testFlags) + ld.applyPkgFlags(ctx, pkg.test, testFlags) createdTest = true }) @@ -1162,12 +1679,12 @@ func (ld *loader) pkgTest(pkg *loadPkg, testFlags loadPkgFlags) *loadPkg { if pkg.inStd { path = ld.stdVendor(test.path, path) } - test.imports = append(test.imports, ld.pkg(path, importFlags)) + test.imports = append(test.imports, ld.pkg(ctx, path, importFlags)) } pkg.testImports = nil - ld.applyPkgFlags(test, pkgImportsLoaded) + ld.applyPkgFlags(ctx, test, pkgImportsLoaded) } else { - ld.applyPkgFlags(test, testFlags) + ld.applyPkgFlags(ctx, test, testFlags) } return test @@ -1181,13 +1698,13 @@ func (ld *loader) stdVendor(parentPath, path string) string { } if str.HasPathPrefix(parentPath, "cmd") { - if Target.Path != "cmd" { + if !ld.VendorModulesInGOROOTSrc || Target.Path != "cmd" { vendorPath := pathpkg.Join("cmd", "vendor", path) if _, err := os.Stat(filepath.Join(cfg.GOROOTsrc, filepath.FromSlash(vendorPath))); err == nil { return vendorPath } } - } else if Target.Path != "std" || str.HasPathPrefix(parentPath, "vendor") { + } else if !ld.VendorModulesInGOROOTSrc || Target.Path != "std" || str.HasPathPrefix(parentPath, "vendor") { // If we are outside of the 'std' module, resolve imports from within 'std' // to the vendor directory. // @@ -1222,6 +1739,242 @@ func (ld *loader) computePatternAll() (all []string) { return all } +// checkMultiplePaths verifies that a given module path is used as itself +// or as a replacement for another module, but not both at the same time. +// +// (See https://golang.org/issue/26607 and https://golang.org/issue/34650.) +func (ld *loader) checkMultiplePaths() { + mods := ld.requirements.rootModules + if cached := ld.requirements.graph.Load(); cached != nil { + if mg := cached.(cachedGraph).mg; mg != nil { + mods = mg.BuildList() + } + } + + firstPath := map[module.Version]string{} + for _, mod := range mods { + src := resolveReplacement(mod) + if prev, ok := firstPath[src]; !ok { + firstPath[src] = mod.Path + } else if prev != mod.Path { + ld.errorf("go: %s@%s used for two different module paths (%s and %s)\n", src.Path, src.Version, prev, mod.Path) + } + } +} + +// checkTidyCompatibility emits an error if any package would be loaded from a +// different module under rs than under ld.requirements. +func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements) { + suggestUpgrade := false + suggestEFlag := false + suggestFixes := func() { + if ld.AllowErrors { + // The user is explicitly ignoring these errors, so don't bother them with + // other options. + return + } + + // We print directly to os.Stderr because this information is advice about + // how to fix errors, not actually an error itself. + // (The actual errors should have been logged already.) + + fmt.Fprintln(os.Stderr) + + goFlag := "" + if ld.GoVersion != modFileGoVersion() { + goFlag = " -go=" + ld.GoVersion + } + + compatFlag := "" + if ld.TidyCompatibleVersion != priorGoVersion(ld.GoVersion) { + compatFlag = " -compat=" + ld.TidyCompatibleVersion + } + if suggestUpgrade { + eDesc := "" + eFlag := "" + if suggestEFlag { + eDesc = ", leaving some packages unresolved" + eFlag = " -e" + } + fmt.Fprintf(os.Stderr, "To upgrade to the versions selected by go %s%s:\n\tgo mod tidy%s -go=%s && go mod tidy%s -go=%s%s\n", ld.TidyCompatibleVersion, eDesc, eFlag, ld.TidyCompatibleVersion, eFlag, ld.GoVersion, compatFlag) + } else if suggestEFlag { + // If some packages are missing but no package is upgraded, then we + // shouldn't suggest upgrading to the Go 1.16 versions explicitly — that + // wouldn't actually fix anything for Go 1.16 users, and *would* break + // something for Go 1.17 users. + fmt.Fprintf(os.Stderr, "To proceed despite packages unresolved in go %s:\n\tgo mod tidy -e%s%s\n", ld.TidyCompatibleVersion, goFlag, compatFlag) + } + + fmt.Fprintf(os.Stderr, "If reproducibility with go %s is not needed:\n\tgo mod tidy%s -compat=%s\n", ld.TidyCompatibleVersion, goFlag, ld.GoVersion) + + // TODO(#46141): Populate the linked wiki page. + fmt.Fprintf(os.Stderr, "For other options, see:\n\thttps://golang.org/doc/modules/pruning\n") + } + + mg, err := rs.Graph(ctx) + if err != nil { + ld.errorf("go mod tidy: error loading go %s module graph: %v\n", ld.TidyCompatibleVersion, err) + suggestFixes() + return + } + + // Re-resolve packages in parallel. + // + // We re-resolve each package — rather than just checking versions — to ensure + // that we have fetched module source code (and, importantly, checksums for + // that source code) for all modules that are necessary to ensure that imports + // are unambiguous. That also produces clearer diagnostics, since we can say + // exactly what happened to the package if it became ambiguous or disappeared + // entirely. + // + // We re-resolve the packages in parallel because this process involves disk + // I/O to check for package sources, and because the process of checking for + // ambiguous imports may require us to download additional modules that are + // otherwise pruned out in Go 1.17 — we don't want to block progress on other + // packages while we wait for a single new download. + type mismatch struct { + mod module.Version + err error + } + mismatchMu := make(chan map[*loadPkg]mismatch, 1) + mismatchMu <- map[*loadPkg]mismatch{} + for _, pkg := range ld.pkgs { + if pkg.mod.Path == "" && pkg.err == nil { + // This package is from the standard library (which does not vary based on + // the module graph). + continue + } + + pkg := pkg + ld.work.Add(func() { + mod, _, err := importFromModules(ctx, pkg.path, rs, mg) + if mod != pkg.mod { + mismatches := <-mismatchMu + mismatches[pkg] = mismatch{mod: mod, err: err} + mismatchMu <- mismatches + } + }) + } + <-ld.work.Idle() + + mismatches := <-mismatchMu + if len(mismatches) == 0 { + // Since we're running as part of 'go mod tidy', the roots of the module + // graph should contain only modules that are relevant to some package in + // the package graph. We checked every package in the package graph and + // didn't find any mismatches, so that must mean that all of the roots of + // the module graph are also consistent. + // + // If we're wrong, Go 1.16 in -mod=readonly mode will error out with + // "updates to go.mod needed", which would be very confusing. So instead, + // we'll double-check that our reasoning above actually holds — if it + // doesn't, we'll emit an internal error and hopefully the user will report + // it as a bug. + for _, m := range ld.requirements.rootModules { + if v := mg.Selected(m.Path); v != m.Version { + fmt.Fprintln(os.Stderr) + base.Fatalf("go: internal error: failed to diagnose selected-version mismatch for module %s: go %s selects %s, but go %s selects %s\n\tPlease report this at https://golang.org/issue.", m.Path, ld.GoVersion, m.Version, ld.TidyCompatibleVersion, v) + } + } + return + } + + // Iterate over the packages (instead of the mismatches map) to emit errors in + // deterministic order. + for _, pkg := range ld.pkgs { + mismatch, ok := mismatches[pkg] + if !ok { + continue + } + + if pkg.isTest() { + // We already did (or will) report an error for the package itself, + // so don't report a duplicate (and more vebose) error for its test. + if _, ok := mismatches[pkg.testOf]; !ok { + base.Fatalf("go: internal error: mismatch recorded for test %s, but not its non-test package", pkg.path) + } + continue + } + + switch { + case mismatch.err != nil: + // pkg resolved successfully, but errors out using the requirements in rs. + // + // This could occur because the import is provided by a single lazy root + // (and is thus unambiguous in lazy mode) and also one or more + // transitive dependencies (and is ambiguous in eager mode). + // + // It could also occur because some transitive dependency upgrades the + // module that previously provided the package to a version that no + // longer does, or to a version for which the module source code (but + // not the go.mod file in isolation) has a checksum error. + if missing := (*ImportMissingError)(nil); errors.As(mismatch.err, &missing) { + selected := module.Version{ + Path: pkg.mod.Path, + Version: mg.Selected(pkg.mod.Path), + } + ld.errorf("%s loaded from %v,\n\tbut go %s would fail to locate it in %s\n", pkg.stackText(), pkg.mod, ld.TidyCompatibleVersion, selected) + } else { + if ambiguous := (*AmbiguousImportError)(nil); errors.As(mismatch.err, &ambiguous) { + // TODO: Is this check needed? + } + ld.errorf("%s loaded from %v,\n\tbut go %s would fail to locate it:\n\t%v\n", pkg.stackText(), pkg.mod, ld.TidyCompatibleVersion, mismatch.err) + } + + suggestEFlag = true + + // Even if we press ahead with the '-e' flag, the older version will + // error out in readonly mode if it thinks the go.mod file contains + // any *explicit* dependency that is not at its selected version, + // even if that dependency is not relevant to any package being loaded. + // + // We check for that condition here. If all of the roots are consistent + // the '-e' flag suffices, but otherwise we need to suggest an upgrade. + if !suggestUpgrade { + for _, m := range ld.requirements.rootModules { + if v := mg.Selected(m.Path); v != m.Version { + suggestUpgrade = true + break + } + } + } + + case pkg.err != nil: + // pkg had an error in lazy mode (presumably suppressed with the -e flag), + // but not in eager mode. + // + // This is possible, if, say, the import is unresolved in lazy mode + // (because the "latest" version of each candidate module either is + // unavailable or does not contain the package), but is resolved in + // eager mode due to a newer-than-latest dependency that is normally + // runed out of the module graph. + // + // This could also occur if the source code for the module providing the + // package in lazy mode has a checksum error, but eager mode upgrades + // that module to a version with a correct checksum. + // + // pkg.err should have already been logged elsewhere — along with a + // stack trace — so log only the import path and non-error info here. + suggestUpgrade = true + ld.errorf("%s failed to load from any module,\n\tbut go %s would load it from %v\n", pkg.path, ld.TidyCompatibleVersion, mismatch.mod) + + case pkg.mod != mismatch.mod: + // The package is loaded successfully by both Go versions, but from a + // different module in each. This could lead to subtle (and perhaps even + // unnoticed!) variations in behavior between builds with different + // toolchains. + suggestUpgrade = true + ld.errorf("%s loaded from %v,\n\tbut go %s would select %v\n", pkg.stackText(), pkg.mod, ld.TidyCompatibleVersion, mismatch.mod.Version) + + default: + base.Fatalf("go: internal error: mismatch recorded for package %s, but no differences found", pkg.path) + } + } + + suggestFixes() + base.ExitIfErrors() +} + // scanDir is like imports.ScanDir but elides known magic imports from the list, // so that we do not go looking for packages that don't really exist. // diff --git a/libgo/go/cmd/go/internal/modload/modfile.go b/libgo/go/cmd/go/internal/modload/modfile.go index c6667d0..03e02e7 100644 --- a/libgo/go/cmd/go/internal/modload/modfile.go +++ b/libgo/go/cmd/go/internal/modload/modfile.go @@ -8,6 +8,7 @@ import ( "context" "errors" "fmt" + "os" "path/filepath" "strings" "sync" @@ -15,6 +16,7 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" + "cmd/go/internal/fsys" "cmd/go/internal/lockedfile" "cmd/go/internal/modfetch" "cmd/go/internal/par" @@ -25,14 +27,58 @@ import ( "golang.org/x/mod/semver" ) -// narrowAllVersionV is the Go version (plus leading "v") at which the -// module-module "all" pattern no longer closes over the dependencies of -// tests outside of the main module. -const narrowAllVersionV = "v1.16" -const go116EnableNarrowAll = true +const ( + // narrowAllVersionV is the Go version (plus leading "v") at which the + // module-module "all" pattern no longer closes over the dependencies of + // tests outside of the main module. + narrowAllVersionV = "v1.16" + + // lazyLoadingVersionV is the Go version (plus leading "v") at which a + // module's go.mod file is expected to list explicit requirements on every + // module that provides any package transitively imported by that module. + lazyLoadingVersionV = "v1.17" + + // separateIndirectVersionV is the Go version (plus leading "v") at which + // "// indirect" dependencies are added in a block separate from the direct + // ones. See https://golang.org/issue/45965. + separateIndirectVersionV = "v1.17" +) + +const ( + // go117EnableLazyLoading toggles whether lazy-loading code paths should be + // active. It will be removed once the lazy loading implementation is stable + // and well-tested. + go117EnableLazyLoading = true + + // go1117LazyTODO is a constant that exists only until lazy loading is + // implemented. Its use indicates a condition that will need to change if the + // main module is lazy. + go117LazyTODO = false +) var modFile *modfile.File +// modFileGoVersion returns the (non-empty) Go version at which the requirements +// in modFile are intepreted, or the latest Go version if modFile is nil. +func modFileGoVersion() string { + if modFile == nil { + return LatestGoVersion() + } + if modFile.Go == nil || modFile.Go.Version == "" { + // The main module necessarily has a go.mod file, and that file lacks a + // 'go' directive. The 'go' command has been adding that directive + // automatically since Go 1.12, so this module either dates to Go 1.11 or + // has been erroneously hand-edited. + // + // The semantics of the go.mod file are more-or-less the same from Go 1.11 + // through Go 1.16, changing at 1.17 for lazy loading. So even though a + // go.mod file without a 'go' directive is theoretically a Go 1.11 file, + // scripts may assume that it ends up as a Go 1.16 module. + return "1.16" + } + return modFile.Go.Version +} + // A modFileIndex is an index of data corresponding to a modFile // at a specific point in time. type modFileIndex struct { @@ -53,6 +99,24 @@ type requireMeta struct { indirect bool } +// A modDepth indicates which dependencies should be loaded for a go.mod file. +type modDepth uint8 + +const ( + lazy modDepth = iota // load dependencies only as needed + eager // load all transitive dependencies eagerly +) + +func modDepthFromGoVersion(goVersion string) modDepth { + if !go117EnableLazyLoading { + return eager + } + if semver.Compare("v"+goVersion, lazyLoadingVersionV) < 0 { + return eager + } + return lazy +} + // CheckAllowed returns an error equivalent to ErrDisallowed if m is excluded by // the main module's go.mod or retracted by its author. Most version queries use // this to filter out versions that should not be used. @@ -88,76 +152,53 @@ func (e *excludedError) Is(err error) bool { return err == ErrDisallowed } // CheckRetractions returns an error if module m has been retracted by // its author. -func CheckRetractions(ctx context.Context, m module.Version) error { +func CheckRetractions(ctx context.Context, m module.Version) (err error) { + defer func() { + if retractErr := (*ModuleRetractedError)(nil); err == nil || errors.As(err, &retractErr) { + return + } + // Attribute the error to the version being checked, not the version from + // which the retractions were to be loaded. + if mErr := (*module.ModuleError)(nil); errors.As(err, &mErr) { + err = mErr.Err + } + err = &retractionLoadingError{m: m, err: err} + }() + if m.Version == "" { // Main module, standard library, or file replacement module. // Cannot be retracted. return nil } - - // Look up retraction information from the latest available version of - // the module. Cache retraction information so we don't parse the go.mod - // file repeatedly. - type entry struct { - retract []retraction - err error + if repl := Replacement(module.Version{Path: m.Path}); repl.Path != "" { + // All versions of the module were replaced. + // Don't load retractions, since we'd just load the replacement. + return nil } - path := m.Path - e := retractCache.Do(path, func() (v interface{}) { - ctx, span := trace.StartSpan(ctx, "checkRetractions "+path) - defer span.Done() - - if repl := Replacement(module.Version{Path: m.Path}); repl.Path != "" { - // All versions of the module were replaced with a local directory. - // Don't load retractions. - return &entry{nil, nil} - } - - // Find the latest version of the module. - // Ignore exclusions from the main module's go.mod. - const ignoreSelected = "" - var allowAll AllowedFunc - rev, err := Query(ctx, path, "latest", ignoreSelected, allowAll) - if err != nil { - return &entry{nil, err} - } - - // Load go.mod for that version. - // If the version is replaced, we'll load retractions from the replacement. - // - // If there's an error loading the go.mod, we'll return it here. - // These errors should generally be ignored by callers of checkRetractions, - // since they happen frequently when we're offline. These errors are not - // equivalent to ErrDisallowed, so they may be distinguished from - // retraction errors. - // - // We load the raw file here: the go.mod file may have a different module - // path that we expect if the module or its repository was renamed. - // We still want to apply retractions to other aliases of the module. - rm := module.Version{Path: path, Version: rev.Version} - if repl := Replacement(rm); repl.Path != "" { - rm = repl - } - summary, err := rawGoModSummary(rm) - if err != nil { - return &entry{nil, err} - } - return &entry{summary.retract, nil} - }).(*entry) - if err := e.err; err != nil { - // Attribute the error to the version being checked, not the version from - // which the retractions were to be loaded. - var mErr *module.ModuleError - if errors.As(err, &mErr) { - err = mErr.Err - } - return &retractionLoadingError{m: m, err: err} + // Find the latest available version of the module, and load its go.mod. If + // the latest version is replaced, we'll load the replacement. + // + // If there's an error loading the go.mod, we'll return it here. These errors + // should generally be ignored by callers since they happen frequently when + // we're offline. These errors are not equivalent to ErrDisallowed, so they + // may be distinguished from retraction errors. + // + // We load the raw file here: the go.mod file may have a different module + // path that we expect if the module or its repository was renamed. + // We still want to apply retractions to other aliases of the module. + rm, err := queryLatestVersionIgnoringRetractions(ctx, m.Path) + if err != nil { + return err + } + summary, err := rawGoModSummary(rm) + if err != nil { + return err } var rationale []string isRetracted := false - for _, r := range e.retract { + for _, r := range summary.retract { if semver.Compare(r.Low, m.Version) <= 0 && semver.Compare(m.Version, r.High) <= 0 { isRetracted = true if r.Rationale != "" { @@ -171,8 +212,6 @@ func CheckRetractions(ctx context.Context, m module.Version) error { return nil } -var retractCache par.Cache - type ModuleRetractedError struct { Rationale []string } @@ -182,7 +221,7 @@ func (e *ModuleRetractedError) Error() string { if len(e.Rationale) > 0 { // This is meant to be a short error printed on a terminal, so just // print the first rationale. - msg += ": " + ShortRetractionRationale(e.Rationale[0]) + msg += ": " + ShortMessage(e.Rationale[0], "retracted by module author") } return msg } @@ -204,28 +243,67 @@ func (e *retractionLoadingError) Unwrap() error { return e.err } -// ShortRetractionRationale returns a retraction rationale string that is safe -// to print in a terminal. It returns hard-coded strings if the rationale -// is empty, too long, or contains non-printable characters. -func ShortRetractionRationale(rationale string) string { - const maxRationaleBytes = 500 - if i := strings.Index(rationale, "\n"); i >= 0 { - rationale = rationale[:i] - } - rationale = strings.TrimSpace(rationale) - if rationale == "" { - return "retracted by module author" - } - if len(rationale) > maxRationaleBytes { - return "(rationale omitted: too long)" - } - for _, r := range rationale { +// ShortMessage returns a string from go.mod (for example, a retraction +// rationale or deprecation message) that is safe to print in a terminal. +// +// If the given string is empty, ShortMessage returns the given default. If the +// given string is too long or contains non-printable characters, ShortMessage +// returns a hard-coded string. +func ShortMessage(message, emptyDefault string) string { + const maxLen = 500 + if i := strings.Index(message, "\n"); i >= 0 { + message = message[:i] + } + message = strings.TrimSpace(message) + if message == "" { + return emptyDefault + } + if len(message) > maxLen { + return "(message omitted: too long)" + } + for _, r := range message { if !unicode.IsGraphic(r) && !unicode.IsSpace(r) { - return "(rationale omitted: contains non-printable characters)" + return "(message omitted: contains non-printable characters)" } } // NOTE: the go.mod parser rejects invalid UTF-8, so we don't check that here. - return rationale + return message +} + +// CheckDeprecation returns a deprecation message from the go.mod file of the +// latest version of the given module. Deprecation messages are comments +// before or on the same line as the module directives that start with +// "Deprecated:" and run until the end of the paragraph. +// +// CheckDeprecation returns an error if the message can't be loaded. +// CheckDeprecation returns "", nil if there is no deprecation message. +func CheckDeprecation(ctx context.Context, m module.Version) (deprecation string, err error) { + defer func() { + if err != nil { + err = fmt.Errorf("loading deprecation for %s: %w", m.Path, err) + } + }() + + if m.Version == "" { + // Main module, standard library, or file replacement module. + // Don't look up deprecation. + return "", nil + } + if repl := Replacement(module.Version{Path: m.Path}); repl.Path != "" { + // All versions of the module were replaced. + // We'll look up deprecation separately for the replacement. + return "", nil + } + + latest, err := queryLatestVersionIgnoringRetractions(ctx, m.Path) + if err != nil { + return "", err + } + summary, err := rawGoModSummary(latest) + if err != nil { + return "", err + } + return summary.deprecated, nil } // Replacement returns the replacement for mod, if any, from go.mod. @@ -243,6 +321,15 @@ func Replacement(mod module.Version) module.Version { return module.Version{} } +// resolveReplacement returns the module actually used to load the source code +// for m: either m itself, or the replacement for m (iff m is replaced). +func resolveReplacement(m module.Version) module.Version { + if r := Replacement(m); r.Path != "" { + return r + } + return m +} + // indexModFile rebuilds the index of modFile. // If modFile has been changed since it was first read, // modFile.Cleanup must be called before indexModFile. @@ -257,10 +344,13 @@ func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileInd } i.goVersionV = "" - if modFile.Go != nil { + if modFile.Go == nil { + rawGoVersion.Store(Target, "") + } else { // We're going to use the semver package to compare Go versions, so go ahead // and add the "v" prefix it expects once instead of every time. i.goVersionV = "v" + modFile.Go.Version + rawGoVersion.Store(Target, modFile.Go.Version) } i.require = make(map[module.Version]requireMeta, len(modFile.Require)) @@ -292,23 +382,6 @@ func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileInd return i } -// allPatternClosesOverTests reports whether the "all" pattern includes -// dependencies of tests outside the main module (as in Go 1.11–1.15). -// (Otherwise — as in Go 1.16+ — the "all" pattern includes only the packages -// transitively *imported by* the packages and tests in the main module.) -func (i *modFileIndex) allPatternClosesOverTests() bool { - if !go116EnableNarrowAll { - return true - } - if i != nil && semver.Compare(i.goVersionV, narrowAllVersionV) < 0 { - // The module explicitly predates the change in "all" for lazy loading, so - // continue to use the older interpretation. (If i == nil, we not in any - // module at all and should use the latest semantics.) - return true - } - return false -} - // modFileIsDirty reports whether the go.mod file differs meaningfully // from what was indexed. // If modFile has been changed (even cosmetically) since it was first read, @@ -335,7 +408,7 @@ func (i *modFileIndex) modFileIsDirty(modFile *modfile.File) bool { return true } } else if "v"+modFile.Go.Version != i.goVersionV { - if i.goVersionV == "" && cfg.BuildMod == "readonly" { + if i.goVersionV == "" && cfg.BuildMod != "mod" { // go.mod files did not always require a 'go' version, so do not error out // if one is missing — we may be inside an older module in the module // cache, and should bias toward providing useful behavior. @@ -391,9 +464,11 @@ var rawGoVersion sync.Map // map[module.Version]string // module. type modFileSummary struct { module module.Version - goVersionV string // GoVersion with "v" prefix + goVersion string + depth modDepth require []module.Version retract []retraction + deprecated string } // A retraction consists of a retracted version interval and rationale. @@ -433,19 +508,13 @@ func goModSummary(m module.Version) (*modFileSummary, error) { // return the full list of modules from modules.txt. readVendorList() - // TODO(#36876): Load the "go" version from vendor/modules.txt and store it - // in rawGoVersion with the appropriate key. - // We don't know what versions the vendored module actually relies on, // so assume that it requires everything. summary.require = vendorList return summary, nil } - actual := Replacement(m) - if actual.Path == "" { - actual = m - } + actual := resolveReplacement(m) if HasModRoot() && cfg.BuildMod == "readonly" && actual.Version != "" { key := module.Version{Path: actual.Path, Version: actual.Version + "/go.mod"} if !modfetch.HaveSum(key) { @@ -526,45 +595,24 @@ func rawGoModSummary(m module.Version) (*modFileSummary, error) { } c := rawGoModSummaryCache.Do(m, func() interface{} { summary := new(modFileSummary) - var f *modfile.File - if m.Version == "" { - // m is a replacement module with only a file path. - dir := m.Path - if !filepath.IsAbs(dir) { - dir = filepath.Join(ModRoot(), dir) - } - gomod := filepath.Join(dir, "go.mod") - - data, err := lockedfile.Read(gomod) - if err != nil { - return cached{nil, module.VersionError(m, fmt.Errorf("reading %s: %v", base.ShortPath(gomod), err))} - } - f, err = modfile.ParseLax(gomod, data, nil) - if err != nil { - return cached{nil, module.VersionError(m, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err))} - } - } else { - if !semver.IsValid(m.Version) { - // Disallow the broader queries supported by fetch.Lookup. - base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", m.Path, m.Version) - } - - data, err := modfetch.GoMod(m.Path, m.Version) - if err != nil { - return cached{nil, err} - } - f, err = modfile.ParseLax("go.mod", data, nil) - if err != nil { - return cached{nil, module.VersionError(m, fmt.Errorf("parsing go.mod: %v", err))} - } + name, data, err := rawGoModData(m) + if err != nil { + return cached{nil, err} + } + f, err := modfile.ParseLax(name, data, nil) + if err != nil { + return cached{nil, module.VersionError(m, fmt.Errorf("parsing %s: %v", base.ShortPath(name), err))} } - if f.Module != nil { summary.module = f.Module.Mod + summary.deprecated = f.Module.Deprecated } if f.Go != nil && f.Go.Version != "" { rawGoVersion.LoadOrStore(m, f.Go.Version) - summary.goVersionV = "v" + f.Go.Version + summary.goVersion = f.Go.Version + summary.depth = modDepthFromGoVersion(f.Go.Version) + } else { + summary.depth = eager } if len(f.Require) > 0 { summary.require = make([]module.Version, 0, len(f.Require)) @@ -589,3 +637,84 @@ func rawGoModSummary(m module.Version) (*modFileSummary, error) { } var rawGoModSummaryCache par.Cache // module.Version → rawGoModSummary result + +// rawGoModData returns the content of the go.mod file for module m, ignoring +// all replacements that may apply to m. +// +// rawGoModData cannot be used on the Target module. +// +// Unlike rawGoModSummary, rawGoModData does not cache its results in memory. +// Use rawGoModSummary instead unless you specifically need these bytes. +func rawGoModData(m module.Version) (name string, data []byte, err error) { + if m.Version == "" { + // m is a replacement module with only a file path. + dir := m.Path + if !filepath.IsAbs(dir) { + dir = filepath.Join(ModRoot(), dir) + } + name = filepath.Join(dir, "go.mod") + if gomodActual, ok := fsys.OverlayPath(name); ok { + // Don't lock go.mod if it's part of the overlay. + // On Plan 9, locking requires chmod, and we don't want to modify any file + // in the overlay. See #44700. + data, err = os.ReadFile(gomodActual) + } else { + data, err = lockedfile.Read(gomodActual) + } + if err != nil { + return "", nil, module.VersionError(m, fmt.Errorf("reading %s: %v", base.ShortPath(name), err)) + } + } else { + if !semver.IsValid(m.Version) { + // Disallow the broader queries supported by fetch.Lookup. + base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", m.Path, m.Version) + } + name = "go.mod" + data, err = modfetch.GoMod(m.Path, m.Version) + } + return name, data, err +} + +// queryLatestVersionIgnoringRetractions looks up the latest version of the +// module with the given path without considering retracted or excluded +// versions. +// +// If all versions of the module are replaced, +// queryLatestVersionIgnoringRetractions returns the replacement without making +// a query. +// +// If the queried latest version is replaced, +// queryLatestVersionIgnoringRetractions returns the replacement. +func queryLatestVersionIgnoringRetractions(ctx context.Context, path string) (latest module.Version, err error) { + type entry struct { + latest module.Version + err error + } + e := latestVersionIgnoringRetractionsCache.Do(path, func() interface{} { + ctx, span := trace.StartSpan(ctx, "queryLatestVersionIgnoringRetractions "+path) + defer span.Done() + + if repl := Replacement(module.Version{Path: path}); repl.Path != "" { + // All versions of the module were replaced. + // No need to query. + return &entry{latest: repl} + } + + // Find the latest version of the module. + // Ignore exclusions from the main module's go.mod. + const ignoreSelected = "" + var allowAll AllowedFunc + rev, err := Query(ctx, path, "latest", ignoreSelected, allowAll) + if err != nil { + return &entry{err: err} + } + latest := module.Version{Path: path, Version: rev.Version} + if repl := resolveReplacement(latest); repl.Path != "" { + latest = repl + } + return &entry{latest: latest} + }).(*entry) + return e.latest, e.err +} + +var latestVersionIgnoringRetractionsCache par.Cache // path → queryLatestVersionIgnoringRetractions result diff --git a/libgo/go/cmd/go/internal/modload/mvs.go b/libgo/go/cmd/go/internal/modload/mvs.go index 3101519..87619b4 100644 --- a/libgo/go/cmd/go/internal/modload/mvs.go +++ b/libgo/go/cmd/go/internal/modload/mvs.go @@ -16,17 +16,36 @@ import ( "golang.org/x/mod/semver" ) +// cmpVersion implements the comparison for versions in the module loader. +// +// It is consistent with semver.Compare except that as a special case, +// the version "" is considered higher than all other versions. +// The main module (also known as the target) has no version and must be chosen +// over other versions of the same module in the module dependency graph. +func cmpVersion(v1, v2 string) int { + if v2 == "" { + if v1 == "" { + return 0 + } + return -1 + } + if v1 == "" { + return 1 + } + return semver.Compare(v1, v2) +} + // mvsReqs implements mvs.Reqs for module semantic versions, // with any exclusions or replacements applied internally. type mvsReqs struct { - buildList []module.Version + roots []module.Version } func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) { if mod == Target { // Use the build list as it existed when r was constructed, not the current // global build list. - return r.buildList[1:], nil + return r.roots, nil } if mod.Version == "none" { @@ -47,7 +66,7 @@ func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) { // be chosen over other versions of the same module in the module dependency // graph. func (*mvsReqs) Max(v1, v2 string) string { - if v1 != "" && (v2 == "" || semver.Compare(v1, v2) == -1) { + if cmpVersion(v1, v2) < 0 { return v2 } return v1 @@ -86,12 +105,12 @@ func versions(ctx context.Context, path string, allowed AllowedFunc) ([]string, return versions, err } -// Previous returns the tagged version of m.Path immediately prior to +// previousVersion returns the tagged version of m.Path immediately prior to // m.Version, or version "none" if no prior version is tagged. // // Since the version of Target is not found in the version list, // it has no previous version. -func (*mvsReqs) Previous(m module.Version) (module.Version, error) { +func previousVersion(m module.Version) (module.Version, error) { // TODO(golang.org/issue/38714): thread tracing context through MVS. if m == Target { @@ -111,3 +130,7 @@ func (*mvsReqs) Previous(m module.Version) (module.Version, error) { } return module.Version{Path: m.Path, Version: "none"}, nil } + +func (*mvsReqs) Previous(m module.Version) (module.Version, error) { + return previousVersion(m) +} diff --git a/libgo/go/cmd/go/internal/modload/query.go b/libgo/go/cmd/go/internal/modload/query.go index 8affd179b..e737ca9 100644 --- a/libgo/go/cmd/go/internal/modload/query.go +++ b/libgo/go/cmd/go/internal/modload/query.go @@ -5,13 +5,13 @@ package modload import ( + "bytes" "context" "errors" "fmt" "io/fs" "os" pathpkg "path" - "path/filepath" "sort" "strings" "sync" @@ -177,7 +177,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed return nil, err } - if (query == "upgrade" || query == "patch") && modfetch.IsPseudoVersion(current) && !rev.Time.IsZero() { + if (query == "upgrade" || query == "patch") && module.IsPseudoVersion(current) && !rev.Time.IsZero() { // Don't allow "upgrade" or "patch" to move from a pseudo-version // to a chronologically older version or pseudo-version. // @@ -196,7 +196,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed // newer but v1.1.0 is still an “upgrade”; or v1.0.2 might be a revert of // an unsuccessful fix in v1.0.1, in which case the v1.0.2 commit may be // older than the v1.0.1 commit despite the tag itself being newer.) - currentTime, err := modfetch.PseudoVersionTime(current) + currentTime, err := module.PseudoVersionTime(current) if err == nil && rev.Time.Before(currentTime) { if err := allowed(ctx, module.Version{Path: path, Version: current}); errors.Is(err, ErrDisallowed) { return nil, err @@ -325,18 +325,18 @@ func newQueryMatcher(path string, query, current string, allowed AllowedFunc) (* if current == "" || current == "none" { qm.mayUseLatest = true } else { - qm.mayUseLatest = modfetch.IsPseudoVersion(current) + qm.mayUseLatest = module.IsPseudoVersion(current) qm.filter = func(mv string) bool { return semver.Compare(mv, current) >= 0 } } case query == "patch": - if current == "none" { + if current == "" || current == "none" { return nil, &NoPatchBaseError{path} } if current == "" { qm.mayUseLatest = true } else { - qm.mayUseLatest = modfetch.IsPseudoVersion(current) + qm.mayUseLatest = module.IsPseudoVersion(current) qm.prefix = semver.MajorMinor(current) + "." qm.filter = func(mv string) bool { return semver.Compare(mv, current) >= 0 } } @@ -695,7 +695,9 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin // modulePrefixesExcludingTarget returns all prefixes of path that may plausibly // exist as a module, excluding targetPrefix but otherwise including path -// itself, sorted by descending length. +// itself, sorted by descending length. Prefixes that are not valid module paths +// but are valid package paths (like "m" or "example.com/.gen") are included, +// since they might be replaced. func modulePrefixesExcludingTarget(path string) []string { prefixes := make([]string, 0, strings.Count(path, "/")+1) @@ -747,6 +749,7 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod noPackage *PackageNotInModuleError noVersion *NoMatchingVersionError noPatchBase *NoPatchBaseError + invalidPath *module.InvalidPathError // see comment in case below notExistErr error ) for _, r := range results { @@ -767,6 +770,17 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod if noPatchBase == nil { noPatchBase = rErr } + case *module.InvalidPathError: + // The prefix was not a valid module path, and there was no replacement. + // Prefixes like this may appear in candidateModules, since we handle + // replaced modules that weren't required in the repo lookup process + // (see lookupRepo). + // + // A shorter prefix may be a valid module path and may contain a valid + // import path, so this is a low-priority error. + if invalidPath == nil { + invalidPath = rErr + } default: if errors.Is(rErr, fs.ErrNotExist) { if notExistErr == nil { @@ -800,6 +814,8 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod err = noVersion case noPatchBase != nil: err = noPatchBase + case invalidPath != nil: + err = invalidPath case notExistErr != nil: err = notExistErr default: @@ -904,8 +920,8 @@ func (e *PackageNotInModuleError) ImportPath() string { return "" } -// ModuleHasRootPackage returns whether module m contains a package m.Path. -func ModuleHasRootPackage(ctx context.Context, m module.Version) (bool, error) { +// moduleHasRootPackage returns whether module m contains a package m.Path. +func moduleHasRootPackage(ctx context.Context, m module.Version) (bool, error) { needSum := false root, isLocal, err := fetch(ctx, m, needSum) if err != nil { @@ -915,14 +931,32 @@ func ModuleHasRootPackage(ctx context.Context, m module.Version) (bool, error) { return ok, err } -func versionHasGoMod(ctx context.Context, m module.Version) (bool, error) { - needSum := false - root, _, err := fetch(ctx, m, needSum) +// versionHasGoMod returns whether a version has a go.mod file. +// +// versionHasGoMod fetches the go.mod file (possibly a fake) and true if it +// contains anything other than a module directive with the same path. When a +// module does not have a real go.mod file, the go command acts as if it had one +// that only contained a module directive. Normal go.mod files created after +// 1.12 at least have a go directive. +// +// This function is a heuristic, since it's possible to commit a file that would +// pass this test. However, we only need a heurstic for determining whether +// +incompatible versions may be "latest", which is what this function is used +// for. +// +// This heuristic is useful for two reasons: first, when using a proxy, +// this lets us fetch from the .mod endpoint which is much faster than the .zip +// endpoint. The .mod file is used anyway, even if the .zip file contains a +// go.mod with different content. Second, if we don't fetch the .zip, then +// we don't need to verify it in go.sum. This makes 'go list -m -u' faster +// and simpler. +func versionHasGoMod(_ context.Context, m module.Version) (bool, error) { + _, data, err := rawGoModData(m) if err != nil { return false, err } - fi, err := os.Stat(filepath.Join(root, "go.mod")) - return err == nil && !fi.IsDir(), nil + isFake := bytes.Equal(data, modfetch.LegacyGoMod(m.Path)) + return !isFake, nil } // A versionRepo is a subset of modfetch.Repo that can report information about @@ -993,7 +1027,7 @@ func (rr *replacementRepo) Versions(prefix string) ([]string, error) { if index != nil && len(index.replace) > 0 { path := rr.ModulePath() for m, _ := range index.replace { - if m.Path == path && strings.HasPrefix(m.Version, prefix) && m.Version != "" && !modfetch.IsPseudoVersion(m.Version) { + if m.Path == path && strings.HasPrefix(m.Version, prefix) && m.Version != "" && !module.IsPseudoVersion(m.Version) { versions = append(versions, m.Version) } } @@ -1050,9 +1084,9 @@ func (rr *replacementRepo) Latest() (*modfetch.RevInfo, error) { // used from within some other module, the user will be able to upgrade // the requirement to any real version they choose. if _, pathMajor, ok := module.SplitPathVersion(path); ok && len(pathMajor) > 0 { - v = modfetch.PseudoVersion(pathMajor[1:], "", time.Time{}, "000000000000") + v = module.PseudoVersion(pathMajor[1:], "", time.Time{}, "000000000000") } else { - v = modfetch.PseudoVersion("v0", "", time.Time{}, "000000000000") + v = module.PseudoVersion("v0", "", time.Time{}, "000000000000") } } @@ -1067,9 +1101,9 @@ func (rr *replacementRepo) Latest() (*modfetch.RevInfo, error) { func (rr *replacementRepo) replacementStat(v string) (*modfetch.RevInfo, error) { rev := &modfetch.RevInfo{Version: v} - if modfetch.IsPseudoVersion(v) { - rev.Time, _ = modfetch.PseudoVersionTime(v) - rev.Short, _ = modfetch.PseudoVersionRev(v) + if module.IsPseudoVersion(v) { + rev.Time, _ = module.PseudoVersionTime(v) + rev.Short, _ = module.PseudoVersionRev(v) } return rev, nil } diff --git a/libgo/go/cmd/go/internal/modload/query_test.go b/libgo/go/cmd/go/internal/modload/query_test.go index e225a0e..a3f2f84 100644 --- a/libgo/go/cmd/go/internal/modload/query_test.go +++ b/libgo/go/cmd/go/internal/modload/query_test.go @@ -106,7 +106,7 @@ var queryTests = []struct { {path: queryRepo, query: "v1.9.10-pre2+metadata", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"}, {path: queryRepo, query: "ed5ffdaa", vers: "v1.9.10-pre2.0.20191220134614-ed5ffdaa1f5e"}, - // golang.org/issue/29262: The major version for for a module without a suffix + // golang.org/issue/29262: The major version for a module without a suffix // should be based on the most recent tag (v1 as appropriate, not v0 // unconditionally). {path: queryRepo, query: "42abcb6df8ee", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"}, @@ -122,7 +122,7 @@ var queryTests = []struct { {path: queryRepo, query: "upgrade", allow: "NOMATCH", err: `no matching versions for query "upgrade"`}, {path: queryRepo, query: "upgrade", current: "v1.9.9", allow: "NOMATCH", err: `vcs-test.golang.org/git/querytest.git@v1.9.9: disallowed module version`}, {path: queryRepo, query: "upgrade", current: "v1.99.99", err: `vcs-test.golang.org/git/querytest.git@v1.99.99: invalid version: unknown revision v1.99.99`}, - {path: queryRepo, query: "patch", current: "", vers: "v1.9.9"}, + {path: queryRepo, query: "patch", current: "", err: `can't query version "patch" of module vcs-test.golang.org/git/querytest.git: no existing version is required`}, {path: queryRepo, query: "patch", current: "v0.1.0", vers: "v0.1.2"}, {path: queryRepo, query: "patch", current: "v1.9.0", vers: "v1.9.9"}, {path: queryRepo, query: "patch", current: "v1.9.10-pre1", vers: "v1.9.10-pre1"}, diff --git a/libgo/go/cmd/go/internal/modload/search.go b/libgo/go/cmd/go/internal/modload/search.go index 4c73c78..0c2e266 100644 --- a/libgo/go/cmd/go/internal/modload/search.go +++ b/libgo/go/cmd/go/internal/modload/search.go @@ -87,7 +87,7 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f } if !fi.IsDir() { - if fi.Mode()&fs.ModeSymlink != 0 && want { + if fi.Mode()&fs.ModeSymlink != 0 && want && strings.Contains(m.Pattern(), "...") { if target, err := fsys.Stat(path); err == nil && target.IsDir() { fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path) } @@ -188,7 +188,7 @@ func MatchInModule(ctx context.Context, pattern string, m module.Version, tags m matchPackages(ctx, match, tags, includeStd, nil) } - LoadModFile(ctx) + LoadModFile(ctx) // Sets Target, needed by fetch and matchPackages. if !match.IsLiteral() { matchPackages(ctx, match, tags, omitStd, []module.Version{m}) diff --git a/libgo/go/cmd/go/internal/modload/stat_openfile.go b/libgo/go/cmd/go/internal/modload/stat_openfile.go index 5842b858..368f893 100644 --- a/libgo/go/cmd/go/internal/modload/stat_openfile.go +++ b/libgo/go/cmd/go/internal/modload/stat_openfile.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (js && wasm) || plan9 // +build js,wasm plan9 // On plan9, per http://9p.io/magic/man2html/2/access: “Since file permissions diff --git a/libgo/go/cmd/go/internal/modload/stat_unix.go b/libgo/go/cmd/go/internal/modload/stat_unix.go index 032fff8..f5f7ce3 100644 --- a/libgo/go/cmd/go/internal/modload/stat_unix.go +++ b/libgo/go/cmd/go/internal/modload/stat_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package modload diff --git a/libgo/go/cmd/go/internal/modload/stat_windows.go b/libgo/go/cmd/go/internal/modload/stat_windows.go index 0ac2391..825e60b 100644 --- a/libgo/go/cmd/go/internal/modload/stat_windows.go +++ b/libgo/go/cmd/go/internal/modload/stat_windows.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package modload diff --git a/libgo/go/cmd/go/internal/modload/vendor.go b/libgo/go/cmd/go/internal/modload/vendor.go index d8fd91f..80713b0 100644 --- a/libgo/go/cmd/go/internal/modload/vendor.go +++ b/libgo/go/cmd/go/internal/modload/vendor.go @@ -31,6 +31,7 @@ var ( type vendorMetadata struct { Explicit bool Replacement module.Version + GoVersion string } // readVendorList reads the list of vendored modules from vendor/modules.txt. @@ -104,6 +105,10 @@ func readVendorList() { if entry == "explicit" { meta.Explicit = true } + if strings.HasPrefix(entry, "go ") { + meta.GoVersion = strings.TrimPrefix(entry, "go ") + rawGoVersion.Store(mod, meta.GoVersion) + } // All other tokens are reserved for future use. } vendorMeta[mod] = meta diff --git a/libgo/go/cmd/go/internal/mvs/errors.go b/libgo/go/cmd/go/internal/mvs/errors.go index 5564965..bf183ce 100644 --- a/libgo/go/cmd/go/internal/mvs/errors.go +++ b/libgo/go/cmd/go/internal/mvs/errors.go @@ -31,13 +31,15 @@ type buildListErrorElem struct { // occurred at a module found along the given path of requirements and/or // upgrades, which must be non-empty. // -// The isUpgrade function reports whether a path step is due to an upgrade. -// A nil isUpgrade function indicates that none of the path steps are due to upgrades. -func NewBuildListError(err error, path []module.Version, isUpgrade func(from, to module.Version) bool) *BuildListError { +// The isVersionChange function reports whether a path step is due to an +// explicit upgrade or downgrade (as opposed to an existing requirement in a +// go.mod file). A nil isVersionChange function indicates that none of the path +// steps are due to explicit version changes. +func NewBuildListError(err error, path []module.Version, isVersionChange func(from, to module.Version) bool) *BuildListError { stack := make([]buildListErrorElem, 0, len(path)) for len(path) > 1 { reason := "requires" - if isUpgrade != nil && isUpgrade(path[0], path[1]) { + if isVersionChange != nil && isVersionChange(path[0], path[1]) { reason = "updating to" } stack = append(stack, buildListErrorElem{ diff --git a/libgo/go/cmd/go/internal/mvs/graph.go b/libgo/go/cmd/go/internal/mvs/graph.go new file mode 100644 index 0000000..c5de486 --- /dev/null +++ b/libgo/go/cmd/go/internal/mvs/graph.go @@ -0,0 +1,223 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mvs + +import ( + "fmt" + + "golang.org/x/mod/module" +) + +// Graph implements an incremental version of the MVS algorithm, with the +// requirements pushed by the caller instead of pulled by the MVS traversal. +type Graph struct { + cmp func(v1, v2 string) int + roots []module.Version + + required map[module.Version][]module.Version + + isRoot map[module.Version]bool // contains true for roots and false for reachable non-roots + selected map[string]string // path → version +} + +// NewGraph returns an incremental MVS graph containing only a set of root +// dependencies and using the given max function for version strings. +// +// The caller must ensure that the root slice is not modified while the Graph +// may be in use. +func NewGraph(cmp func(v1, v2 string) int, roots []module.Version) *Graph { + g := &Graph{ + cmp: cmp, + roots: roots[:len(roots):len(roots)], + required: make(map[module.Version][]module.Version), + isRoot: make(map[module.Version]bool), + selected: make(map[string]string), + } + + for _, m := range roots { + g.isRoot[m] = true + if g.cmp(g.Selected(m.Path), m.Version) < 0 { + g.selected[m.Path] = m.Version + } + } + + return g +} + +// Require adds the information that module m requires all modules in reqs. +// The reqs slice must not be modified after it is passed to Require. +// +// m must be reachable by some existing chain of requirements from g's target, +// and Require must not have been called for it already. +// +// If any of the modules in reqs has the same path as g's target, +// the target must have higher precedence than the version in req. +func (g *Graph) Require(m module.Version, reqs []module.Version) { + // To help catch disconnected-graph bugs, enforce that all required versions + // are actually reachable from the roots (and therefore should affect the + // selected versions of the modules they name). + if _, reachable := g.isRoot[m]; !reachable { + panic(fmt.Sprintf("%v is not reachable from any root", m)) + } + + // Truncate reqs to its capacity to avoid aliasing bugs if it is later + // returned from RequiredBy and appended to. + reqs = reqs[:len(reqs):len(reqs)] + + if _, dup := g.required[m]; dup { + panic(fmt.Sprintf("requirements of %v have already been set", m)) + } + g.required[m] = reqs + + for _, dep := range reqs { + // Mark dep reachable, regardless of whether it is selected. + if _, ok := g.isRoot[dep]; !ok { + g.isRoot[dep] = false + } + + if g.cmp(g.Selected(dep.Path), dep.Version) < 0 { + g.selected[dep.Path] = dep.Version + } + } +} + +// RequiredBy returns the slice of requirements passed to Require for m, if any, +// with its capacity reduced to its length. +// If Require has not been called for m, RequiredBy(m) returns ok=false. +// +// The caller must not modify the returned slice, but may safely append to it +// and may rely on it not to be modified. +func (g *Graph) RequiredBy(m module.Version) (reqs []module.Version, ok bool) { + reqs, ok = g.required[m] + return reqs, ok +} + +// Selected returns the selected version of the given module path. +// +// If no version is selected, Selected returns version "none". +func (g *Graph) Selected(path string) (version string) { + v, ok := g.selected[path] + if !ok { + return "none" + } + return v +} + +// BuildList returns the selected versions of all modules present in the Graph, +// beginning with the selected versions of each module path in the roots of g. +// +// The order of the remaining elements in the list is deterministic +// but arbitrary. +func (g *Graph) BuildList() []module.Version { + seenRoot := make(map[string]bool, len(g.roots)) + + var list []module.Version + for _, r := range g.roots { + if seenRoot[r.Path] { + // Multiple copies of the same root, with the same or different versions, + // are a bit of a degenerate case: we will take the transitive + // requirements of both roots into account, but only the higher one can + // possibly be selected. However — especially given that we need the + // seenRoot map for later anyway — it is simpler to support this + // degenerate case than to forbid it. + continue + } + + if v := g.Selected(r.Path); v != "none" { + list = append(list, module.Version{Path: r.Path, Version: v}) + } + seenRoot[r.Path] = true + } + uniqueRoots := list + + for path, version := range g.selected { + if !seenRoot[path] { + list = append(list, module.Version{Path: path, Version: version}) + } + } + module.Sort(list[len(uniqueRoots):]) + + return list +} + +// WalkBreadthFirst invokes f once, in breadth-first order, for each module +// version other than "none" that appears in the graph, regardless of whether +// that version is selected. +func (g *Graph) WalkBreadthFirst(f func(m module.Version)) { + var queue []module.Version + enqueued := make(map[module.Version]bool) + for _, m := range g.roots { + if m.Version != "none" { + queue = append(queue, m) + enqueued[m] = true + } + } + + for len(queue) > 0 { + m := queue[0] + queue = queue[1:] + + f(m) + + reqs, _ := g.RequiredBy(m) + for _, r := range reqs { + if !enqueued[r] && r.Version != "none" { + queue = append(queue, r) + enqueued[r] = true + } + } + } +} + +// FindPath reports a shortest requirement path starting at one of the roots of +// the graph and ending at a module version m for which f(m) returns true, or +// nil if no such path exists. +func (g *Graph) FindPath(f func(module.Version) bool) []module.Version { + // firstRequires[a] = b means that in a breadth-first traversal of the + // requirement graph, the module version a was first required by b. + firstRequires := make(map[module.Version]module.Version) + + queue := g.roots + for _, m := range g.roots { + firstRequires[m] = module.Version{} + } + + for len(queue) > 0 { + m := queue[0] + queue = queue[1:] + + if f(m) { + // Construct the path reversed (because we're starting from the far + // endpoint), then reverse it. + path := []module.Version{m} + for { + m = firstRequires[m] + if m.Path == "" { + break + } + path = append(path, m) + } + + i, j := 0, len(path)-1 + for i < j { + path[i], path[j] = path[j], path[i] + i++ + j-- + } + + return path + } + + reqs, _ := g.RequiredBy(m) + for _, r := range reqs { + if _, seen := firstRequires[r]; !seen { + queue = append(queue, r) + firstRequires[r] = m + } + } + } + + return nil +} diff --git a/libgo/go/cmd/go/internal/mvs/mvs.go b/libgo/go/cmd/go/internal/mvs/mvs.go index b630b61..6969f90 100644 --- a/libgo/go/cmd/go/internal/mvs/mvs.go +++ b/libgo/go/cmd/go/internal/mvs/mvs.go @@ -10,7 +10,6 @@ import ( "fmt" "sort" "sync" - "sync/atomic" "cmd/go/internal/par" @@ -41,6 +40,11 @@ type Reqs interface { // Note that v1 < v2 can be written Max(v1, v2) != v1 // and similarly v1 <= v2 can be written Max(v1, v2) == v2. Max(v1, v2 string) string +} + +// An UpgradeReqs is a Reqs that can also identify available upgrades. +type UpgradeReqs interface { + Reqs // Upgrade returns the upgraded version of m, // for use during an UpgradeAll operation. @@ -54,6 +58,11 @@ type Reqs interface { // TODO(rsc): Upgrade must be able to return errors, // but should "no latest version" just return m instead? Upgrade(m module.Version) (module.Version, error) +} + +// A DowngradeReqs is a Reqs that can also identify available downgrades. +type DowngradeReqs interface { + Reqs // Previous returns the version of m.Path immediately prior to m.Version, // or "none" if no such version is known. @@ -81,151 +90,91 @@ func BuildList(target module.Version, reqs Reqs) ([]module.Version, error) { } func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) (module.Version, error)) ([]module.Version, error) { - // Explore work graph in parallel in case reqs.Required - // does high-latency network operations. - type modGraphNode struct { - m module.Version - required []module.Version - upgrade module.Version - err error + cmp := func(v1, v2 string) int { + if reqs.Max(v1, v2) != v1 { + return -1 + } + if reqs.Max(v2, v1) != v2 { + return 1 + } + return 0 } + var ( mu sync.Mutex - modGraph = map[module.Version]*modGraphNode{} - min = map[string]string{} // maps module path to minimum required version - haveErr int32 + g = NewGraph(cmp, []module.Version{target}) + upgrades = map[module.Version]module.Version{} + errs = map[module.Version]error{} // (non-nil errors only) ) - setErr := func(n *modGraphNode, err error) { - n.err = err - atomic.StoreInt32(&haveErr, 1) - } + // Explore work graph in parallel in case reqs.Required + // does high-latency network operations. var work par.Work work.Add(target) work.Do(10, func(item interface{}) { m := item.(module.Version) - node := &modGraphNode{m: m} - mu.Lock() - modGraph[m] = node + var required []module.Version + var err error if m.Version != "none" { - if v, ok := min[m.Path]; !ok || reqs.Max(v, m.Version) != v { - min[m.Path] = m.Version - } + required, err = reqs.Required(m) } - mu.Unlock() - if m.Version != "none" { - required, err := reqs.Required(m) - if err != nil { - setErr(node, err) - return - } - node.required = required - for _, r := range node.required { - work.Add(r) + u := m + if upgrade != nil { + upgradeTo, upErr := upgrade(m) + if upErr == nil { + u = upgradeTo + } else if err == nil { + err = upErr } } - if upgrade != nil { - u, err := upgrade(m) - if err != nil { - setErr(node, err) - return - } - if u != m { - node.upgrade = u - work.Add(u) - } + mu.Lock() + if err != nil { + errs[m] = err + } + if u != m { + upgrades[m] = u + required = append([]module.Version{u}, required...) + } + g.Require(m, required) + mu.Unlock() + + for _, r := range required { + work.Add(r) } }) // If there was an error, find the shortest path from the target to the // node where the error occurred so we can report a useful error message. - if haveErr != 0 { - // neededBy[a] = b means a was added to the module graph by b. - neededBy := make(map[*modGraphNode]*modGraphNode) - q := make([]*modGraphNode, 0, len(modGraph)) - q = append(q, modGraph[target]) - for len(q) > 0 { - node := q[0] - q = q[1:] - - if node.err != nil { - pathUpgrade := map[module.Version]module.Version{} - - // Construct the error path reversed (from the error to the main module), - // then reverse it to obtain the usual order (from the main module to - // the error). - errPath := []module.Version{node.m} - for n, prev := neededBy[node], node; n != nil; n, prev = neededBy[n], n { - if n.upgrade == prev.m { - pathUpgrade[n.m] = prev.m - } - errPath = append(errPath, n.m) - } - i, j := 0, len(errPath)-1 - for i < j { - errPath[i], errPath[j] = errPath[j], errPath[i] - i++ - j-- - } - - isUpgrade := func(from, to module.Version) bool { - return pathUpgrade[from] == to - } - - return nil, NewBuildListError(node.err, errPath, isUpgrade) - } + if len(errs) > 0 { + errPath := g.FindPath(func(m module.Version) bool { + return errs[m] != nil + }) + if len(errPath) == 0 { + panic("internal error: could not reconstruct path to module with error") + } - neighbors := node.required - if node.upgrade.Path != "" { - neighbors = append(neighbors, node.upgrade) - } - for _, neighbor := range neighbors { - nn := modGraph[neighbor] - if neededBy[nn] != nil { - continue - } - neededBy[nn] = node - q = append(q, nn) + err := errs[errPath[len(errPath)-1]] + isUpgrade := func(from, to module.Version) bool { + if u, ok := upgrades[from]; ok { + return u == to } + return false } + return nil, NewBuildListError(err.(error), errPath, isUpgrade) } // The final list is the minimum version of each module found in the graph. - - if v := min[target.Path]; v != target.Version { + list := g.BuildList() + if v := list[0]; v != target { // target.Version will be "" for modload, the main client of MVS. // "" denotes the main module, which has no version. However, MVS treats // version strings as opaque, so "" is not a special value here. // See golang.org/issue/31491, golang.org/issue/29773. - panic(fmt.Sprintf("mistake: chose version %q instead of target %+v", v, target)) // TODO: Don't panic. + panic(fmt.Sprintf("mistake: chose version %q instead of target %+v", v, target)) } - - list := []module.Version{target} - for path, vers := range min { - if path != target.Path { - list = append(list, module.Version{Path: path, Version: vers}) - } - - n := modGraph[module.Version{Path: path, Version: vers}] - required := n.required - for _, r := range required { - if r.Version == "none" { - continue - } - v := min[r.Path] - if r.Path != target.Path && reqs.Max(v, r.Version) != v { - panic(fmt.Sprintf("mistake: version %q does not satisfy requirement %+v", v, r)) // TODO: Don't panic. - } - } - } - - tail := list[1:] - sort.Slice(tail, func(i, j int) bool { - return tail[i].Path < tail[j].Path - }) return list, nil } @@ -293,10 +242,15 @@ func Req(target module.Version, base []string, reqs Reqs) ([]module.Version, err } // First walk the base modules that must be listed. var min []module.Version + haveBase := map[string]bool{} for _, path := range base { + if haveBase[path] { + continue + } m := module.Version{Path: path, Version: max[path]} min = append(min, m) walk(m) + haveBase[path] = true } // Now the reverse postorder to bring in anything else. for i := len(postorder) - 1; i >= 0; i-- { @@ -318,7 +272,7 @@ func Req(target module.Version, base []string, reqs Reqs) ([]module.Version, err // UpgradeAll returns a build list for the target module // in which every module is upgraded to its latest version. -func UpgradeAll(target module.Version, reqs Reqs) ([]module.Version, error) { +func UpgradeAll(target module.Version, reqs UpgradeReqs) ([]module.Version, error) { return buildList(target, reqs, func(m module.Version) (module.Version, error) { if m.Path == target.Path { return target, nil @@ -330,7 +284,7 @@ func UpgradeAll(target module.Version, reqs Reqs) ([]module.Version, error) { // Upgrade returns a build list for the target module // in which the given additional modules are upgraded. -func Upgrade(target module.Version, reqs Reqs, upgrade ...module.Version) ([]module.Version, error) { +func Upgrade(target module.Version, reqs UpgradeReqs, upgrade ...module.Version) ([]module.Version, error) { list, err := reqs.Required(target) if err != nil { return nil, err @@ -369,11 +323,20 @@ func Upgrade(target module.Version, reqs Reqs, upgrade ...module.Version) ([]mod // The versions to be downgraded may be unreachable from reqs.Latest and // reqs.Previous, but the methods of reqs must otherwise handle such versions // correctly. -func Downgrade(target module.Version, reqs Reqs, downgrade ...module.Version) ([]module.Version, error) { - list, err := reqs.Required(target) +func Downgrade(target module.Version, reqs DowngradeReqs, downgrade ...module.Version) ([]module.Version, error) { + // Per https://research.swtch.com/vgo-mvs#algorithm_4: + // “To avoid an unnecessary downgrade to E 1.1, we must also add a new + // requirement on E 1.2. We can apply Algorithm R to find the minimal set of + // new requirements to write to go.mod.” + // + // In order to generate those new requirements, we need to identify versions + // for every module in the build list — not just reqs.Required(target). + list, err := BuildList(target, reqs) if err != nil { return nil, err } + list = list[1:] // remove target + max := make(map[string]string) for _, r := range list { max[r.Path] = r.Version @@ -406,6 +369,9 @@ func Downgrade(target module.Version, reqs Reqs, downgrade ...module.Version) ([ } added[m] = true if v, ok := max[m.Path]; ok && reqs.Max(m.Version, v) != v { + // m would upgrade an existing dependency — it is not a strict downgrade, + // and because it was already present as a dependency, it could affect the + // behavior of other relevant packages. exclude(m) return } @@ -422,6 +388,7 @@ func Downgrade(target module.Version, reqs Reqs, downgrade ...module.Version) ([ // is transient (we couldn't download go.mod), return the error from // Downgrade. Currently, we can't tell what kind of error it is. exclude(m) + return } for _, r := range list { add(r) @@ -433,8 +400,8 @@ func Downgrade(target module.Version, reqs Reqs, downgrade ...module.Version) ([ } } - var out []module.Version - out = append(out, target) + downgraded := make([]module.Version, 0, len(list)+1) + downgraded = append(downgraded, target) List: for _, r := range list { add(r) @@ -461,10 +428,49 @@ List: add(p) r = p } - out = append(out, r) + downgraded = append(downgraded, r) } - return out, nil + // The downgrades we computed above only downgrade to versions enumerated by + // reqs.Previous. However, reqs.Previous omits some versions — such as + // pseudo-versions and retracted versions — that may be selected as transitive + // requirements of other modules. + // + // If one of those requirements pulls the version back up above the version + // identified by reqs.Previous, then the transitive dependencies of that that + // initially-downgraded version should no longer matter — in particular, we + // should not add new dependencies on module paths that nothing else in the + // updated module graph even requires. + // + // In order to eliminate those spurious dependencies, we recompute the build + // list with the actual versions of the downgraded modules as selected by MVS, + // instead of our initial downgrades. + // (See the downhiddenartifact and downhiddencross test cases). + actual, err := BuildList(target, &override{ + target: target, + list: downgraded, + Reqs: reqs, + }) + if err != nil { + return nil, err + } + actualVersion := make(map[string]string, len(actual)) + for _, m := range actual { + actualVersion[m.Path] = m.Version + } + + downgraded = downgraded[:0] + for _, m := range list { + if v, ok := actualVersion[m.Path]; ok { + downgraded = append(downgraded, module.Version{Path: m.Path, Version: v}) + } + } + + return BuildList(target, &override{ + target: target, + list: downgraded, + Reqs: reqs, + }) } type override struct { diff --git a/libgo/go/cmd/go/internal/mvs/mvs_test.go b/libgo/go/cmd/go/internal/mvs/mvs_test.go index 721cd96..598ed66 100644 --- a/libgo/go/cmd/go/internal/mvs/mvs_test.go +++ b/libgo/go/cmd/go/internal/mvs/mvs_test.go @@ -28,10 +28,11 @@ D4: E2 F1 D5: E2 G1: C4 A2: B1 C4 D4 -build A: A B1 C2 D4 E2 F1 -upgrade* A: A B1 C4 D5 E2 F1 G1 -upgrade A C4: A B1 C4 D4 E2 F1 G1 -downgrade A2 D2: A2 C4 D2 +build A: A B1 C2 D4 E2 F1 +upgrade* A: A B1 C4 D5 E2 F1 G1 +upgrade A C4: A B1 C4 D4 E2 F1 G1 +build A2: A2 B1 C4 D4 E2 F1 G1 +downgrade A2 D2: A2 C4 D2 E2 F1 G1 name: trim A: B1 C2 @@ -68,7 +69,7 @@ B2: D1 C: D2 D1: E2 D2: E1 -build A: A B1 C D2 E1 +build A: A B1 C D2 E1 upgrade A B2: A B2 C D2 E2 name: cross1R @@ -136,17 +137,17 @@ name: cross5 A: D1 D1: E2 D2: E1 -build A: A D1 E2 -upgrade* A: A D2 E2 -upgrade A D2: A D2 E2 +build A: A D1 E2 +upgrade* A: A D2 E2 +upgrade A D2: A D2 E2 upgradereq A D2: D2 E2 name: cross6 A: D2 D1: E2 D2: E1 -build A: A D2 E1 -upgrade* A: A D2 E2 +build A: A D2 E1 +upgrade* A: A D2 E2 upgrade A E2: A D2 E2 name: cross7 @@ -175,7 +176,7 @@ B1: D1 B2: C2: D2: -build A: A B1 C1 D1 +build A: A B1 C1 D1 upgrade* A: A B2 C2 D2 name: simplify @@ -194,7 +195,7 @@ B4: B5.hidden: C2: C3: -build A: A B1 C1 +build A: A B1 C1 upgrade* A: A B4 C3 name: up2 @@ -206,15 +207,15 @@ B4: B5.hidden: C2: C3: -build A: A B5.hidden C1 +build A: A B5.hidden C1 upgrade* A: A B5.hidden C3 name: down1 A: B2 B1: C1 B2: C2 -build A: A B2 C2 -downgrade A C1: A B1 +build A: A B2 C2 +downgrade A C1: A B1 C1 name: down2 A: B2 E2 @@ -227,19 +228,113 @@ D2: B2 E2: D2 E1: F1: -downgrade A F1: A B1 E1 +build A: A B2 C2 D2 E2 F2 +downgrade A F1: A B1 C1 D1 E1 F1 + +# https://research.swtch.com/vgo-mvs#algorithm_4: +# “[D]owngrades are constrained to only downgrade packages, not also upgrade +# them; if an upgrade before downgrade is needed, the user must ask for it +# explicitly.” +# +# Here, downgrading B2 to B1 upgrades C1 to C2, and C2 does not depend on D2. +# However, C2 would be an upgrade — not a downgrade — so B1 must also be +# rejected. +name: downcross1 +A: B2 C1 +B1: C2 +B2: C1 +C1: D2 +C2: +D1: +D2: +build A: A B2 C1 D2 +downgrade A D1: A D1 + +# https://research.swtch.com/vgo-mvs#algorithm_4: +# “Unlike upgrades, downgrades must work by removing requirements, not adding +# them.” +# +# However, downgrading a requirement may introduce a new requirement on a +# previously-unrequired module. If each dependency's requirements are complete +# (“tidy”), that can't change the behavior of any other package whose version is +# not also being downgraded, so we should allow it. +name: downcross2 +A: B2 +B1: C1 +B2: D2 +C1: +D1: +D2: +build A: A B2 D2 +downgrade A D1: A B1 C1 D1 name: downcycle A: A B2 B2: A B1: +build A: A B2 downgrade A B1: A B1 +# Both B3 and C2 require D2. +# If we downgrade D to D1, then in isolation B3 would downgrade to B1, +# because B2 is hidden — B1 is the next-highest version that is not hidden. +# However, if we downgrade D, we will also downgrade C to C1. +# And C1 requires B2.hidden, and B2.hidden also meets our requirements: +# it is compatible with D1 and a strict downgrade from B3. +# +# Since neither the initial nor the final build list includes B1, +# and the nothing in the final downgraded build list requires E at all, +# no dependency on E1 (required by only B1) should be introduced. +# +name: downhiddenartifact +A: B3 C2 +A1: B3 +B1: E1 +B2.hidden: +B3: D2 +C1: B2.hidden +C2: D2 +D1: +D2: +build A1: A1 B3 D2 +downgrade A1 D1: A1 B1 D1 E1 +build A: A B3 C2 D2 +downgrade A D1: A B2.hidden C1 D1 + +# Both B3 and C3 require D2. +# If we downgrade D to D1, then in isolation B3 would downgrade to B1, +# and C3 would downgrade to C1. +# But C1 requires B2.hidden, and B1 requires C2.hidden, so we can't +# downgrade to either of those without pulling the other back up a little. +# +# B2.hidden and C2.hidden are both compatible with D1, so that still +# meets our requirements — but then we're in an odd state in which +# B and C have both been downgraded to hidden versions, without any +# remaining requirements to explain how those hidden versions got there. +# +# TODO(bcmills): Would it be better to force downgrades to land on non-hidden +# versions? +# In this case, that would remove the dependencies on B and C entirely. +# +name: downhiddencross +A: B3 C3 +B1: C2.hidden +B2.hidden: +B3: D2 +C1: B2.hidden +C2.hidden: +C3: D2 +D1: +D2: +build A: A B3 C3 D2 +downgrade A D1: A B2.hidden C2.hidden D1 + # golang.org/issue/25542. name: noprev1 A: B4 C2 B2.hidden: C2: +build A: A B4 C2 downgrade A B2.hidden: A B2.hidden C2 name: noprev2 @@ -247,6 +342,7 @@ A: B4 C2 B2.hidden: B1: C2: +build A: A B4 C2 downgrade A B2.hidden: A B2.hidden C2 name: noprev3 @@ -254,6 +350,7 @@ A: B4 C2 B3: B2.hidden: C2: +build A: A B4 C2 downgrade A B2.hidden: A B2.hidden C2 # Cycles involving the target. @@ -264,9 +361,9 @@ A: B1 B1: A1 B2: A2 B3: A3 -build A: A B1 +build A: A B1 upgrade A B2: A B2 -upgrade* A: A B3 +upgrade* A: A B3 # golang.org/issue/29773: # Requirements of older versions of the target @@ -280,7 +377,7 @@ B2: A2 C1: A2 C2: D2: -build A: A B1 C1 D1 +build A: A B1 C1 D1 upgrade* A: A B2 C2 D2 # Cycles with multiple possible solutions. @@ -293,23 +390,23 @@ B2: C2 C1: C2: B2 build M: M A1 B2 C2 -req M: A1 B2 -req M A: A1 B2 -req M C: A1 C2 +req M: A1 B2 +req M A: A1 B2 +req M C: A1 C2 # Requirement minimization. name: req1 A: B1 C1 D1 E1 F1 B1: C1 E1 F1 -req A: B1 D1 +req A: B1 D1 req A C: B1 C1 D1 name: req2 A: G1 H1 G1: H1 H1: G1 -req A: G1 +req A: G1 req A G: G1 req A H: H1 @@ -326,7 +423,20 @@ M: Anone B1 D1 E1 B1: Cnone D1 E1: Fnone build M: M B1 D1 E1 -req M: B1 E1 +req M: B1 E1 + +name: reqdup +M: A1 B1 +A1: B1 +B1: +req M A A: A1 + +name: reqcross +M: A1 B1 C1 +A1: B1 C1 +B1: C1 +C1: +req M A B: A1 B1 ` func Test(t *testing.T) { diff --git a/libgo/go/cmd/go/internal/renameio/renameio.go b/libgo/go/cmd/go/internal/renameio/renameio.go deleted file mode 100644 index 9788171..0000000 --- a/libgo/go/cmd/go/internal/renameio/renameio.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package renameio writes files atomically by renaming temporary files. -package renameio - -import ( - "bytes" - "io" - "io/fs" - "math/rand" - "os" - "path/filepath" - "strconv" - - "cmd/go/internal/robustio" -) - -const patternSuffix = ".tmp" - -// Pattern returns a glob pattern that matches the unrenamed temporary files -// created when writing to filename. -func Pattern(filename string) string { - return filepath.Join(filepath.Dir(filename), filepath.Base(filename)+patternSuffix) -} - -// WriteFile is like os.WriteFile, but first writes data to an arbitrary -// file in the same directory as filename, then renames it atomically to the -// final name. -// -// That ensures that the final location, if it exists, is always a complete file. -func WriteFile(filename string, data []byte, perm fs.FileMode) (err error) { - return WriteToFile(filename, bytes.NewReader(data), perm) -} - -// WriteToFile is a variant of WriteFile that accepts the data as an io.Reader -// instead of a slice. -func WriteToFile(filename string, data io.Reader, perm fs.FileMode) (err error) { - f, err := tempFile(filepath.Dir(filename), filepath.Base(filename), perm) - if err != nil { - return err - } - defer func() { - // Only call os.Remove on f.Name() if we failed to rename it: otherwise, - // some other process may have created a new file with the same name after - // that. - if err != nil { - f.Close() - os.Remove(f.Name()) - } - }() - - if _, err := io.Copy(f, data); err != nil { - return err - } - // Sync the file before renaming it: otherwise, after a crash the reader may - // observe a 0-length file instead of the actual contents. - // See https://golang.org/issue/22397#issuecomment-380831736. - if err := f.Sync(); err != nil { - return err - } - if err := f.Close(); err != nil { - return err - } - - return robustio.Rename(f.Name(), filename) -} - -// ReadFile is like os.ReadFile, but on Windows retries spurious errors that -// may occur if the file is concurrently replaced. -// -// Errors are classified heuristically and retries are bounded, so even this -// function may occasionally return a spurious error on Windows. -// If so, the error will likely wrap one of: -// - syscall.ERROR_ACCESS_DENIED -// - syscall.ERROR_FILE_NOT_FOUND -// - internal/syscall/windows.ERROR_SHARING_VIOLATION -func ReadFile(filename string) ([]byte, error) { - return robustio.ReadFile(filename) -} - -// tempFile creates a new temporary file with given permission bits. -func tempFile(dir, prefix string, perm fs.FileMode) (f *os.File, err error) { - for i := 0; i < 10000; i++ { - name := filepath.Join(dir, prefix+strconv.Itoa(rand.Intn(1000000000))+patternSuffix) - f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, perm) - if os.IsExist(err) { - continue - } - break - } - return -} diff --git a/libgo/go/cmd/go/internal/renameio/renameio_test.go b/libgo/go/cmd/go/internal/renameio/renameio_test.go deleted file mode 100644 index 5b2ed83..0000000 --- a/libgo/go/cmd/go/internal/renameio/renameio_test.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !plan9 - -package renameio - -import ( - "encoding/binary" - "errors" - "internal/testenv" - "math/rand" - "os" - "path/filepath" - "runtime" - "strings" - "sync" - "sync/atomic" - "syscall" - "testing" - "time" - - "cmd/go/internal/robustio" -) - -func TestConcurrentReadsAndWrites(t *testing.T) { - if runtime.GOOS == "darwin" && strings.HasSuffix(testenv.Builder(), "-10_14") { - testenv.SkipFlaky(t, 33041) - } - - dir, err := os.MkdirTemp("", "renameio") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dir) - path := filepath.Join(dir, "blob.bin") - - const chunkWords = 8 << 10 - buf := make([]byte, 2*chunkWords*8) - for i := uint64(0); i < 2*chunkWords; i++ { - binary.LittleEndian.PutUint64(buf[i*8:], i) - } - - var attempts int64 = 128 - if !testing.Short() { - attempts *= 16 - } - const parallel = 32 - - var sem = make(chan bool, parallel) - - var ( - writeSuccesses, readSuccesses int64 // atomic - writeErrnoSeen, readErrnoSeen sync.Map - ) - - for n := attempts; n > 0; n-- { - sem <- true - go func() { - defer func() { <-sem }() - - time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond) - offset := rand.Intn(chunkWords) - chunk := buf[offset*8 : (offset+chunkWords)*8] - if err := WriteFile(path, chunk, 0666); err == nil { - atomic.AddInt64(&writeSuccesses, 1) - } else if robustio.IsEphemeralError(err) { - var ( - errno syscall.Errno - dup bool - ) - if errors.As(err, &errno) { - _, dup = writeErrnoSeen.LoadOrStore(errno, true) - } - if !dup { - t.Logf("ephemeral error: %v", err) - } - } else { - t.Errorf("unexpected error: %v", err) - } - - time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond) - data, err := ReadFile(path) - if err == nil { - atomic.AddInt64(&readSuccesses, 1) - } else if robustio.IsEphemeralError(err) { - var ( - errno syscall.Errno - dup bool - ) - if errors.As(err, &errno) { - _, dup = readErrnoSeen.LoadOrStore(errno, true) - } - if !dup { - t.Logf("ephemeral error: %v", err) - } - return - } else { - t.Errorf("unexpected error: %v", err) - return - } - - if len(data) != 8*chunkWords { - t.Errorf("read %d bytes, but each write is a %d-byte file", len(data), 8*chunkWords) - return - } - - u := binary.LittleEndian.Uint64(data) - for i := 1; i < chunkWords; i++ { - next := binary.LittleEndian.Uint64(data[i*8:]) - if next != u+1 { - t.Errorf("wrote sequential integers, but read integer out of sequence at offset %d", i) - return - } - u = next - } - }() - } - - for n := parallel; n > 0; n-- { - sem <- true - } - - var minWriteSuccesses int64 = attempts - if runtime.GOOS == "windows" { - // Windows produces frequent "Access is denied" errors under heavy rename load. - // As long as those are the only errors and *some* of the writes succeed, we're happy. - minWriteSuccesses = attempts / 4 - } - - if writeSuccesses < minWriteSuccesses { - t.Errorf("%d (of %d) writes succeeded; want ≥ %d", writeSuccesses, attempts, minWriteSuccesses) - } else { - t.Logf("%d (of %d) writes succeeded (ok: ≥ %d)", writeSuccesses, attempts, minWriteSuccesses) - } - - var minReadSuccesses int64 = attempts - - switch runtime.GOOS { - case "windows": - // Windows produces frequent "Access is denied" errors under heavy rename load. - // As long as those are the only errors and *some* of the reads succeed, we're happy. - minReadSuccesses = attempts / 4 - - case "darwin", "ios": - // The filesystem on certain versions of macOS (10.14) and iOS (affected - // versions TBD) occasionally fail with "no such file or directory" errors. - // See https://golang.org/issue/33041 and https://golang.org/issue/42066. - // The flake rate is fairly low, so ensure that at least 75% of attempts - // succeed. - minReadSuccesses = attempts - (attempts / 4) - } - - if readSuccesses < minReadSuccesses { - t.Errorf("%d (of %d) reads succeeded; want ≥ %d", readSuccesses, attempts, minReadSuccesses) - } else { - t.Logf("%d (of %d) reads succeeded (ok: ≥ %d)", readSuccesses, attempts, minReadSuccesses) - } -} diff --git a/libgo/go/cmd/go/internal/renameio/umask_test.go b/libgo/go/cmd/go/internal/renameio/umask_test.go deleted file mode 100644 index 65e4fa5..0000000 --- a/libgo/go/cmd/go/internal/renameio/umask_test.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !plan9,!windows,!js - -package renameio - -import ( - "io/fs" - "os" - "path/filepath" - "syscall" - "testing" -) - -func TestWriteFileModeAppliesUmask(t *testing.T) { - dir, err := os.MkdirTemp("", "renameio") - if err != nil { - t.Fatalf("Failed to create temporary directory: %v", err) - } - defer os.RemoveAll(dir) - - const mode = 0644 - const umask = 0007 - defer syscall.Umask(syscall.Umask(umask)) - - file := filepath.Join(dir, "testWrite") - err = WriteFile(file, []byte("go-build"), mode) - if err != nil { - t.Fatalf("Failed to write file: %v", err) - } - - fi, err := os.Stat(file) - if err != nil { - t.Fatalf("Stat %q (looking for mode %#o): %s", file, mode, err) - } - - if fi.Mode()&fs.ModePerm != 0640 { - t.Errorf("Stat %q: mode %#o want %#o", file, fi.Mode()&fs.ModePerm, 0640) - } -} diff --git a/libgo/go/cmd/go/internal/robustio/robustio_flaky.go b/libgo/go/cmd/go/internal/robustio/robustio_flaky.go index 5bd44bd..d5c2418 100644 --- a/libgo/go/cmd/go/internal/robustio/robustio_flaky.go +++ b/libgo/go/cmd/go/internal/robustio/robustio_flaky.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows || darwin // +build windows darwin package robustio diff --git a/libgo/go/cmd/go/internal/robustio/robustio_other.go b/libgo/go/cmd/go/internal/robustio/robustio_other.go index 6fe7b7e..3a20cac 100644 --- a/libgo/go/cmd/go/internal/robustio/robustio_other.go +++ b/libgo/go/cmd/go/internal/robustio/robustio_other.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows && !darwin // +build !windows,!darwin package robustio diff --git a/libgo/go/cmd/go/internal/run/run.go b/libgo/go/cmd/go/internal/run/run.go index 666b1a0..784f716 100644 --- a/libgo/go/cmd/go/internal/run/run.go +++ b/libgo/go/cmd/go/internal/run/run.go @@ -8,13 +8,16 @@ package run import ( "context" "fmt" + "go/build" "os" "path" + "path/filepath" "strings" "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/load" + "cmd/go/internal/modload" "cmd/go/internal/str" "cmd/go/internal/work" ) @@ -24,10 +27,21 @@ var CmdRun = &base.Command{ Short: "compile and run Go program", Long: ` Run compiles and runs the named main Go package. -Typically the package is specified as a list of .go source files from a single directory, -but it may also be an import path, file system path, or pattern +Typically the package is specified as a list of .go source files from a single +directory, but it may also be an import path, file system path, or pattern matching a single known package, as in 'go run .' or 'go run my/cmd'. +If the package argument has a version suffix (like @latest or @v1.0.0), +"go run" builds the program in module-aware mode, ignoring the go.mod file in +the current directory or any parent directory, if there is one. This is useful +for running programs without affecting the dependencies of the main module. + +If the package argument doesn't have a version suffix, "go run" may run in +module-aware mode or GOPATH mode, depending on the GO111MODULE environment +variable and the presence of a go.mod file. See 'go help modules' for details. +If module-aware mode is enabled, "go run" runs in the context of the main +module. + By default, 'go run' runs the compiled binary directly: 'a.out arguments...'. If the -exec flag is given, 'go run' invokes the binary using xprog: 'xprog a.out arguments...'. @@ -59,14 +73,26 @@ func printStderr(args ...interface{}) (int, error) { } func runRun(ctx context.Context, cmd *base.Command, args []string) { + if shouldUseOutsideModuleMode(args) { + // Set global module flags for 'go run cmd@version'. + // This must be done before modload.Init, but we need to call work.BuildInit + // before loading packages, since it affects package locations, e.g., + // for -race and -msan. + modload.ForceUseModules = true + modload.RootMode = modload.NoRoot + modload.AllowMissingModuleImports() + modload.Init() + } work.BuildInit() var b work.Builder b.Init() b.Print = printStderr + i := 0 for i < len(args) && strings.HasSuffix(args[i], ".go") { i++ } + pkgOpts := load.PackageOpts{MainOnly: true} var p *load.Package if i > 0 { files := args[:i] @@ -77,18 +103,29 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) { base.Fatalf("go run: cannot run *_test.go files (%s)", file) } } - p = load.GoFilesPackage(ctx, files) + p = load.GoFilesPackage(ctx, pkgOpts, files) } else if len(args) > 0 && !strings.HasPrefix(args[0], "-") { - pkgs := load.PackagesAndErrors(ctx, args[:1]) + arg := args[0] + var pkgs []*load.Package + if strings.Contains(arg, "@") && !build.IsLocalImport(arg) && !filepath.IsAbs(arg) { + var err error + pkgs, err = load.PackagesAndErrorsOutsideModule(ctx, pkgOpts, args[:1]) + if err != nil { + base.Fatalf("go run: %v", err) + } + } else { + pkgs = load.PackagesAndErrors(ctx, pkgOpts, args[:1]) + } + if len(pkgs) == 0 { - base.Fatalf("go run: no packages loaded from %s", args[0]) + base.Fatalf("go run: no packages loaded from %s", arg) } if len(pkgs) > 1 { var names []string for _, p := range pkgs { names = append(names, p.ImportPath) } - base.Fatalf("go run: pattern %s matches multiple packages:\n\t%s", args[0], strings.Join(names, "\n\t")) + base.Fatalf("go run: pattern %s matches multiple packages:\n\t%s", arg, strings.Join(names, "\n\t")) } p = pkgs[0] i++ @@ -98,9 +135,6 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) { cmdArgs := args[i:] load.CheckPackageErrors([]*load.Package{p}) - if p.Name != "main" { - base.Fatalf("go run: cannot run non-main package") - } p.Internal.OmitDebug = true p.Target = "" // must build - not up to date if p.Internal.CmdlineFiles { @@ -123,11 +157,34 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) { } else { p.Internal.ExeName = path.Base(p.ImportPath) } + a1 := b.LinkAction(work.ModeBuild, work.ModeBuild, p) a := &work.Action{Mode: "go run", Func: buildRunProgram, Args: cmdArgs, Deps: []*work.Action{a1}} b.Do(ctx, a) } +// shouldUseOutsideModuleMode returns whether 'go run' will load packages in +// module-aware mode, ignoring the go.mod file in the current directory. It +// returns true if the first argument contains "@", does not begin with "-" +// (resembling a flag) or end with ".go" (a file). The argument must not be a +// local or absolute file path. +// +// These rules are slightly different than other commands. Whether or not +// 'go run' uses this mode, it interprets arguments ending with ".go" as files +// and uses arguments up to the last ".go" argument to comprise the package. +// If there are no ".go" arguments, only the first argument is interpreted +// as a package path, since there can be only one package. +func shouldUseOutsideModuleMode(args []string) bool { + // NOTE: "@" not allowed in import paths, but it is allowed in non-canonical + // versions. + return len(args) > 0 && + !strings.HasSuffix(args[0], ".go") && + !strings.HasPrefix(args[0], "-") && + strings.Contains(args[0], "@") && + !build.IsLocalImport(args[0]) && + !filepath.IsAbs(args[0]) +} + // buildRunProgram is the action for running a binary that has already // been compiled. We ignore exit status. func buildRunProgram(b *work.Builder, ctx context.Context, a *work.Action) error { diff --git a/libgo/go/cmd/go/internal/search/search.go b/libgo/go/cmd/go/internal/search/search.go index 18738cf..a0c806a 100644 --- a/libgo/go/cmd/go/internal/search/search.go +++ b/libgo/go/cmd/go/internal/search/search.go @@ -155,7 +155,7 @@ func (m *Match) MatchPackages() { } if !fi.IsDir() { - if fi.Mode()&fs.ModeSymlink != 0 && want { + if fi.Mode()&fs.ModeSymlink != 0 && want && strings.Contains(m.pattern, "...") { if target, err := fsys.Stat(path); err == nil && target.IsDir() { fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path) } @@ -445,7 +445,7 @@ func ImportPathsQuiet(patterns []string) []*Match { for i, dir := range m.Dirs { absDir := dir if !filepath.IsAbs(dir) { - absDir = filepath.Join(base.Cwd, dir) + absDir = filepath.Join(base.Cwd(), dir) } if bp, _ := cfg.BuildContext.ImportDir(absDir, build.FindOnly); bp.ImportPath != "" && bp.ImportPath != "." { m.Pkgs[i] = bp.ImportPath @@ -571,7 +571,6 @@ func IsRelativePath(pattern string) bool { // If so, InDir returns an equivalent path relative to dir. // If not, InDir returns an empty string. // InDir makes some effort to succeed even in the presence of symbolic links. -// TODO(rsc): Replace internal/test.inDir with a call to this function for Go 1.12. func InDir(path, dir string) string { if rel := inDirLex(path, dir); rel != "" { return rel diff --git a/libgo/go/cmd/go/internal/test/cover.go b/libgo/go/cmd/go/internal/test/cover.go index 9841791..657d22a 100644 --- a/libgo/go/cmd/go/internal/test/cover.go +++ b/libgo/go/cmd/go/internal/test/cover.go @@ -26,8 +26,8 @@ func initCoverProfile() { if testCoverProfile == "" || testC { return } - if !filepath.IsAbs(testCoverProfile) && testOutputDir != "" { - testCoverProfile = filepath.Join(testOutputDir, testCoverProfile) + if !filepath.IsAbs(testCoverProfile) { + testCoverProfile = filepath.Join(testOutputDir.getAbs(), testCoverProfile) } // No mutex - caller's responsibility to call with no racing goroutines. diff --git a/libgo/go/cmd/go/internal/test/flagdefs.go b/libgo/go/cmd/go/internal/test/flagdefs.go index 8a0a076..37ac81c 100644 --- a/libgo/go/cmd/go/internal/test/flagdefs.go +++ b/libgo/go/cmd/go/internal/test/flagdefs.go @@ -28,6 +28,7 @@ var passFlagToTest = map[string]bool{ "parallel": true, "run": true, "short": true, + "shuffle": true, "timeout": true, "trace": true, "v": true, diff --git a/libgo/go/cmd/go/internal/test/genflags.go b/libgo/go/cmd/go/internal/test/genflags.go index 30334b0..9277de7 100644 --- a/libgo/go/cmd/go/internal/test/genflags.go +++ b/libgo/go/cmd/go/internal/test/genflags.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package main diff --git a/libgo/go/cmd/go/internal/test/test.go b/libgo/go/cmd/go/internal/test/test.go index 7fc9e8f..59ea1ef 100644 --- a/libgo/go/cmd/go/internal/test/test.go +++ b/libgo/go/cmd/go/internal/test/test.go @@ -29,6 +29,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/load" "cmd/go/internal/lockedfile" + "cmd/go/internal/search" "cmd/go/internal/str" "cmd/go/internal/trace" "cmd/go/internal/work" @@ -117,8 +118,8 @@ elapsed time in the summary line. The rule for a match in the cache is that the run involves the same test binary and the flags on the command line come entirely from a -restricted set of 'cacheable' test flags, defined as -cpu, -list, --parallel, -run, -short, and -v. If a run of go test has any test +restricted set of 'cacheable' test flags, defined as -benchtime, -cpu, +-list, -parallel, -run, -short, and -v. If a run of go test has any test or non-test flags outside this set, the result is not cached. To disable test caching, use any test flag or argument other than the cacheable flags. The idiomatic way to disable test caching explicitly @@ -271,6 +272,13 @@ control the execution of any test: the Go tree can run a sanity check but not spend time running exhaustive tests. + -shuffle off,on,N + Randomize the execution order of tests and benchmarks. + It is off by default. If -shuffle is set to on, then it will seed + the randomizer using the system clock. If -shuffle is set to an + integer N, then N will be used as the seed value. In both cases, + the seed will be reported for reproducibility. + -timeout d If a test binary runs longer than duration d, panic. If d is 0, the timeout is disabled. @@ -478,7 +486,8 @@ var ( testJSON bool // -json flag testList string // -list flag testO string // -o flag - testOutputDir = base.Cwd // -outputdir flag + testOutputDir outputdirFlag // -outputdir flag + testShuffle shuffleFlag // -shuffle flag testTimeout time.Duration // -timeout flag testV bool // -v flag testVet = vetFlag{flags: defaultVetFlags} // -vet flag @@ -568,8 +577,6 @@ var defaultVetFlags = []string{ } func runTest(ctx context.Context, cmd *base.Command, args []string) { - load.ModResolveTests = true - pkgArgs, testArgs = testFlags(args) if cfg.DebugTrace != "" { @@ -595,7 +602,8 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { work.VetFlags = testVet.flags work.VetExplicit = testVet.explicit - pkgs = load.PackagesAndErrors(ctx, pkgArgs) + pkgOpts := load.PackageOpts{ModResolveTests: true} + pkgs = load.PackagesAndErrors(ctx, pkgOpts, pkgArgs) load.CheckPackageErrors(pkgs) if len(pkgs) == 0 { base.Fatalf("no packages to test") @@ -679,7 +687,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { sort.Strings(all) a := &work.Action{Mode: "go test -i"} - pkgs := load.PackagesAndErrors(ctx, all) + pkgs := load.PackagesAndErrors(ctx, pkgOpts, all) load.CheckPackageErrors(pkgs) for _, p := range pkgs { if cfg.BuildToolchainName == "gccgo" && p.Standard { @@ -702,11 +710,11 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { match := make([]func(*load.Package) bool, len(testCoverPaths)) matched := make([]bool, len(testCoverPaths)) for i := range testCoverPaths { - match[i] = load.MatchPackage(testCoverPaths[i], base.Cwd) + match[i] = load.MatchPackage(testCoverPaths[i], base.Cwd()) } // Select for coverage all dependencies matching the testCoverPaths patterns. - for _, p := range load.TestPackageList(ctx, pkgs) { + for _, p := range load.TestPackageList(ctx, pkgOpts, pkgs) { haveMatch := false for i := range testCoverPaths { if match[i](p) { @@ -715,6 +723,12 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { } } + // A package which only has test files can't be imported + // as a dependency, nor can it be instrumented for coverage. + if len(p.GoFiles)+len(p.CgoFiles) == 0 { + continue + } + // Silently ignore attempts to run coverage on // sync/atomic when using atomic coverage mode. // Atomic coverage mode uses sync/atomic, so @@ -768,7 +782,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { ensureImport(p, "sync/atomic") } - buildTest, runTest, printTest, err := builderTest(&b, ctx, p) + buildTest, runTest, printTest, err := builderTest(&b, ctx, pkgOpts, p) if err != nil { str := err.Error() str = strings.TrimPrefix(str, "\n") @@ -835,7 +849,7 @@ var windowsBadWords = []string{ "update", } -func builderTest(b *work.Builder, ctx context.Context, p *load.Package) (buildAction, runAction, printAction *work.Action, err error) { +func builderTest(b *work.Builder, ctx context.Context, pkgOpts load.PackageOpts, p *load.Package) (buildAction, runAction, printAction *work.Action, err error) { if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 { build := b.CompileAction(work.ModeBuild, work.ModeBuild, p) run := &work.Action{Mode: "test run", Package: p, Deps: []*work.Action{build}} @@ -858,7 +872,7 @@ func builderTest(b *work.Builder, ctx context.Context, p *load.Package) (buildAc DeclVars: declareCoverVars, } } - pmain, ptest, pxtest, err := load.TestPackagesFor(ctx, p, cover) + pmain, ptest, pxtest, err := load.TestPackagesFor(ctx, pkgOpts, p, cover) if err != nil { return nil, nil, nil, err } @@ -931,11 +945,11 @@ func builderTest(b *work.Builder, ctx context.Context, p *load.Package) (buildAc var installAction, cleanAction *work.Action if testC || testNeedBinary() { // -c or profiling flag: create action to copy binary to ./test.out. - target := filepath.Join(base.Cwd, testBinary+cfg.ExeSuffix) + target := filepath.Join(base.Cwd(), testBinary+cfg.ExeSuffix) if testO != "" { target = testO if !filepath.IsAbs(target) { - target = filepath.Join(base.Cwd, target) + target = filepath.Join(base.Cwd(), target) } } if target == os.DevNull { @@ -1326,7 +1340,8 @@ func (c *runCache) tryCacheWithID(b *work.Builder, a *work.Action, id string) bo return false } switch arg[:i] { - case "-test.cpu", + case "-test.benchtime", + "-test.cpu", "-test.list", "-test.parallel", "-test.run", @@ -1499,7 +1514,7 @@ func computeTestInputsID(a *work.Action, testlog []byte) (cache.ActionID, error) if !filepath.IsAbs(name) { name = filepath.Join(pwd, name) } - if a.Package.Root == "" || !inDir(name, a.Package.Root) { + if a.Package.Root == "" || search.InDir(name, a.Package.Root) == "" { // Do not recheck files outside the module, GOPATH, or GOROOT root. break } @@ -1508,7 +1523,7 @@ func computeTestInputsID(a *work.Action, testlog []byte) (cache.ActionID, error) if !filepath.IsAbs(name) { name = filepath.Join(pwd, name) } - if a.Package.Root == "" || !inDir(name, a.Package.Root) { + if a.Package.Root == "" || search.InDir(name, a.Package.Root) == "" { // Do not recheck files outside the module, GOPATH, or GOROOT root. break } @@ -1526,18 +1541,6 @@ func computeTestInputsID(a *work.Action, testlog []byte) (cache.ActionID, error) return sum, nil } -func inDir(path, dir string) bool { - if str.HasFilePathPrefix(path, dir) { - return true - } - xpath, err1 := filepath.EvalSymlinks(path) - xdir, err2 := filepath.EvalSymlinks(dir) - if err1 == nil && err2 == nil && str.HasFilePathPrefix(xpath, xdir) { - return true - } - return false -} - func hashGetenv(name string) cache.ActionID { h := cache.NewHash("getenv") v, ok := os.LookupEnv(name) diff --git a/libgo/go/cmd/go/internal/test/testflag.go b/libgo/go/cmd/go/internal/test/testflag.go index 10e6604..08f1efa 100644 --- a/libgo/go/cmd/go/internal/test/testflag.go +++ b/libgo/go/cmd/go/internal/test/testflag.go @@ -10,6 +10,7 @@ import ( "fmt" "os" "path/filepath" + "strconv" "strings" "time" @@ -61,15 +62,16 @@ func init() { cf.String("memprofilerate", "", "") cf.StringVar(&testMutexProfile, "mutexprofile", "", "") cf.String("mutexprofilefraction", "", "") - cf.Var(outputdirFlag{&testOutputDir}, "outputdir", "") + cf.Var(&testOutputDir, "outputdir", "") cf.Int("parallel", 0, "") cf.String("run", "", "") cf.Bool("short", false, "") cf.DurationVar(&testTimeout, "timeout", 10*time.Minute, "") cf.StringVar(&testTrace, "trace", "", "") cf.BoolVar(&testV, "v", false, "") + cf.Var(&testShuffle, "shuffle", "") - for name, _ := range passFlagToTest { + for name := range passFlagToTest { cf.Var(cf.Lookup(name).Value, "test."+name, "") } } @@ -126,19 +128,26 @@ func (f stringFlag) Set(value string) error { // outputdirFlag implements the -outputdir flag. // It interprets an empty value as the working directory of the 'go' command. type outputdirFlag struct { - resolved *string + abs string } -func (f outputdirFlag) String() string { return *f.resolved } -func (f outputdirFlag) Set(value string) (err error) { +func (f *outputdirFlag) String() string { + return f.abs +} +func (f *outputdirFlag) Set(value string) (err error) { if value == "" { - // The empty string implies the working directory of the 'go' command. - *f.resolved = base.Cwd + f.abs = "" } else { - *f.resolved, err = filepath.Abs(value) + f.abs, err = filepath.Abs(value) } return err } +func (f *outputdirFlag) getAbs() string { + if f.abs == "" { + return base.Cwd() + } + return f.abs +} // vetFlag implements the special parsing logic for the -vet flag: // a comma-separated list, with a distinguished value "off" and @@ -194,6 +203,41 @@ func (f *vetFlag) Set(value string) error { return nil } +type shuffleFlag struct { + on bool + seed *int64 +} + +func (f *shuffleFlag) String() string { + if !f.on { + return "off" + } + if f.seed == nil { + return "on" + } + return fmt.Sprintf("%d", *f.seed) +} + +func (f *shuffleFlag) Set(value string) error { + if value == "off" { + *f = shuffleFlag{on: false} + return nil + } + + if value == "on" { + *f = shuffleFlag{on: true} + return nil + } + + seed, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return fmt.Errorf(`-shuffle argument must be "on", "off", or an int64: %v`, err) + } + + *f = shuffleFlag{on: true, seed: &seed} + return nil +} + // testFlags processes the command line, grabbing -x and -c, rewriting known flags // to have "test" before them, and reading the command line for the test binary. // Unfortunately for us, we need to do our own flag processing because go test @@ -367,7 +411,7 @@ func testFlags(args []string) (packageNames, passToTest []string) { // command. Set it explicitly if it is needed due to some other flag that // requests output. if testProfile() != "" && !outputDirSet { - injectedFlags = append(injectedFlags, "-test.outputdir="+testOutputDir) + injectedFlags = append(injectedFlags, "-test.outputdir="+testOutputDir.getAbs()) } // If the user is explicitly passing -help or -h, show output diff --git a/libgo/go/cmd/go/internal/vcs/vcs.go b/libgo/go/cmd/go/internal/vcs/vcs.go index 9feffe0..91485f6 100644 --- a/libgo/go/cmd/go/internal/vcs/vcs.go +++ b/libgo/go/cmd/go/internal/vcs/vcs.go @@ -1176,7 +1176,7 @@ func expand(match map[string]string, s string) string { // and import paths referring to a fully-qualified importPath // containing a VCS type (foo.com/repo.git/dir) var vcsPaths = []*vcsPath{ - // Github + // GitHub { pathPrefix: "github.com", regexp: lazyregexp.New(`^(?P<root>github\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`), diff --git a/libgo/go/cmd/go/internal/vet/vet.go b/libgo/go/cmd/go/internal/vet/vet.go index 4257c90c..1d419dd 100644 --- a/libgo/go/cmd/go/internal/vet/vet.go +++ b/libgo/go/cmd/go/internal/vet/vet.go @@ -53,8 +53,6 @@ See also: go fmt, go fix. } func runVet(ctx context.Context, cmd *base.Command, args []string) { - load.ModResolveTests = true - vetFlags, pkgArgs := vetFlags(args) if cfg.DebugTrace != "" { @@ -87,7 +85,8 @@ func runVet(ctx context.Context, cmd *base.Command, args []string) { } } - pkgs := load.PackagesAndErrors(ctx, pkgArgs) + pkgOpts := load.PackageOpts{ModResolveTests: true} + pkgs := load.PackagesAndErrors(ctx, pkgOpts, pkgArgs) load.CheckPackageErrors(pkgs) if len(pkgs) == 0 { base.Fatalf("no packages to vet") @@ -98,7 +97,7 @@ func runVet(ctx context.Context, cmd *base.Command, args []string) { root := &work.Action{Mode: "go vet"} for _, p := range pkgs { - _, ptest, pxtest, err := load.TestPackagesFor(ctx, p, nil) + _, ptest, pxtest, err := load.TestPackagesFor(ctx, pkgOpts, p, nil) if err != nil { base.Errorf("%v", err) continue diff --git a/libgo/go/cmd/go/internal/web/bootstrap.go b/libgo/go/cmd/go/internal/web/bootstrap.go index 7817021..08686cd 100644 --- a/libgo/go/cmd/go/internal/web/bootstrap.go +++ b/libgo/go/cmd/go/internal/web/bootstrap.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cmd_go_bootstrap // +build cmd_go_bootstrap // This code is compiled only into the bootstrap 'go' binary. diff --git a/libgo/go/cmd/go/internal/web/http.go b/libgo/go/cmd/go/internal/web/http.go index 72fa2b2..f177278 100644 --- a/libgo/go/cmd/go/internal/web/http.go +++ b/libgo/go/cmd/go/internal/web/http.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !cmd_go_bootstrap // +build !cmd_go_bootstrap // This code is compiled into the real 'go' binary, but it is not @@ -27,7 +28,7 @@ import ( "cmd/internal/browser" ) -// impatientInsecureHTTPClient is used in -insecure mode, +// impatientInsecureHTTPClient is used with GOINSECURE, // when we're connecting to https servers that might not be there // or might be using self-signed certificates. var impatientInsecureHTTPClient = &http.Client{ diff --git a/libgo/go/cmd/go/internal/web/url_other.go b/libgo/go/cmd/go/internal/web/url_other.go index 2641ee6..453af40 100644 --- a/libgo/go/cmd/go/internal/web/url_other.go +++ b/libgo/go/cmd/go/internal/web/url_other.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows // +build !windows package web diff --git a/libgo/go/cmd/go/internal/web/url_other_test.go b/libgo/go/cmd/go/internal/web/url_other_test.go index aa56633..4d6ed2e 100644 --- a/libgo/go/cmd/go/internal/web/url_other_test.go +++ b/libgo/go/cmd/go/internal/web/url_other_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows // +build !windows package web diff --git a/libgo/go/cmd/go/internal/work/action.go b/libgo/go/cmd/go/internal/work/action.go index 5320121..2e00c0c 100644 --- a/libgo/go/cmd/go/internal/work/action.go +++ b/libgo/go/cmd/go/internal/work/action.go @@ -349,7 +349,7 @@ func readpkglist(shlibpath string) (pkgs []*load.Package) { if strings.HasPrefix(t, "pkgpath ") { t = strings.TrimPrefix(t, "pkgpath ") t = strings.TrimSuffix(t, ";") - pkgs = append(pkgs, load.LoadImportWithFlags(t, base.Cwd, nil, &stk, nil, 0)) + pkgs = append(pkgs, load.LoadImportWithFlags(t, base.Cwd(), nil, &stk, nil, 0)) } } } else { @@ -360,7 +360,7 @@ func readpkglist(shlibpath string) (pkgs []*load.Package) { scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes)) for scanner.Scan() { t := scanner.Text() - pkgs = append(pkgs, load.LoadImportWithFlags(t, base.Cwd, nil, &stk, nil, 0)) + pkgs = append(pkgs, load.LoadImportWithFlags(t, base.Cwd(), nil, &stk, nil, 0)) } } return @@ -781,7 +781,7 @@ func (b *Builder) linkSharedAction(mode, depMode BuildMode, shlib string, a1 *Ac } } var stk load.ImportStack - p := load.LoadImportWithFlags(pkg, base.Cwd, nil, &stk, nil, 0) + p := load.LoadImportWithFlags(pkg, base.Cwd(), nil, &stk, nil, 0) if p.Error != nil { base.Fatalf("load %s: %v", pkg, p.Error) } diff --git a/libgo/go/cmd/go/internal/work/build.go b/libgo/go/cmd/go/internal/work/build.go index f024b07..0ed2389 100644 --- a/libgo/go/cmd/go/internal/work/build.go +++ b/libgo/go/cmd/go/internal/work/build.go @@ -10,9 +10,7 @@ import ( "fmt" "go/build" exec "internal/execabs" - "internal/goroot" "os" - "path" "path/filepath" "runtime" "strings" @@ -21,13 +19,9 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/fsys" "cmd/go/internal/load" - "cmd/go/internal/modfetch" "cmd/go/internal/modload" "cmd/go/internal/search" "cmd/go/internal/trace" - - "golang.org/x/mod/modfile" - "golang.org/x/mod/module" ) var CmdBuild = &base.Command{ @@ -71,7 +65,7 @@ and test commands: -p n the number of programs, such as build commands or test binaries, that can be run in parallel. - The default is the number of CPUs available. + The default is GOMAXPROCS, normally the number of CPUs available. -race enable data race detection. Supported only on linux/amd64, freebsd/amd64, darwin/amd64, windows/amd64, @@ -134,8 +128,8 @@ and test commands: a build will run as if the disk file path exists with the contents given by the backing file paths, or as if the disk file path does not exist if its backing file path is empty. Support for the -overlay flag - has some limitations:importantly, cgo files included from outside the - include path must be in the same directory as the Go package they are + has some limitations: importantly, cgo files included from outside the + include path must be in the same directory as the Go package they are included from, and overlays will not appear when binaries and tests are run through go run and go test respectively. -pkgdir dir @@ -158,6 +152,8 @@ and test commands: a program to use to invoke toolchain programs like vet and asm. For example, instead of running asm, the go command will run 'cmd args /path/to/asm <arguments for asm>'. + The TOOLEXEC_IMPORTPATH environment variable will be set, + matching 'go list -f {{.ImportPath}}' for the package being built. The -asmflags, -gccgoflags, -gcflags, and -ldflags flags accept a space-separated list of arguments to pass to an underlying tool @@ -372,7 +368,7 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) { var b Builder b.Init() - pkgs := load.PackagesAndErrors(ctx, args) + pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, args) load.CheckPackageErrors(pkgs) explicitO := len(cfg.BuildO) > 0 @@ -592,7 +588,7 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) { } BuildInit() - pkgs := load.PackagesAndErrors(ctx, args) + pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, args) if cfg.ModulesEnabled && !modload.HasModRoot() { haveErrors := false allMissingErrors := true @@ -762,145 +758,27 @@ func installOutsideModule(ctx context.Context, args []string) { modload.RootMode = modload.NoRoot modload.AllowMissingModuleImports() modload.Init() - - // Check that the arguments satisfy syntactic constraints. - var version string - for _, arg := range args { - if i := strings.Index(arg, "@"); i >= 0 { - version = arg[i+1:] - if version == "" { - base.Fatalf("go install %s: version must not be empty", arg) - } - break - } - } - patterns := make([]string, len(args)) - for i, arg := range args { - if !strings.HasSuffix(arg, "@"+version) { - base.Errorf("go install %s: all arguments must have the same version (@%s)", arg, version) - continue - } - p := arg[:len(arg)-len(version)-1] - switch { - case build.IsLocalImport(p): - base.Errorf("go install %s: argument must be a package path, not a relative path", arg) - case filepath.IsAbs(p): - base.Errorf("go install %s: argument must be a package path, not an absolute path", arg) - case search.IsMetaPackage(p): - base.Errorf("go install %s: argument must be a package path, not a meta-package", arg) - case path.Clean(p) != p: - base.Errorf("go install %s: argument must be a clean package path", arg) - case !strings.Contains(p, "...") && search.IsStandardImportPath(p) && goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, p): - base.Errorf("go install %s: argument must not be a package in the standard library", arg) - default: - patterns[i] = p - } - } - base.ExitIfErrors() BuildInit() - // Query the module providing the first argument, load its go.mod file, and - // check that it doesn't contain directives that would cause it to be - // interpreted differently if it were the main module. - // - // If multiple modules match the first argument, accept the longest match - // (first result). It's possible this module won't provide packages named by - // later arguments, and other modules would. Let's not try to be too - // magical though. - allowed := modload.CheckAllowed - if modload.IsRevisionQuery(version) { - // Don't check for retractions if a specific revision is requested. - allowed = nil - } - noneSelected := func(path string) (version string) { return "none" } - qrs, err := modload.QueryPackages(ctx, patterns[0], version, noneSelected, allowed) - if err != nil { - base.Fatalf("go install %s: %v", args[0], err) - } - installMod := qrs[0].Mod - data, err := modfetch.GoMod(installMod.Path, installMod.Version) - if err != nil { - base.Fatalf("go install %s: %v", args[0], err) - } - f, err := modfile.Parse("go.mod", data, nil) - if err != nil { - base.Fatalf("go install %s: %s: %v", args[0], installMod, err) - } - directiveFmt := "go install %s: %s\n" + - "\tThe go.mod file for the module providing named packages contains one or\n" + - "\tmore %s directives. It must not contain directives that would cause\n" + - "\tit to be interpreted differently than if it were the main module." - if len(f.Replace) > 0 { - base.Fatalf(directiveFmt, args[0], installMod, "replace") - } - if len(f.Exclude) > 0 { - base.Fatalf(directiveFmt, args[0], installMod, "exclude") - } - - // Since we are in NoRoot mode, the build list initially contains only - // the dummy command-line-arguments module. Add a requirement on the - // module that provides the packages named on the command line. - if err := modload.EditBuildList(ctx, nil, []module.Version{installMod}); err != nil { - base.Fatalf("go install %s: %v", args[0], err) - } - - // Load packages for all arguments. Ignore non-main packages. + // Load packages. Ignore non-main packages. // Print a warning if an argument contains "..." and matches no main packages. // PackagesAndErrors already prints warnings for patterns that don't match any // packages, so be careful not to double print. - matchers := make([]func(string) bool, len(patterns)) - for i, p := range patterns { - if strings.Contains(p, "...") { - matchers[i] = search.MatchPattern(p) - } - } - // TODO(golang.org/issue/40276): don't report errors loading non-main packages // matched by a pattern. - pkgs := load.PackagesAndErrors(ctx, patterns) - load.CheckPackageErrors(pkgs) - mainPkgs := make([]*load.Package, 0, len(pkgs)) - mainCount := make([]int, len(patterns)) - nonMainCount := make([]int, len(patterns)) - for _, pkg := range pkgs { - if pkg.Name == "main" { - mainPkgs = append(mainPkgs, pkg) - for i := range patterns { - if matchers[i] != nil && matchers[i](pkg.ImportPath) { - mainCount[i]++ - } - } - } else { - for i := range patterns { - if matchers[i] == nil && patterns[i] == pkg.ImportPath { - base.Errorf("go install: package %s is not a main package", pkg.ImportPath) - } else if matchers[i] != nil && matchers[i](pkg.ImportPath) { - nonMainCount[i]++ - } - } - } - } - base.ExitIfErrors() - for i, p := range patterns { - if matchers[i] != nil && mainCount[i] == 0 && nonMainCount[i] > 0 { - fmt.Fprintf(os.Stderr, "go: warning: %q matched no main packages\n", p) - } + pkgOpts := load.PackageOpts{MainOnly: true} + pkgs, err := load.PackagesAndErrorsOutsideModule(ctx, pkgOpts, args) + if err != nil { + base.Fatalf("go install: %v", err) } - - // Check that named packages are all provided by the same module. - for _, pkg := range mainPkgs { - if pkg.Module == nil { - // Packages in std, cmd, and their vendored dependencies - // don't have this field set. - base.Errorf("go install: package %s not provided by module %s", pkg.ImportPath, installMod) - } else if pkg.Module.Path != installMod.Path || pkg.Module.Version != installMod.Version { - base.Errorf("go install: package %s provided by module %s@%s\n\tAll packages must be provided by the same module (%s).", pkg.ImportPath, pkg.Module.Path, pkg.Module.Version, installMod) - } + load.CheckPackageErrors(pkgs) + patterns := make([]string, len(args)) + for i, arg := range args { + patterns[i] = arg[:strings.Index(arg, "@")] } - base.ExitIfErrors() // Build and install the packages. - InstallPackages(ctx, patterns, mainPkgs) + InstallPackages(ctx, patterns, pkgs) } // ExecCmd is the command to use to run user binaries. diff --git a/libgo/go/cmd/go/internal/work/build_test.go b/libgo/go/cmd/go/internal/work/build_test.go index eaf2639..600fc30 100644 --- a/libgo/go/cmd/go/internal/work/build_test.go +++ b/libgo/go/cmd/go/internal/work/build_test.go @@ -173,10 +173,11 @@ func TestSharedLibName(t *testing.T) { if err != nil { t.Fatal(err) } + cwd := base.Cwd() oldGopath := cfg.BuildContext.GOPATH defer func() { cfg.BuildContext.GOPATH = oldGopath - os.Chdir(base.Cwd) + os.Chdir(cwd) err := os.RemoveAll(tmpGopath) if err != nil { t.Error(err) diff --git a/libgo/go/cmd/go/internal/work/buildid.go b/libgo/go/cmd/go/internal/work/buildid.go index c555d4a..4e9189a 100644 --- a/libgo/go/cmd/go/internal/work/buildid.go +++ b/libgo/go/cmd/go/internal/work/buildid.go @@ -204,7 +204,7 @@ func (b *Builder) toolID(name string) string { // In order to get reproducible builds for released compilers, we // detect a released compiler by the absence of "experimental" in the // --version output, and in that case we just use the version string. -func (b *Builder) gccgoToolID(name, language string) (string, error) { +func (b *Builder) gccToolID(name, language string) (string, error) { key := name + "." + language b.id.Lock() id := b.toolIDCache[key] diff --git a/libgo/go/cmd/go/internal/work/exec.go b/libgo/go/cmd/go/internal/work/exec.go index f354f30..b028104 100644 --- a/libgo/go/cmd/go/internal/work/exec.go +++ b/libgo/go/cmd/go/internal/work/exec.go @@ -8,11 +8,11 @@ package work import ( "bytes" - "cmd/go/internal/fsys" "context" "encoding/json" "errors" "fmt" + "internal/buildcfg" exec "internal/execabs" "internal/lazyregexp" "io" @@ -31,6 +31,7 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cache" "cmd/go/internal/cfg" + "cmd/go/internal/fsys" "cmd/go/internal/load" "cmd/go/internal/modload" "cmd/go/internal/str" @@ -245,17 +246,37 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID { if p.Internal.ForceLibrary { fmt.Fprintf(h, "forcelibrary\n") } - if len(p.CgoFiles)+len(p.SwigFiles) > 0 { + if len(p.CgoFiles)+len(p.SwigFiles)+len(p.SwigCXXFiles) > 0 { fmt.Fprintf(h, "cgo %q\n", b.toolID("cgo")) cppflags, cflags, cxxflags, fflags, ldflags, _ := b.CFlags(p) - fmt.Fprintf(h, "CC=%q %q %q %q\n", b.ccExe(), cppflags, cflags, ldflags) - if len(p.CXXFiles)+len(p.SwigFiles) > 0 { - fmt.Fprintf(h, "CXX=%q %q\n", b.cxxExe(), cxxflags) + + ccExe := b.ccExe() + fmt.Fprintf(h, "CC=%q %q %q %q\n", ccExe, cppflags, cflags, ldflags) + // Include the C compiler tool ID so that if the C + // compiler changes we rebuild the package. + // But don't do that for standard library packages like net, + // so that the prebuilt .a files from a Go binary install + // don't need to be rebuilt with the local compiler. + if !p.Standard { + if ccID, err := b.gccToolID(ccExe[0], "c"); err == nil { + fmt.Fprintf(h, "CC ID=%q\n", ccID) + } + } + if len(p.CXXFiles)+len(p.SwigCXXFiles) > 0 { + cxxExe := b.cxxExe() + fmt.Fprintf(h, "CXX=%q %q\n", cxxExe, cxxflags) + if cxxID, err := b.gccToolID(cxxExe[0], "c++"); err == nil { + fmt.Fprintf(h, "CXX ID=%q\n", cxxID) + } } if len(p.FFiles) > 0 { - fmt.Fprintf(h, "FC=%q %q\n", b.fcExe(), fflags) + fcExe := b.fcExe() + fmt.Fprintf(h, "FC=%q %q\n", fcExe, fflags) + if fcID, err := b.gccToolID(fcExe[0], "f95"); err == nil { + fmt.Fprintf(h, "FC ID=%q\n", fcID) + } } - // TODO(rsc): Should we include the SWIG version or Fortran/GCC/G++/Objective-C compiler versions? + // TODO(rsc): Should we include the SWIG version? } if p.Internal.CoverMode != "" { fmt.Fprintf(h, "cover %q %q\n", p.Internal.CoverMode, b.toolID("cover")) @@ -276,6 +297,10 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID { key, val := cfg.GetArchEnv() fmt.Fprintf(h, "%s=%s\n", key, val) + if goexperiment := buildcfg.GOEXPERIMENT(); goexperiment != "" { + fmt.Fprintf(h, "GOEXPERIMENT=%q\n", goexperiment) + } + // TODO(rsc): Convince compiler team not to add more magic environment variables, // or perhaps restrict the environment variables passed to subprocesses. // Because these are clumsy, undocumented special-case hacks @@ -284,7 +309,7 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID { magic := []string{ "GOCLOBBERDEADHASH", "GOSSAFUNC", - "GO_SSA_PHI_LOC_CUTOFF", + "GOSSADIR", "GOSSAHASH", } for _, env := range magic { @@ -311,7 +336,7 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID { } case "gccgo": - id, err := b.gccgoToolID(BuildToolchain.compiler(), "go") + id, err := b.gccToolID(BuildToolchain.compiler(), "go") if err != nil { base.Fatalf("%v", err) } @@ -319,7 +344,7 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID { fmt.Fprintf(h, "pkgpath %s\n", gccgoPkgpath(p)) fmt.Fprintf(h, "ar %q\n", BuildToolchain.(gccgoToolchain).ar()) if len(p.SFiles) > 0 { - id, _ = b.gccgoToolID(BuildToolchain.compiler(), "assembler-with-cpp") + id, _ = b.gccToolID(BuildToolchain.compiler(), "assembler-with-cpp") // Ignore error; different assembler versions // are unlikely to make any difference anyhow. fmt.Fprintf(h, "asm %q\n", id) @@ -649,6 +674,10 @@ OverlayLoop: } outGo, outObj, err := b.cgo(a, base.Tool("cgo"), objdir, pcCFLAGS, pcLDFLAGS, mkAbsFiles(a.Package.Dir, cgofiles), gccfiles, cxxfiles, a.Package.MFiles, a.Package.FFiles) + + // The files in cxxfiles have now been handled by b.cgo. + cxxfiles = nil + if err != nil { return err } @@ -1248,6 +1277,10 @@ func (b *Builder) printLinkerConfig(h io.Writer, p *load.Package) { key, val := cfg.GetArchEnv() fmt.Fprintf(h, "%s=%s\n", key, val) + if goexperiment := buildcfg.GOEXPERIMENT(); goexperiment != "" { + fmt.Fprintf(h, "GOEXPERIMENT=%q\n", goexperiment) + } + // The linker writes source file paths that say GOROOT_FINAL, but // only if -trimpath is not specified (see ld() in gc.go). gorootFinal := cfg.GOROOT_FINAL @@ -1263,7 +1296,7 @@ func (b *Builder) printLinkerConfig(h io.Writer, p *load.Package) { // Or external linker settings and flags? case "gccgo": - id, err := b.gccgoToolID(BuildToolchain.linker(), "go") + id, err := b.gccToolID(BuildToolchain.linker(), "go") if err != nil { base.Fatalf("%v", err) } @@ -1843,6 +1876,7 @@ var objectMagic = [][]byte{ {0xCE, 0xFA, 0xED, 0xFE}, // Mach-O little-endian 32-bit {0xCF, 0xFA, 0xED, 0xFE}, // Mach-O little-endian 64-bit {0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00}, // PE (Windows) as generated by 6l/8l and gcc + {0x4d, 0x5a, 0x78, 0x00, 0x01, 0x00}, // PE (Windows) as generated by llvm for dll {0x00, 0x00, 0x01, 0xEB}, // Plan 9 i386 {0x00, 0x00, 0x8a, 0x97}, // Plan 9 amd64 {0x00, 0x00, 0x06, 0x47}, // Plan 9 arm @@ -2059,8 +2093,11 @@ func (b *Builder) runOut(a *Action, dir string, env []string, cmdargs ...interfa // Add the TOOLEXEC_IMPORTPATH environment variable for -toolexec tools. // It doesn't really matter if -toolexec isn't being used. + // Note that a.Package.Desc is not really an import path, + // but this is consistent with 'go list -f {{.ImportPath}}'. + // Plus, it is useful to uniquely identify packages in 'go list -json'. if a != nil && a.Package != nil { - cmd.Env = append(cmd.Env, "TOOLEXEC_IMPORTPATH="+a.Package.ImportPath) + cmd.Env = append(cmd.Env, "TOOLEXEC_IMPORTPATH="+a.Package.Desc()) } cmd.Env = append(cmd.Env, env...) @@ -2349,7 +2386,7 @@ func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flag cmdargs := []interface{}{cmd, "-o", outfile, objs, flags} dir := p.Dir - out, err := b.runOut(a, base.Cwd, b.cCompilerEnv(), cmdargs...) + out, err := b.runOut(a, base.Cwd(), b.cCompilerEnv(), cmdargs...) if len(out) > 0 { // Filter out useless linker warnings caused by bugs outside Go. @@ -2606,9 +2643,19 @@ func (b *Builder) gccArchArgs() []string { case "s390x": return []string{"-m64", "-march=z196"} case "mips64", "mips64le": - return []string{"-mabi=64"} + args := []string{"-mabi=64"} + if cfg.GOMIPS64 == "hardfloat" { + return append(args, "-mhard-float") + } else if cfg.GOMIPS64 == "softfloat" { + return append(args, "-msoft-float") + } case "mips", "mipsle": - return []string{"-mabi=32", "-march=mips32"} + args := []string{"-mabi=32", "-march=mips32"} + if cfg.GOMIPS == "hardfloat" { + return append(args, "-mhard-float", "-mfp32", "-mno-odd-spreg") + } else if cfg.GOMIPS == "softfloat" { + return append(args, "-msoft-float") + } case "ppc64": if cfg.Goos == "aix" { return []string{"-maix64"} @@ -2963,7 +3010,7 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe if p.Standard && p.ImportPath == "runtime/cgo" { cgoflags = []string{"-dynlinker"} // record path to dynamic linker } - return b.run(a, base.Cwd, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) + return b.run(a, base.Cwd(), p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) } // Run SWIG on all SWIG input files. @@ -3097,7 +3144,7 @@ func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) { } srcs := []string{src} - p := load.GoFilesPackage(context.TODO(), srcs) + p := load.GoFilesPackage(context.TODO(), load.PackageOpts{}, srcs) if _, _, e := BuildToolchain.gc(b, &Action{Mode: "swigDoIntSize", Package: p, Objdir: objdir}, "", nil, nil, "", false, srcs); e != nil { return "32", nil diff --git a/libgo/go/cmd/go/internal/work/gc.go b/libgo/go/cmd/go/internal/work/gc.go index cc4e2b2b..85da4f8 100644 --- a/libgo/go/cmd/go/internal/work/gc.go +++ b/libgo/go/cmd/go/internal/work/gc.go @@ -8,6 +8,7 @@ import ( "bufio" "bytes" "fmt" + "internal/buildcfg" "io" "log" "os" @@ -63,15 +64,33 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg pkgpath := pkgPath(a) gcargs := []string{"-p", pkgpath} - if p.Module != nil && p.Module.GoVersion != "" && allowedVersion(p.Module.GoVersion) { - gcargs = append(gcargs, "-lang=go"+p.Module.GoVersion) + if p.Module != nil { + v := p.Module.GoVersion + if v == "" { + // We started adding a 'go' directive to the go.mod file unconditionally + // as of Go 1.12, so any module that still lacks such a directive must + // either have been authored before then, or have a hand-edited go.mod + // file that hasn't been updated by cmd/go since that edit. + // + // Unfortunately, through at least Go 1.16 we didn't add versions to + // vendor/modules.txt. So this could also be a vendored 1.16 dependency. + // + // Fortunately, there were no breaking changes to the language between Go + // 1.11 and 1.16, so if we assume Go 1.16 semantics we will not introduce + // any spurious errors — we will only mask errors, and not particularly + // important ones at that. + v = "1.16" + } + if allowedVersion(v) { + gcargs = append(gcargs, "-lang=go"+v) + } } if p.Standard { gcargs = append(gcargs, "-std") } compilingRuntime := p.Standard && (p.ImportPath == "runtime" || strings.HasPrefix(p.ImportPath, "runtime/internal")) // The runtime package imports a couple of general internal packages. - if p.Standard && (p.ImportPath == "internal/cpu" || p.ImportPath == "internal/bytealg") { + if p.Standard && (p.ImportPath == "internal/cpu" || p.ImportPath == "internal/bytealg" || p.ImportPath == "internal/abi") { compilingRuntime = true } if compilingRuntime { @@ -129,7 +148,11 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg } } - args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), gcflags, gcargs, "-D", p.Internal.LocalPrefix} + args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), gcflags, gcargs} + if p.Internal.LocalPrefix != "" { + // Workaround #43883. + args = append(args, "-D", p.Internal.LocalPrefix) + } if importcfg != nil { if err := b.writeFile(objdir+"importcfg", importcfg); err != nil { return "", nil, err @@ -174,7 +197,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg args = append(args, f) } - output, err = b.runOut(a, base.Cwd, nil, args...) + output, err = b.runOut(a, base.Cwd(), nil, args...) return ofile, output, err } @@ -209,7 +232,7 @@ CheckFlags: } // TODO: Test and delete these conditions. - if objabi.Fieldtrack_enabled != 0 || objabi.Preemptibleloops_enabled != 0 { + if buildcfg.Experiment.FieldTrack || buildcfg.Experiment.PreemptibleLoops { canDashC = false } @@ -235,16 +258,19 @@ CheckFlags: // - it has no successor packages to compile (usually package main) // - all paths through the build graph pass through it // - critical path scheduling says it is high priority - // and in such a case, set c to runtime.NumCPU. + // and in such a case, set c to runtime.GOMAXPROCS(0). + // By default this is the same as runtime.NumCPU. // We do this now when p==1. + // To limit parallelism, set GOMAXPROCS below numCPU; this may be useful + // on a low-memory builder, or if a deterministic build order is required. + c := runtime.GOMAXPROCS(0) if cfg.BuildP == 1 { - // No process parallelism. Max out c. - return runtime.NumCPU() + // No process parallelism, do not cap compiler parallelism. + return c } - // Some process parallelism. Set c to min(4, numcpu). - c := 4 - if ncpu := runtime.NumCPU(); ncpu < c { - c = ncpu + // Some process parallelism. Set c to min(4, maxprocs). + if c > 4 { + c = 4 } return c } @@ -265,10 +291,11 @@ func (a *Action) trimpath() string { rewriteDir := a.Package.Dir if cfg.BuildTrimpath { + importPath := a.Package.Internal.OrigImportPath if m := a.Package.Module; m != nil && m.Version != "" { - rewriteDir = m.Path + "@" + m.Version + strings.TrimPrefix(a.Package.ImportPath, m.Path) + rewriteDir = m.Path + "@" + m.Version + strings.TrimPrefix(importPath, m.Path) } else { - rewriteDir = a.Package.ImportPath + rewriteDir = importPath } rewrite += a.Package.Dir + "=>" + rewriteDir + ";" } @@ -336,18 +363,6 @@ func asmArgs(a *Action, p *load.Package) []interface{} { } if objabi.IsRuntimePackagePath(pkgpath) { args = append(args, "-compiling-runtime") - if objabi.Regabi_enabled != 0 { - // In order to make it easier to port runtime assembly - // to the register ABI, we introduce a macro - // indicating the experiment is enabled. - // - // Note: a similar change also appears in - // cmd/dist/build.go. - // - // TODO(austin): Remove this once we commit to the - // register ABI (#40724). - args = append(args, "-D=GOEXPERIMENT_REGABI=1") - } } if cfg.Goarch == "mips" || cfg.Goarch == "mipsle" { diff --git a/libgo/go/cmd/go/internal/work/gccgo.go b/libgo/go/cmd/go/internal/work/gccgo.go index 36b3f4b..1e82500 100644 --- a/libgo/go/cmd/go/internal/work/gccgo.go +++ b/libgo/go/cmd/go/internal/work/gccgo.go @@ -102,7 +102,7 @@ func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg, if b.gccSupportsFlag(args[:1], "-ffile-prefix-map=a=b") { if cfg.BuildTrimpath { - args = append(args, "-ffile-prefix-map="+base.Cwd+"=.") + args = append(args, "-ffile-prefix-map="+base.Cwd()+"=.") args = append(args, "-ffile-prefix-map="+b.WorkDir+"=/tmp/go-build") } if fsys.OverlayFile != "" { @@ -114,9 +114,9 @@ func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg, } toPath := absPath // gccgo only applies the last matching rule, so also handle the case where - // BuildTrimpath is true and the path is relative to base.Cwd. - if cfg.BuildTrimpath && str.HasFilePathPrefix(toPath, base.Cwd) { - toPath = "." + toPath[len(base.Cwd):] + // BuildTrimpath is true and the path is relative to base.Cwd(). + if cfg.BuildTrimpath && str.HasFilePathPrefix(toPath, base.Cwd()) { + toPath = "." + toPath[len(base.Cwd()):] } args = append(args, "-ffile-prefix-map="+overlayPath+"="+toPath) } @@ -597,7 +597,7 @@ func (tools gccgoToolchain) cc(b *Builder, a *Action, ofile, cfile string) error } defs = tools.maybePIC(defs) if b.gccSupportsFlag(compiler, "-ffile-prefix-map=a=b") { - defs = append(defs, "-ffile-prefix-map="+base.Cwd+"=.") + defs = append(defs, "-ffile-prefix-map="+base.Cwd()+"=.") defs = append(defs, "-ffile-prefix-map="+b.WorkDir+"=/tmp/go-build") } else if b.gccSupportsFlag(compiler, "-fdebug-prefix-map=a=b") { defs = append(defs, "-fdebug-prefix-map="+b.WorkDir+"=/tmp/go-build") diff --git a/libgo/go/cmd/go/internal/work/init.go b/libgo/go/cmd/go/internal/work/init.go index ba7c7c2..37a3e2d 100644 --- a/libgo/go/cmd/go/internal/work/init.go +++ b/libgo/go/cmd/go/internal/work/init.go @@ -11,21 +11,19 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/fsys" "cmd/go/internal/modload" - "cmd/internal/objabi" "cmd/internal/sys" "flag" "fmt" "os" "path/filepath" "runtime" - "strings" ) func BuildInit() { modload.Init() instrumentInit() buildModeInit() - if err := fsys.Init(base.Cwd); err != nil { + if err := fsys.Init(base.Cwd()); err != nil { base.Fatalf("go: %v", err) } @@ -47,20 +45,6 @@ func BuildInit() { base.Fatalf("go %s: %s environment variable is relative; must be absolute path: %s\n", flag.Args()[0], key, path) } } - - // For each experiment that has been enabled in the toolchain, define a - // build tag with the same name but prefixed by "goexperiment." which can be - // used for compiling alternative files for the experiment. This allows - // changes for the experiment, like extra struct fields in the runtime, - // without affecting the base non-experiment code at all. [2:] strips the - // leading "X:" from objabi.Expstring(). - exp := objabi.Expstring()[2:] - if exp != "none" { - experiments := strings.Split(exp, ",") - for _, expt := range experiments { - cfg.BuildContext.BuildTags = append(cfg.BuildContext.BuildTags, "goexperiment."+expt) - } - } } func instrumentInit() { diff --git a/libgo/go/cmd/go/internal/work/security.go b/libgo/go/cmd/go/internal/work/security.go index 36bbab3..e9b9f6c 100644 --- a/libgo/go/cmd/go/internal/work/security.go +++ b/libgo/go/cmd/go/internal/work/security.go @@ -208,8 +208,8 @@ var validLinkerFlags = []*lazyregexp.Regexp{ re(`-Wl,-z,(no)?execstack`), re(`-Wl,-z,relro`), - re(`[a-zA-Z0-9_/].*\.(a|o|obj|dll|dylib|so)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o) - re(`\./.*\.(a|o|obj|dll|dylib|so)`), + re(`[a-zA-Z0-9_/].*\.(a|o|obj|dll|dylib|so|tbd)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o) + re(`\./.*\.(a|o|obj|dll|dylib|so|tbd)`), } var validLinkerFlagsWithNextArg = []string{ diff --git a/libgo/go/cmd/go/internal/work/security_test.go b/libgo/go/cmd/go/internal/work/security_test.go index 4f2e0eb..8d4be0a 100644 --- a/libgo/go/cmd/go/internal/work/security_test.go +++ b/libgo/go/cmd/go/internal/work/security_test.go @@ -164,6 +164,8 @@ var goodLinkerFlags = [][]string{ {"-Wl,-framework", "-Wl,Chocolate"}, {"-Wl,-framework,Chocolate"}, {"-Wl,-unresolved-symbols=ignore-all"}, + {"libcgotbdtest.tbd"}, + {"./libcgotbdtest.tbd"}, } var badLinkerFlags = [][]string{ diff --git a/libgo/go/cmd/go/internal/work/testgo.go b/libgo/go/cmd/go/internal/work/testgo.go index 931f49a..8b77871 100644 --- a/libgo/go/cmd/go/internal/work/testgo.go +++ b/libgo/go/cmd/go/internal/work/testgo.go @@ -4,6 +4,7 @@ // This file contains extra hooks for testing the go command. +//go:build testgo // +build testgo package work diff --git a/libgo/go/cmd/go/main.go b/libgo/go/cmd/go/main.go index c4af195..a325172 100644 --- a/libgo/go/cmd/go/main.go +++ b/libgo/go/cmd/go/main.go @@ -10,6 +10,7 @@ import ( "context" "flag" "fmt" + "internal/buildcfg" "log" "os" "path/filepath" @@ -147,19 +148,6 @@ func main() { os.Exit(2) } - // Set environment (GOOS, GOARCH, etc) explicitly. - // In theory all the commands we invoke should have - // the same default computation of these as we do, - // but in practice there might be skew - // This makes sure we all agree. - cfg.OrigEnv = os.Environ() - cfg.CmdEnv = envcmd.MkEnv() - for _, env := range cfg.CmdEnv { - if os.Getenv(env.Name) != env.Value { - os.Setenv(env.Name, env.Value) - } - } - BigCmdLoop: for bigCmd := base.Go; ; { for _, cmd := range bigCmd.Commands { @@ -185,18 +173,7 @@ BigCmdLoop: if !cmd.Runnable() { continue } - cmd.Flag.Usage = func() { cmd.Usage() } - if cmd.CustomFlags { - args = args[1:] - } else { - base.SetFromGOFLAGS(&cmd.Flag) - cmd.Flag.Parse(args[1:]) - args = cmd.Flag.Args() - } - ctx := maybeStartTrace(context.Background()) - ctx, span := trace.StartSpan(ctx, fmt.Sprint("Running ", cmd.Name(), " command")) - cmd.Run(ctx, cmd, args) - span.Done() + invoke(cmd, args) base.Exit() return } @@ -210,6 +187,39 @@ BigCmdLoop: } } +func invoke(cmd *base.Command, args []string) { + // 'go env' handles checking the build config + if cmd != envcmd.CmdEnv { + buildcfg.Check() + } + + // Set environment (GOOS, GOARCH, etc) explicitly. + // In theory all the commands we invoke should have + // the same default computation of these as we do, + // but in practice there might be skew + // This makes sure we all agree. + cfg.OrigEnv = os.Environ() + cfg.CmdEnv = envcmd.MkEnv() + for _, env := range cfg.CmdEnv { + if os.Getenv(env.Name) != env.Value { + os.Setenv(env.Name, env.Value) + } + } + + cmd.Flag.Usage = func() { cmd.Usage() } + if cmd.CustomFlags { + args = args[1:] + } else { + base.SetFromGOFLAGS(&cmd.Flag) + cmd.Flag.Parse(args[1:]) + args = cmd.Flag.Args() + } + ctx := maybeStartTrace(context.Background()) + ctx, span := trace.StartSpan(ctx, fmt.Sprint("Running ", cmd.Name(), " command")) + cmd.Run(ctx, cmd, args) + span.Done() +} + func init() { base.Usage = mainUsage } diff --git a/libgo/go/cmd/go/mkalldocs.sh b/libgo/go/cmd/go/mkalldocs.sh index 72886db..a2b0aca 100755 --- a/libgo/go/cmd/go/mkalldocs.sh +++ b/libgo/go/cmd/go/mkalldocs.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2012 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. @@ -6,6 +6,8 @@ set -e go build -o go.latest -./go.latest help documentation >alldocs.go +# If the command used to generate alldocs.go changes, update TestDocsUpToDate in +# help_test.go. +GO111MODULE='' ./go.latest help documentation >alldocs.go gofmt -w alldocs.go rm go.latest diff --git a/libgo/go/cmd/go/proxy_test.go b/libgo/go/cmd/go/proxy_test.go index e390c73..74bfecc 100644 --- a/libgo/go/cmd/go/proxy_test.go +++ b/libgo/go/cmd/go/proxy_test.go @@ -23,7 +23,6 @@ import ( "sync" "testing" - "cmd/go/internal/modfetch" "cmd/go/internal/modfetch/codehost" "cmd/go/internal/par" "cmd/go/internal/txtar" @@ -229,7 +228,7 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) { if m.Path != modPath { continue } - if modfetch.IsPseudoVersion(m.Version) && (latestPseudo == "" || semver.Compare(latestPseudo, m.Version) > 0) { + if module.IsPseudoVersion(m.Version) && (latestPseudo == "" || semver.Compare(latestPseudo, m.Version) > 0) { latestPseudo = m.Version } else if semver.Prerelease(m.Version) != "" && (latestPrerelease == "" || semver.Compare(latestPrerelease, m.Version) > 0) { latestPrerelease = m.Version @@ -282,7 +281,7 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) { continue } found = true - if !modfetch.IsPseudoVersion(m.Version) { + if !module.IsPseudoVersion(m.Version) { if err := module.Check(m.Path, m.Version); err == nil { fmt.Fprintf(w, "%s\n", m.Version) } @@ -315,7 +314,7 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) { for _, m := range modList { if m.Path == path && semver.Compare(best, m.Version) < 0 { var hash string - if modfetch.IsPseudoVersion(m.Version) { + if module.IsPseudoVersion(m.Version) { hash = m.Version[strings.LastIndex(m.Version, "-")+1:] } else { hash = findHash(m) @@ -362,7 +361,7 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) { var buf bytes.Buffer z := zip.NewWriter(&buf) for _, f := range a.Files { - if strings.HasPrefix(f.Name, ".") { + if f.Name == ".info" || f.Name == ".mod" || f.Name == ".zip" { continue } var zipName string diff --git a/libgo/go/cmd/go/script_test.go b/libgo/go/cmd/go/script_test.go index dfaa405..639e907 100644 --- a/libgo/go/cmd/go/script_test.go +++ b/libgo/go/cmd/go/script_test.go @@ -32,7 +32,6 @@ import ( "cmd/go/internal/robustio" "cmd/go/internal/txtar" "cmd/go/internal/work" - "cmd/internal/objabi" "cmd/internal/sys" ) @@ -41,6 +40,33 @@ func TestScript(t *testing.T) { testenv.MustHaveGoBuild(t) testenv.SkipIfShortAndSlow(t) + var ( + ctx = context.Background() + gracePeriod = 100 * time.Millisecond + ) + if deadline, ok := t.Deadline(); ok { + timeout := time.Until(deadline) + + // If time allows, increase the termination grace period to 5% of the + // remaining time. + if gp := timeout / 20; gp > gracePeriod { + gracePeriod = gp + } + + // When we run commands that execute subprocesses, we want to reserve two + // grace periods to clean up. We will send the first termination signal when + // the context expires, then wait one grace period for the process to + // produce whatever useful output it can (such as a stack trace). After the + // first grace period expires, we'll escalate to os.Kill, leaving the second + // grace period for the test function to record its output before the test + // process itself terminates. + timeout -= 2 * gracePeriod + + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, timeout) + t.Cleanup(cancel) + } + files, err := filepath.Glob("testdata/script/*.txt") if err != nil { t.Fatal(err) @@ -50,40 +76,51 @@ func TestScript(t *testing.T) { name := strings.TrimSuffix(filepath.Base(file), ".txt") t.Run(name, func(t *testing.T) { t.Parallel() - ts := &testScript{t: t, name: name, file: file} + ctx, cancel := context.WithCancel(ctx) + ts := &testScript{ + t: t, + ctx: ctx, + cancel: cancel, + gracePeriod: gracePeriod, + name: name, + file: file, + } ts.setup() if !*testWork { defer removeAll(ts.workdir) } ts.run() + cancel() }) } } // A testScript holds execution state for a single test script. type testScript struct { - t *testing.T - workdir string // temporary work dir ($WORK) - log bytes.Buffer // test execution log (printed at end of test) - mark int // offset of next log truncation - cd string // current directory during test execution; initially $WORK/gopath/src - name string // short name of test ("foo") - file string // full file name ("testdata/script/foo.txt") - lineno int // line number currently executing - line string // line currently executing - env []string // environment list (for os/exec) - envMap map[string]string // environment mapping (matches env) - stdout string // standard output from last 'go' command; for 'stdout' command - stderr string // standard error from last 'go' command; for 'stderr' command - stopped bool // test wants to stop early - start time.Time // time phase started - background []*backgroundCmd // backgrounded 'exec' and 'go' commands + t *testing.T + ctx context.Context + cancel context.CancelFunc + gracePeriod time.Duration + workdir string // temporary work dir ($WORK) + log bytes.Buffer // test execution log (printed at end of test) + mark int // offset of next log truncation + cd string // current directory during test execution; initially $WORK/gopath/src + name string // short name of test ("foo") + file string // full file name ("testdata/script/foo.txt") + lineno int // line number currently executing + line string // line currently executing + env []string // environment list (for os/exec) + envMap map[string]string // environment mapping (matches env) + stdout string // standard output from last 'go' command; for 'stdout' command + stderr string // standard error from last 'go' command; for 'stderr' command + stopped bool // test wants to stop early + start time.Time // time phase started + background []*backgroundCmd // backgrounded 'exec' and 'go' commands } type backgroundCmd struct { want simpleStatus args []string - cancel context.CancelFunc done <-chan struct{} err error stdout, stderr strings.Builder @@ -109,6 +146,10 @@ var extraEnvKeys = []string{ // setup sets up the test execution temporary directory and environment. func (ts *testScript) setup() { + if err := ts.ctx.Err(); err != nil { + ts.t.Fatalf("test interrupted during setup: %v", err) + } + StartProxy() ts.workdir = filepath.Join(testTmpDir, "script-"+ts.name) ts.check(os.MkdirAll(filepath.Join(ts.workdir, "tmp"), 0777)) @@ -123,13 +164,13 @@ func (ts *testScript) setup() { "GOCACHE=" + testGOCACHE, "GODEBUG=" + os.Getenv("GODEBUG"), "GOEXE=" + cfg.ExeSuffix, - "GOEXPSTRING=" + objabi.Expstring()[2:], "GOOS=" + runtime.GOOS, "GOPATH=" + filepath.Join(ts.workdir, "gopath"), "GOPROXY=" + proxyURL, "GOPRIVATE=", "GOROOT=" + testGOROOT, "GOROOT_FINAL=" + os.Getenv("GOROOT_FINAL"), // causes spurious rebuilds and breaks the "stale" built-in if not propagated + "GOTRACEBACK=system", "TESTGO_GOROOT=" + testGOROOT, "GOSUMDB=" + testSumDBVerifierKey, "GONOPROXY=", @@ -200,9 +241,7 @@ func (ts *testScript) run() { // On a normal exit from the test loop, background processes are cleaned up // before we print PASS. If we return early (e.g., due to a test failure), // don't print anything about the processes that were still running. - for _, bg := range ts.background { - bg.cancel() - } + ts.cancel() for _, bg := range ts.background { <-bg.done } @@ -275,6 +314,10 @@ Script: fmt.Fprintf(&ts.log, "> %s\n", line) for _, cond := range parsed.conds { + if err := ts.ctx.Err(); err != nil { + ts.fatalf("test interrupted: %v", err) + } + // Known conds are: $GOOS, $GOARCH, runtime.Compiler, and 'short' (for testing.Short). // // NOTE: If you make changes here, update testdata/script/README too! @@ -356,9 +399,7 @@ Script: } } - for _, bg := range ts.background { - bg.cancel() - } + ts.cancel() ts.cmdWait(success, nil) // Final phase ended. @@ -476,7 +517,7 @@ func (ts *testScript) cmdCd(want simpleStatus, args []string) { ts.fatalf("usage: cd dir") } - dir := args[0] + dir := filepath.FromSlash(args[0]) if !filepath.IsAbs(dir) { dir = filepath.Join(ts.cd, dir) } @@ -798,9 +839,7 @@ func (ts *testScript) cmdSkip(want simpleStatus, args []string) { // Before we mark the test as skipped, shut down any background processes and // make sure they have returned the correct status. - for _, bg := range ts.background { - bg.cancel() - } + ts.cancel() ts.cmdWait(success, nil) if len(args) == 1 { @@ -1065,38 +1104,9 @@ func (ts *testScript) exec(command string, args ...string) (stdout, stderr strin func (ts *testScript) startBackground(want simpleStatus, command string, args ...string) (*backgroundCmd, error) { done := make(chan struct{}) bg := &backgroundCmd{ - want: want, - args: append([]string{command}, args...), - done: done, - cancel: func() {}, - } - - ctx := context.Background() - gracePeriod := 100 * time.Millisecond - if deadline, ok := ts.t.Deadline(); ok { - timeout := time.Until(deadline) - // If time allows, increase the termination grace period to 5% of the - // remaining time. - if gp := timeout / 20; gp > gracePeriod { - gracePeriod = gp - } - - // Send the first termination signal with two grace periods remaining. - // If it still hasn't finished after the first period has elapsed, - // we'll escalate to os.Kill with a second period remaining until the - // test deadline.. - timeout -= 2 * gracePeriod - - if timeout <= 0 { - // The test has less than the grace period remaining. There is no point in - // even starting the command, because it will be terminated immediately. - // Save the expense of starting it in the first place. - bg.err = context.DeadlineExceeded - close(done) - return bg, nil - } - - ctx, bg.cancel = context.WithTimeout(ctx, timeout) + want: want, + args: append([]string{command}, args...), + done: done, } cmd := exec.Command(command, args...) @@ -1105,29 +1115,16 @@ func (ts *testScript) startBackground(want simpleStatus, command string, args .. cmd.Stdout = &bg.stdout cmd.Stderr = &bg.stderr if err := cmd.Start(); err != nil { - bg.cancel() return nil, err } go func() { - bg.err = waitOrStop(ctx, cmd, stopSignal(), gracePeriod) + bg.err = waitOrStop(ts.ctx, cmd, quitSignal(), ts.gracePeriod) close(done) }() return bg, nil } -// stopSignal returns the appropriate signal to use to request that a process -// stop execution. -func stopSignal() os.Signal { - if runtime.GOOS == "windows" { - // Per https://golang.org/pkg/os/#Signal, “Interrupt is not implemented on - // Windows; using it with os.Process.Signal will return an error.” - // Fall back to Kill instead. - return os.Kill - } - return os.Interrupt -} - // waitOrStop waits for the already-started command cmd by calling its Wait method. // // If cmd does not return before ctx is done, waitOrStop sends it the given interrupt signal. diff --git a/libgo/go/cmd/go/stop_other_test.go b/libgo/go/cmd/go/stop_other_test.go new file mode 100644 index 0000000..e1cc6cf --- /dev/null +++ b/libgo/go/cmd/go/stop_other_test.go @@ -0,0 +1,33 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !(aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris) +// +build !aix +// +build !darwin +// +build !dragonfly +// +build !freebsd +// +build !js !wasm +// +build !linux +// +build !netbsd +// +build !openbsd +// +build !solaris + +package main_test + +import ( + "os" + "runtime" +) + +// quitSignal returns the appropriate signal to use to request that a process +// quit execution. +func quitSignal() os.Signal { + if runtime.GOOS == "windows" { + // Per https://golang.org/pkg/os/#Signal, “Interrupt is not implemented on + // Windows; using it with os.Process.Signal will return an error.” + // Fall back to Kill instead. + return os.Kill + } + return os.Interrupt +} diff --git a/libgo/go/cmd/go/stop_unix_test.go b/libgo/go/cmd/go/stop_unix_test.go new file mode 100644 index 0000000..ac35b24 --- /dev/null +++ b/libgo/go/cmd/go/stop_unix_test.go @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris + +package main_test + +import ( + "os" + "syscall" +) + +func quitSignal() os.Signal { + return syscall.SIGQUIT +} diff --git a/libgo/go/cmd/go/testdata/addmod.go b/libgo/go/cmd/go/testdata/addmod.go index 09fc8e7..03869e6 100644 --- a/libgo/go/cmd/go/testdata/addmod.go +++ b/libgo/go/cmd/go/testdata/addmod.go @@ -22,10 +22,10 @@ import ( "bytes" "flag" "fmt" + exec "internal/execabs" "io/fs" "log" "os" - exec "internal/execabs" "path/filepath" "strings" diff --git a/libgo/go/cmd/go/testdata/mod/example.com_ambiguous_a_b_v0.0.0-empty.txt b/libgo/go/cmd/go/testdata/mod/example.com_ambiguous_a_b_v0.0.0-empty.txt new file mode 100644 index 0000000..a869519 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_ambiguous_a_b_v0.0.0-empty.txt @@ -0,0 +1,12 @@ +Module example.com/ambiguous/a/b is a suffix of example.com/a. +This version contains no package. +-- .mod -- +module example.com/ambiguous/a/b + +go 1.16 +-- .info -- +{"Version":"v0.0.0-empty"} +-- go.mod -- +module example.com/ambiguous/a/b + +go 1.16 diff --git a/libgo/go/cmd/go/testdata/mod/example.com_ambiguous_a_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_ambiguous_a_v1.0.0.txt new file mode 100644 index 0000000..bb43826 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_ambiguous_a_v1.0.0.txt @@ -0,0 +1,18 @@ +Module example.com/ambiguous/a is a prefix of example.com/a/b. +It contains package example.com/a/b. +-- .mod -- +module example.com/ambiguous/a + +go 1.16 + +require example.com/ambiguous/a/b v0.0.0-empty +-- .info -- +{"Version":"v1.0.0"} +-- go.mod -- +module example.com/ambiguous/a + +go 1.16 + +require example.com/ambiguous/a/b v0.0.0-empty +-- b/b.go -- +package b diff --git a/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-exclude.txt b/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-exclude.txt new file mode 100644 index 0000000..c883d8a --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-exclude.txt @@ -0,0 +1,28 @@ +example.com/cmd contains main packages. + +-- .info -- +{"Version":"v1.0.0-exclude"} +-- .mod -- +module example.com/cmd + +go 1.16 + +exclude rsc.io/quote v1.5.2 +-- go.mod -- +module example.com/cmd + +go 1.16 + +exclude rsc.io/quote v1.5.2 +-- a/a.go -- +package main + +func main() {} +-- b/b.go -- +package main + +func main() {} +-- err/err.go -- +package err + +var X = DoesNotCompile diff --git a/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-newerself.txt b/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-newerself.txt new file mode 100644 index 0000000..7670f29 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-newerself.txt @@ -0,0 +1,28 @@ +example.com/cmd contains main packages. + +-- .info -- +{"Version":"v1.0.0-newerself"} +-- .mod -- +module example.com/cmd + +go 1.16 + +require example.com/cmd v1.0.0 +-- go.mod -- +module example.com/cmd + +go 1.16 + +require example.com/cmd v1.0.0 +-- a/a.go -- +package main + +func main() {} +-- b/b.go -- +package main + +func main() {} +-- err/err.go -- +package err + +var X = DoesNotCompile diff --git a/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-replace.txt b/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-replace.txt new file mode 100644 index 0000000..581a496 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0-replace.txt @@ -0,0 +1,28 @@ +example.com/cmd contains main packages. + +-- .info -- +{"Version":"v1.0.0-replace"} +-- .mod -- +module example.com/cmd + +go 1.16 + +replace rsc.io/quote => rsc.io/quote v1.5.2 +-- go.mod -- +module example.com/cmd + +go 1.16 + +replace rsc.io/quote => rsc.io/quote v1.5.2 +-- a/a.go -- +package main + +func main() {} +-- b/b.go -- +package main + +func main() {} +-- err/err.go -- +package err + +var X = DoesNotCompile diff --git a/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0.txt new file mode 100644 index 0000000..c198139 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.0.0.txt @@ -0,0 +1,31 @@ +example.com/cmd contains main packages. + +v1.0.0 is the latest non-retracted version. Other versions contain errors or +detectable problems. + +-- .info -- +{"Version":"v1.0.0"} +-- .mod -- +module example.com/cmd + +go 1.16 +-- go.mod -- +module example.com/cmd + +go 1.16 +-- a/a.go -- +package main + +import "fmt" + +func main() { fmt.Println("a@v1.0.0") } +-- b/b.go -- +package main + +import "fmt" + +func main() { fmt.Println("b@v1.0.0") } +-- err/err.go -- +package err + +var X = DoesNotCompile diff --git a/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.9.0.txt new file mode 100644 index 0000000..9298afb --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_cmd_v1.9.0.txt @@ -0,0 +1,30 @@ +example.com/cmd contains main packages. + +-- .info -- +{"Version":"v1.9.0"} +-- .mod -- +module example.com/cmd + +go 1.16 + +// this is a bad version +retract v1.9.0 +-- go.mod -- +module example.com/cmd + +go 1.16 + +// this is a bad version +retract v1.9.0 +-- a/a.go -- +package main + +func main() {} +-- b/b.go -- +package main + +func main() {} +-- err/err.go -- +package err + +var X = DoesNotCompile diff --git a/libgo/go/cmd/go/testdata/mod/example.com_deprecated_a_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_deprecated_a_v1.0.0.txt new file mode 100644 index 0000000..7c29621 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_deprecated_a_v1.0.0.txt @@ -0,0 +1,12 @@ +-- .info -- +{"Version":"v1.0.0"} +-- .mod -- +module example.com/deprecated/a + +go 1.17 +-- go.mod -- +module example.com/deprecated/a + +go 1.17 +-- a.go -- +package a diff --git a/libgo/go/cmd/go/testdata/mod/example.com_deprecated_a_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_deprecated_a_v1.9.0.txt new file mode 100644 index 0000000..0613389 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_deprecated_a_v1.9.0.txt @@ -0,0 +1,14 @@ +-- .info -- +{"Version":"v1.9.0"} +-- .mod -- +// Deprecated: in example.com/deprecated/a@v1.9.0 +module example.com/deprecated/a + +go 1.17 +-- go.mod -- +// Deprecated: in example.com/deprecated/a@v1.9.0 +module example.com/deprecated/a + +go 1.17 +-- a.go -- +package a diff --git a/libgo/go/cmd/go/testdata/mod/example.com_deprecated_b_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_deprecated_b_v1.0.0.txt new file mode 100644 index 0000000..50006ae --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_deprecated_b_v1.0.0.txt @@ -0,0 +1,12 @@ +-- .info -- +{"Version":"v1.0.0"} +-- .mod -- +module example.com/deprecated/b + +go 1.17 +-- go.mod -- +module example.com/deprecated/b + +go 1.17 +-- b.go -- +package b diff --git a/libgo/go/cmd/go/testdata/mod/example.com_deprecated_b_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_deprecated_b_v1.9.0.txt new file mode 100644 index 0000000..163d6b5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_deprecated_b_v1.9.0.txt @@ -0,0 +1,14 @@ +-- .info -- +{"Version":"v1.9.0"} +-- .mod -- +// Deprecated: in example.com/deprecated/b@v1.9.0 +module example.com/deprecated/b + +go 1.17 +-- go.mod -- +// Deprecated: in example.com/deprecated/b@v1.9.0 +module example.com/deprecated/b + +go 1.17 +-- b.go -- +package b diff --git a/libgo/go/cmd/go/testdata/mod/example.com_dotname_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_dotname_v1.0.0.txt new file mode 100644 index 0000000..2ada3a3 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_dotname_v1.0.0.txt @@ -0,0 +1,12 @@ +-- .info -- +{"Version":"v1.0.0"} +-- .mod -- +module example.com/dotname + +go 1.16 +-- go.mod -- +module example.com/dotname + +go 1.16 +-- .dot/dot.go -- +package dot diff --git a/libgo/go/cmd/go/testdata/mod/example.com_incompatiblewithsub_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_incompatiblewithsub_v1.0.0.txt new file mode 100644 index 0000000..435578d --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_incompatiblewithsub_v1.0.0.txt @@ -0,0 +1,8 @@ +Module example.com/incompatiblewithsub has an incompatible version +and a package in a subdirectory. +-- .info -- +{"Version":"v1.0.0"} +-- .mod -- +module example.com/incompatiblewithsub +-- sub/sub.go -- +package sub diff --git a/libgo/go/cmd/go/testdata/mod/example.com_incompatiblewithsub_v2.0.0+incompatible.txt b/libgo/go/cmd/go/testdata/mod/example.com_incompatiblewithsub_v2.0.0+incompatible.txt new file mode 100644 index 0000000..198ec17 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_incompatiblewithsub_v2.0.0+incompatible.txt @@ -0,0 +1,8 @@ +Module example.com/incompatiblewithsub has an incompatible version +and a package in a subdirectory. +-- .info -- +{"Version":"v2.0.0+incompatible"} +-- .mod -- +module example.com/incompatiblewithsub +-- sub/sub.go -- +package sub diff --git a/libgo/go/cmd/go/testdata/mod/example.com_quote_v1.5.2.txt b/libgo/go/cmd/go/testdata/mod/example.com_quote_v1.5.2.txt new file mode 100644 index 0000000..05f7ae2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_quote_v1.5.2.txt @@ -0,0 +1,9 @@ +This module is a replacement for rsc.io/quote, but its go.mod file declares +a module path different from its location and the original module. + +-- .mod -- +module rsc.io/Quote + +go 1.14 +-- .info -- +{"Version":"v1.5.2"} diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_nested_v1.9.0-bad.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_nested_v1.9.0-bad.txt new file mode 100644 index 0000000..f8e623d --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_nested_v1.9.0-bad.txt @@ -0,0 +1,10 @@ +-- .mod -- +module example.com/retract/ambiguous/nested + +go 1.16 + +retract v1.9.0-bad // nested modules are bad +-- .info -- +{"Version":"v1.9.0-bad"} +-- nested.go -- +package nested diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_other_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_other_v1.0.0.txt new file mode 100644 index 0000000..5ee0139 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_other_v1.0.0.txt @@ -0,0 +1,12 @@ +-- .mod -- +module example.com/retract/ambiguous/other + +go 1.16 + +require example.com/retract/ambiguous v1.0.0 +-- .info -- +{"Version":"v1.0.0"} +-- other.go -- +package other + +import _ "example.com/retract/ambiguous/nested" diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_v1.0.0.txt new file mode 100644 index 0000000..c8eeb16 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_ambiguous_v1.0.0.txt @@ -0,0 +1,9 @@ +-- .mod -- +module example.com/retract/ambiguous + +go 1.16 +-- .info -- +{"Version":"v1.0.0"} +-- nested/nested.go -- +package nested + diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_incompatible_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_incompatible_v1.0.0.txt new file mode 100644 index 0000000..a987685 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_incompatible_v1.0.0.txt @@ -0,0 +1,19 @@ +The v1.0.0 release of example.com/retract/incompatible retracts +v2.0.0+incompatible. + +-- .mod -- +module example.com/retract/incompatible + +go 1.16 + +retract v2.0.0+incompatible +-- .info -- +{"Version":"v1.0.0"} +-- go.mod -- +module example.com/retract/incompatible + +go 1.16 + +retract v2.0.0+incompatible +-- incompatible.go -- +package incompatible diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_incompatible_v2.0.0+incompatible.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_incompatible_v2.0.0+incompatible.txt new file mode 100644 index 0000000..c668dbb --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_incompatible_v2.0.0+incompatible.txt @@ -0,0 +1,9 @@ +The v1.0.0 release of example.com/retract/incompatible retracts +v2.0.0+incompatible. + +-- .mod -- +module example.com/retract/incompatible +-- .info -- +{"Version":"v2.0.0+incompatible"} +-- incompatible.go -- +package incompatible diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_missingmod_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_missingmod_v1.0.0.txt new file mode 100644 index 0000000..1d8d810 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_missingmod_v1.0.0.txt @@ -0,0 +1,10 @@ +This version should be retracted, but the go.mod file for the version that would +contain the retraction is not available. +-- .mod -- +module example.com/retract/missingmod + +go 1.14 +-- .info -- +{"Version":"v1.0.0"} +-- missingmod.go -- +package missingmod diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_missingmod_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_missingmod_v1.9.0.txt new file mode 100644 index 0000000..bba919e --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_missingmod_v1.9.0.txt @@ -0,0 +1,4 @@ +The go.mod file at this version will be loaded to check for retractions +of earlier versions. However, the .mod file is not available. +-- .info -- +{"Version":"v1.9.0"} diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-block.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-block.txt new file mode 100644 index 0000000..c4a53e1 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-block.txt @@ -0,0 +1,6 @@ +-- .mod -- +module example.com/retract/rationale + +go 1.14 +-- .info -- +{"Version":"v1.0.0-block"} diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-blockwithcomment.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-blockwithcomment.txt new file mode 100644 index 0000000..92573b6 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-blockwithcomment.txt @@ -0,0 +1,6 @@ +-- .mod -- +module example.com/retract/rationale + +go 1.14 +-- .info -- +{"Version":"v1.0.0-blockwithcomment"} diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-empty.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-empty.txt new file mode 100644 index 0000000..1f0894a --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-empty.txt @@ -0,0 +1,8 @@ +-- .mod -- +module example.com/retract/rationale + +go 1.14 +-- .info -- +{"Version":"v1.0.0-empty"} +-- empty.go -- +package empty diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-long.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-long.txt new file mode 100644 index 0000000..1b5e753 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-long.txt @@ -0,0 +1,8 @@ +-- .mod -- +module example.com/retract/rationale + +go 1.14 +-- .info -- +{"Version":"v1.0.0-long"} +-- empty.go -- +package empty diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-multiline1.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-multiline1.txt new file mode 100644 index 0000000..b1ffe27 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-multiline1.txt @@ -0,0 +1,8 @@ +-- .mod -- +module example.com/retract/rationale + +go 1.14 +-- .info -- +{"Version":"v1.0.0-multiline1"} +-- empty.go -- +package empty diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-multiline2.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-multiline2.txt new file mode 100644 index 0000000..72f80b3 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-multiline2.txt @@ -0,0 +1,8 @@ +-- .mod -- +module example.com/retract/rationale + +go 1.14 +-- .info -- +{"Version":"v1.0.0-multiline2"} +-- empty.go -- +package empty diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-order.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-order.txt new file mode 100644 index 0000000..1b04504 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-order.txt @@ -0,0 +1,6 @@ +-- .mod -- +module example.com/retract/rationale + +go 1.14 +-- .info -- +{"Version":"v1.0.0-order"} diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-unprintable.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-unprintable.txt new file mode 100644 index 0000000..9496124 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.0-unprintable.txt @@ -0,0 +1,8 @@ +-- .mod -- +module example.com/retract/rationale + +go 1.14 +-- .info -- +{"Version":"v1.0.0-unprintable"} +-- empty.go -- +package empty diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.1-order.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.1-order.txt new file mode 100644 index 0000000..3be7d5b --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.0.1-order.txt @@ -0,0 +1,6 @@ +-- .mod -- +module example.com/retract/rationale + +go 1.14 +-- .info -- +{"Version":"v1.0.1-order"} diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.9.0.txt new file mode 100644 index 0000000..6975d4e --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_rationale_v1.9.0.txt @@ -0,0 +1,48 @@ +Module example.com/retract/description retracts all versions of itself. +The rationale comments have various problems. + +-- .mod -- +module example.com/retract/rationale + +go 1.14 + +retract ( + v1.0.0-empty + + // short description + // more + // + // detail + v1.0.0-multiline1 // suffix + // after not included +) + +// short description +// more +// +// detail +retract v1.0.0-multiline2 // suffix + +// loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +retract v1.0.0-long + +// Ends with a BEL character. Beep! +retract v1.0.0-unprintable + +// block comment +retract ( + v1.0.0-block + + // inner comment + v1.0.0-blockwithcomment +) + +retract ( + [v1.0.0-order, v1.0.0-order] // degenerate range + v1.0.0-order // single version + + v1.0.1-order // single version + [v1.0.1-order, v1.0.1-order] // degenerate range +) +-- .info -- +{"Version":"v1.9.0"} diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rename_v1.0.0-bad.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rename_v1.0.0-bad.txt new file mode 100644 index 0000000..25c4ff1 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_rename_v1.0.0-bad.txt @@ -0,0 +1,16 @@ +Module example.com/retract/rename is renamed in a later version. + +This happens frequently when a repository is renamed or when a go.mod file +is added for the first time with a custom module path. +-- .info -- +{"Version":"v1.0.0-bad"} +-- .mod -- +module example.com/retract/rename + +go 1.16 +-- go.mod -- +module example.com/retract/rename + +go 1.16 +-- rename.go -- +package rename diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_rename_v1.9.0-new.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_rename_v1.9.0-new.txt new file mode 100644 index 0000000..9c08f71 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_rename_v1.9.0-new.txt @@ -0,0 +1,22 @@ +Module example.com/retract/rename is renamed in this version. + +This happens frequently when a repository is renamed or when a go.mod file +is added for the first time with a custom module path. +-- .info -- +{"Version":"v1.9.0-new"} +-- .mod -- +module example.com/retract/newname + +go 1.16 + +// bad +retract v1.0.0-bad +-- go.mod -- +module example.com/retract/newname + +go 1.16 + +// bad +retract v1.0.0-bad +-- newname.go -- +package newname diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_all_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_all_v1.9.0.txt new file mode 100644 index 0000000..4dc486b5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_all_v1.9.0.txt @@ -0,0 +1,14 @@ +Module example.com/retract/self/prev is a module that retracts its own +latest version. + +No unretracted versions are available. + +-- .mod -- +module example.com/retract/self/all + +go 1.15 + +retract v1.9.0 // bad + +-- .info -- +{"Version":"v1.9.0"} diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.0.0.txt new file mode 100644 index 0000000..04c2845 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.0.0.txt @@ -0,0 +1,16 @@ +Module example.com/retract/self/prerelease is a module that retracts its own +latest version and all other release version. + +A pre-release version higher than the highest release version is still +available, and that should be matched by @latest. + +-- .mod -- +module example.com/retract/self/prerelease + +go 1.15 + +-- .info -- +{"Version":"v1.0.0"} + +-- p.go -- +package p diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.9.0.txt new file mode 100644 index 0000000..7c1c047e --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.9.0.txt @@ -0,0 +1,19 @@ +Module example.com/retract/self/prerelease is a module that retracts its own +latest version and all other release version. + +A pre-release version higher than the highest release version is still +available, and that should be matched by @latest. + +-- .mod -- +module example.com/retract/self/prerelease + +go 1.15 + +retract v1.0.0 // bad +retract v1.9.0 // self + +-- .info -- +{"Version":"v1.9.0"} + +-- p.go -- +package p diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.9.1-pre.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.9.1-pre.txt new file mode 100644 index 0000000..abf44fd --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prerelease_v1.9.1-pre.txt @@ -0,0 +1,16 @@ +Module example.com/retract/self/prerelease is a module that retracts its own +latest version and all other release version. + +A pre-release version higher than the highest release version is still +available, and that should be matched by @latest. + +-- .mod -- +module example.com/retract/self/prerelease + +go 1.15 + +-- .info -- +{"Version":"v1.9.1-pre"} + +-- p.go -- +package p diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.0.0-bad.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.0.0-bad.txt new file mode 100644 index 0000000..095063d --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.0.0-bad.txt @@ -0,0 +1,14 @@ +See example.com_retract_self_prev_v1.9.0.txt. + +This version is retracted. + +-- .mod -- +module example.com/retract/self/prev + +go 1.15 + +-- .info -- +{"Version":"v1.0.0-bad"} + +-- p.go -- +package p diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.1.0.txt new file mode 100644 index 0000000..27c3a39 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.1.0.txt @@ -0,0 +1,14 @@ +See example.com_retract_self_pref_v1.9.0.txt. + +This version is the latest (only) non-retracted version. + +-- .mod -- +module example.com/retract/self/prev + +go 1.15 + +-- .info -- +{"Version":"v1.1.0"} + +-- p.go -- +package p diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.9.0.txt new file mode 100644 index 0000000..03d6168 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_prev_v1.9.0.txt @@ -0,0 +1,18 @@ +Module example.com/retract/self/prev is a module that retracts its own +latest version, as well as an earlier version. + +A previous unretracted release version, v1.1.0, is still available. + +-- .mod -- +module example.com/retract/self/prev + +go 1.15 + +retract v1.0.0-bad // bad +retract v1.9.0 // self + +-- .info -- +{"Version":"v1.9.0"} + +-- p.go -- +package p diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v0.0.0-20200325131415-0123456789ab b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v0.0.0-20200325131415-0123456789ab new file mode 100644 index 0000000..f9ab41e --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v0.0.0-20200325131415-0123456789ab @@ -0,0 +1,20 @@ +See example.com_retract_self_pseudo_v1.9.0.txt. + +This version is not retracted. It should be returned by the proxy's +@latest endpoint. It should match the @latest version query. + +TODO(golang.org/issue/24031): the proxy and proxy.golang.org both return +the highest release version from the @latest endpoint, even if that +version is retracted, so there is no way for the go command to +discover an unretracted pseudo-version. + +-- .mod -- +module example.com/retract/self/pseudo + +go 1.15 + +-- .info -- +{"Version":"v0.0.0-20200325131415-01234567890ab"} + +-- p.go -- +package p diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v1.0.0-bad.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v1.0.0-bad.txt new file mode 100644 index 0000000..d47eda0 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v1.0.0-bad.txt @@ -0,0 +1,14 @@ +See example.com_retract_self_pseudo_v1.9.0.txt. + +This version is retracted. + +-- .mod -- +module example.com/retract/self/pseudo + +go 1.15 + +-- .info -- +{"Version":"v1.0.0-bad"} + +-- p.go -- +package p diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v1.9.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v1.9.0.txt new file mode 100644 index 0000000..db09cc6 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_self_pseudo_v1.9.0.txt @@ -0,0 +1,16 @@ +Module example.com/retract/self/pseudo is a module that retracts its own +latest version, as well as an earlier version. + +An unretracted pseudo-version is available. + +-- .mod -- +module example.com/retract/self/pseudo + +go 1.15 + +retract v1.0.0-bad // bad +retract v1.9.0 // self + +-- .info -- +{"Version":"v1.9.0"} + diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-bad.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-bad.txt new file mode 100644 index 0000000..2f996cf --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-bad.txt @@ -0,0 +1,10 @@ +-- .mod -- +module example.com/retract + +go 1.15 + +-- .info -- +{"Version":"v1.0.0-bad"} + +-- retract.go -- +package retract diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-good.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-good.txt new file mode 100644 index 0000000..78152bb --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-good.txt @@ -0,0 +1,10 @@ +-- .mod -- +module example.com/retract + +go 1.15 + +-- .info -- +{"Version":"v1.0.0-good"} + +-- retract.go -- +package retract diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-unused.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-unused.txt new file mode 100644 index 0000000..3bc9e35 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.0.0-unused.txt @@ -0,0 +1,10 @@ +-- .mod -- +module example.com/retract + +go 1.15 + +-- .info -- +{"Version":"v1.0.0-unused"} + +-- retract.go -- +package retract diff --git a/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.1.0.txt new file mode 100644 index 0000000..18d6d83 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_retract_v1.1.0.txt @@ -0,0 +1,13 @@ +-- .mod -- +module example.com/retract + +go 1.15 + +retract v1.0.0-bad // bad +retract v1.0.0-unused // bad + +-- .info -- +{"Version":"v1.1.0"} + +-- retract.go -- +package retract diff --git a/libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_subpkg_v0.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_subpkg_v0.1.0.txt new file mode 100644 index 0000000..edf5d48 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_subpkg_v0.1.0.txt @@ -0,0 +1,14 @@ +Written by hand. +Test case for getting a package that has been moved to a nested module, +with a +incompatible version (and thus no go.mod file) at the root module. + +-- .mod -- +module example.com/split-incompatible/subpkg +-- .info -- +{"Version": "v0.1.0"} +-- go.mod -- +module example.com/split-incompatible/subpkg + +go 1.16 +-- subpkg.go -- +package subpkg diff --git a/libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_v2.0.0+incompatible.txt b/libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_v2.0.0+incompatible.txt new file mode 100644 index 0000000..35c3f27 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_v2.0.0+incompatible.txt @@ -0,0 +1,10 @@ +Written by hand. +Test case for getting a package that has been moved to a nested module, +with a +incompatible verison (and thus no go.mod file) at the root module. + +-- .mod -- +module example.com/split-incompatible +-- .info -- +{"Version": "v2.0.0+incompatible"} +-- subpkg/subpkg.go -- +package subpkg diff --git a/libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_v2.1.0-pre+incompatible.txt b/libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_v2.1.0-pre+incompatible.txt new file mode 100644 index 0000000..917fc0f --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_split-incompatible_v2.1.0-pre+incompatible.txt @@ -0,0 +1,10 @@ +Written by hand. +Test case for getting a package that has been moved to a nested module, +with a +incompatible verison (and thus no go.mod file) at the root module. + +-- .mod -- +module example.com/split-incompatible +-- .info -- +{"Version": "v2.1.0-pre+incompatible"} +-- README.txt -- +subpkg has moved to module example.com/split-incompatible/subpkg diff --git a/libgo/go/cmd/go/testdata/mod/example.com_undeprecated_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_undeprecated_v1.0.0.txt new file mode 100644 index 0000000..a68588e --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_undeprecated_v1.0.0.txt @@ -0,0 +1,14 @@ +-- .info -- +{"Version":"v1.0.0"} +-- .mod -- +// Deprecated: in v1.0.0 +module example.com/undeprecated + +go 1.17 +-- go.mod -- +// Deprecated: in v1.0.0 +module example.com/undeprecated + +go 1.17 +-- undeprecated.go -- +package undeprecated diff --git a/libgo/go/cmd/go/testdata/mod/example.com_undeprecated_v1.0.1.txt b/libgo/go/cmd/go/testdata/mod/example.com_undeprecated_v1.0.1.txt new file mode 100644 index 0000000..ecabf32 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_undeprecated_v1.0.1.txt @@ -0,0 +1,14 @@ +-- .info -- +{"Version":"v1.0.1"} +-- .mod -- +// no longer deprecated +module example.com/undeprecated + +go 1.17 +-- go.mod -- +// no longer deprecated +module example.com/undeprecated + +go 1.17 +-- undeprecated.go -- +package undeprecated diff --git a/libgo/go/cmd/go/testdata/mod/example.net_ambiguous_nested_v0.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.net_ambiguous_nested_v0.1.0.txt new file mode 100644 index 0000000..8c9de7a --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.net_ambiguous_nested_v0.1.0.txt @@ -0,0 +1,19 @@ +Written by hand. + +Test module containing a package that is also provided by a nested module tagged +with the same version. + +-- .mod -- +module example.net/ambiguous/nested + +go 1.16 +-- .info -- +{"Version": "v0.1.0"} +-- go.mod -- +module example.net/ambiguous/nested + +go 1.16 +-- pkg/pkg.go -- +// Package pkg exists in both example.net/ambiguous v0.1.0 +// and example.net/ambiguous/nested v0.1.0 +package pkg diff --git a/libgo/go/cmd/go/testdata/mod/example.net_ambiguous_v0.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.net_ambiguous_v0.1.0.txt new file mode 100644 index 0000000..8fa6d83 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.net_ambiguous_v0.1.0.txt @@ -0,0 +1,19 @@ +Written by hand. + +Test module containing a package that is also provided by a nested module tagged +with the same version. + +-- .mod -- +module example.net/ambiguous + +go 1.16 +-- .info -- +{"Version": "v0.1.0"} +-- go.mod -- +module example.net/ambiguous + +go 1.16 +-- nested/pkg/pkg.go -- +// Package pkg exists in both example.net/ambiguous v0.1.0 +// and example.net/ambiguous/nested v0.1.0 +package pkg diff --git a/libgo/go/cmd/go/testdata/mod/example.net_ambiguous_v0.2.0.txt b/libgo/go/cmd/go/testdata/mod/example.net_ambiguous_v0.2.0.txt new file mode 100644 index 0000000..7589ad7 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.net_ambiguous_v0.2.0.txt @@ -0,0 +1,18 @@ +Written by hand. + +Test module containing a package that is also provided by a nested module tagged +with the same version. + +-- .mod -- +module example.net/ambiguous + +go 1.16 +-- .info -- +{"Version": "v0.2.0"} +-- go.mod -- +module example.net/ambiguous + +go 1.16 +-- nested/pkg/README.txt -- +// Package pkg no longer exists in this module at v0.2.0. +// Find it in module example.net/ambiguous/nested instead. diff --git a/libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.0.0.txt new file mode 100644 index 0000000..207e86a --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.0.0.txt @@ -0,0 +1,17 @@ +Written by hand. +Test module with a root package added in v1.1.0 +and a subpackage added in v1.2.0. + +-- .mod -- +module example.net/pkgadded + +go 1.16 +-- .info -- +{"Version":"v1.0.0"} +-- go.mod -- +module example.net/pkgadded + +go 1.16 +-- README.txt -- +We will add the package example.net/pkgadded in v1.1.0, +and example.net/pkgadded/subpkg in v1.2.0. diff --git a/libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.1.0.txt new file mode 100644 index 0000000..1c88de2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.1.0.txt @@ -0,0 +1,19 @@ +Written by hand. +Test module with a root package added in v1.1.0 +and a subpackage added in v1.2.0. + +-- .mod -- +module example.net/pkgadded + +go 1.16 +-- .info -- +{"Version":"v1.1.0"} +-- go.mod -- +module example.net/pkgadded + +go 1.16 +-- README.txt -- +We will add the package example.net/pkgadded/subpkg in v1.2.0. +-- pkgadded.go -- +// Package pkgadded was added in v1.1.0. +package pkgadded diff --git a/libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.2.0.txt b/libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.2.0.txt new file mode 100644 index 0000000..922951a --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.net_pkgadded_v1.2.0.txt @@ -0,0 +1,20 @@ +Written by hand. +Test module with a root package added in v1.1.0 +and a subpackage added in v1.2.0. + +-- .mod -- +module example.net/pkgadded + +go 1.16 +-- .info -- +{"Version":"v1.2.0"} +-- go.mod -- +module example.net/pkgadded + +go 1.16 +-- pkgadded.go -- +// Package pkgadded was added in v1.1.0. +package pkgadded +-- subpkg/subpkg.go -- +// Package subpkg was added in v1.2.0. +package subpkg diff --git a/libgo/go/cmd/go/testdata/script/README b/libgo/go/cmd/go/testdata/script/README index d658ceb..48e4055 100644 --- a/libgo/go/cmd/go/testdata/script/README +++ b/libgo/go/cmd/go/testdata/script/README @@ -29,7 +29,6 @@ Scripts also have access to these other environment variables: GOARCH=<target GOARCH> GOCACHE=<actual GOCACHE being used outside the test> GOEXE=<executable file suffix: .exe on Windows, empty on other systems> - GOEXPSTRING=<value of objabi.Expstring(), from GOEXPERIMENT when toolchain built> GOOS=<target GOOS> GOPATH=$WORK/gopath GOPROXY=<local module proxy serving from cmd/go/testdata/mod> @@ -103,6 +102,7 @@ The commands are: - cd dir Change to the given directory for future commands. + The directory must use slashes as path separator. - chmod perm path... Change the permissions of the files or directories named by the path arguments diff --git a/libgo/go/cmd/go/testdata/script/badgo.txt b/libgo/go/cmd/go/testdata/script/badgo.txt new file mode 100644 index 0000000..cf4e258 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/badgo.txt @@ -0,0 +1,50 @@ +go get example.net/badgo@v1.0.0 +go get example.net/badgo@v1.1.0 +go get example.net/badgo@v1.2.0 +go get example.net/badgo@v1.3.0 +go get example.net/badgo@v1.4.0 +go get example.net/badgo@v1.5.0 +! go get example.net/badgo@v1.6.0 +stderr 'invalid go version .X.Y.: must match format 1.23' + +-- go.mod -- +module m + +replace ( + example.net/badgo v1.0.0 => ./v1.0.0 + example.net/badgo v1.1.0 => ./v1.1.0 + example.net/badgo v1.2.0 => ./v1.2.0 + example.net/badgo v1.3.0 => ./v1.3.0 + example.net/badgo v1.4.0 => ./v1.4.0 + example.net/badgo v1.5.0 => ./v1.5.0 + example.net/badgo v1.6.0 => ./v1.6.0 +) + +-- v1.0.0/go.mod -- +module example.net/badgo +go 1.17.0 + +-- v1.1.0/go.mod -- +module example.net/badgo +go 1.17rc2 + +-- v1.2.0/go.mod -- +module example.net/badgo +go 1.17.1 + +-- v1.3.0/go.mod -- +module example.net/badgo +go v1.17.0 + +-- v1.4.0/go.mod -- +module example.net/badgo +go v1.17.0-rc.2 + +-- v1.5.0/go.mod -- +module example.net/badgo +go v1.17.1 + +-- v1.6.0/go.mod -- +module example.net/badgo +go X.Y + diff --git a/libgo/go/cmd/go/testdata/script/bug.txt b/libgo/go/cmd/go/testdata/script/bug.txt index f52250a..fc38f18 100644 --- a/libgo/go/cmd/go/testdata/script/bug.txt +++ b/libgo/go/cmd/go/testdata/script/bug.txt @@ -2,9 +2,11 @@ [!linux] skip [gccgo] skip +[short] skip go install -env BROWSER=$GOPATH/bin/browser +go build -o $TMPDIR/go ./go +env BROWSER=$GOPATH/bin/browser PATH=$TMPDIR:$PATH go bug exists $TMPDIR/browser grep '^go version' $TMPDIR/browser @@ -45,3 +47,13 @@ func main() { } } +-- go/main.go -- +package main + +import ( + "os" +) + +func main() { + os.Exit(1) +} diff --git a/libgo/go/cmd/go/testdata/script/build_arm.txt b/libgo/go/cmd/go/testdata/script/build_arm.txt new file mode 100644 index 0000000..ff2a364 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_arm.txt @@ -0,0 +1,13 @@ +[short] skip 'skipping cross-compile in short mode' + +env GOARCH=arm +env GOOS=linux +env GOARM=5 + +go build hello.go +! stderr 'unable to find math.a' + +-- hello.go -- +package main + +func main() {}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/build_cache_arch_mode.txt b/libgo/go/cmd/go/testdata/script/build_cache_arch_mode.txt new file mode 100644 index 0000000..931827f --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_cache_arch_mode.txt @@ -0,0 +1,21 @@ +# Issue 9737: verify that GOARM affects the computed build ID + +[short] skip + +# arm +env GOOS=linux +env GOARCH=arm +env GOARM=5 +go install mycmd +env GOARM=7 +stale mycmd + + +-- go.mod -- +module mycmd + +go 1.16 +-- x.go -- +package main + +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/build_cache_disabled.txt b/libgo/go/cmd/go/testdata/script/build_cache_disabled.txt new file mode 100644 index 0000000..68e2773 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_cache_disabled.txt @@ -0,0 +1,50 @@ +# The build cache is required to build anything. It also may be needed to +# initialize the build system, which is needed for commands like 'go env'. +# However, there are lots of commands the cache is not needed for, and we +# shouldn't require it when it won't be used. +# +# TODO(golang.org/issue/39882): commands below should work, too. +# * go clean -modcache +# * go env +# * go fix +# * go fmt +# * go generate +# * go get -d +# * go list (without -export or -compiled) + +env GOCACHE=off + +# Commands that don't completely load packages should work. +[!gccgo] go doc fmt +[!gccgo] stdout Printf + +[!gccgo] ! go tool compile -h +[!gccgo] stderr usage: + +go version +stdout '^go version' + + +# Module commands that don't load packages should work. +go mod init m +exists go.mod + +go mod edit -require rsc.io/quote@v1.5.2 + +go mod download rsc.io/quote + +go mod graph +stdout rsc.io/quote + +go mod verify + + +# Commands that load but don't build packages should work. +go fmt . + +[!gccgo] go doc . + +-- main.go -- +package main + +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/build_cd_gopath_different.txt b/libgo/go/cmd/go/testdata/script/build_cd_gopath_different.txt new file mode 100644 index 0000000..a7a4bf4 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_cd_gopath_different.txt @@ -0,0 +1,73 @@ +[gccgo] skip 'gccgo does not support -ldflags -X' +env GO111MODULE=off +go build run_go.go + +# Apply identity function to GOPATH +exec ./run_go$GOEXE $GOPATH/src/my.pkg/main $GOPATH IDENTITY build -o $WORK/tmp/a.exe -ldflags -X=my.pkg.Text=linkXworked +exec $WORK/tmp/a.exe +stderr 'linkXworked' +rm $WORK/tmp/a.exe + +[!windows] stop 'rest of the tests only apply to Windows' + +# Replace '\' with '/' in GOPATH +exec ./run_go$GOEXE $GOPATH/src/my.pkg/main $GOPATH REPLACE_SLASH build -o $WORK/tmp/a.exe -ldflags -X=my.pkg.Text=linkXworked +exec $WORK/tmp/a.exe +stderr 'linkXworked' +rm $WORK/tmp/a.exe + +# Apply identity function to GOPATH +exec ./run_go$GOEXE $GOPATH/src/my.pkg/main $GOPATH UPPER build -o $WORK/tmp/a.exe -ldflags -X=my.pkg.Text=linkXworked +exec $WORK/tmp/a.exe +stderr 'linkXworked' +rm $WORK/tmp/a.exe + +# Apply identity function to GOPATH +exec ./run_go$GOEXE $GOPATH/src/my.pkg/main $GOPATH LOWER build -o $WORK/tmp/a.exe -ldflags -X=my.pkg.Text=linkXworked +exec $WORK/tmp/a.exe +stderr 'linkXworked' +rm $WORK/tmp/a.exe + +-- run_go.go -- +package main + +import ( + "fmt" + "os" + "os/exec" + "strings" +) + +func main() { + dir := os.Args[1] + gopath := os.Args[2] + switch os.Args[3] { + case "IDENTITY": + case "REPLACE_SLASH": gopath = strings.ReplaceAll(gopath, `\`, `/`) + case "UPPER": gopath = strings.ToUpper(gopath) + case "LOWER": gopath = strings.ToLower(gopath) + default: fmt.Fprintln(os.Stderr, "bad op"); os.Exit(1) + } + cmd := exec.Command("go", os.Args[4:]...) + cmd.Dir = dir + cmd.Env = append(os.Environ(), "GOPATH="+gopath) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + +-- my.pkg/main/main.go -- +package main + +import "my.pkg" + +func main() { + println(pkg.Text) +} +-- my.pkg/pkg.go -- +package pkg + +var Text = "unset" diff --git a/libgo/go/cmd/go/testdata/script/build_cgo_consistent_results.txt b/libgo/go/cmd/go/testdata/script/build_cgo_consistent_results.txt new file mode 100644 index 0000000..88a24de --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_cgo_consistent_results.txt @@ -0,0 +1,23 @@ +[short] skip +[!cgo] skip + +[solaris] skip "skipping on Solaris; see golang.org/issue/13247" +[illumos] skip "skipping on Solaris; see golang.org/issue/13247" + +go build -o $WORK/exe1$GOEXE cgotest +go build -x -o $WORK/exe2$GOEXE cgotest + +# TODO(matloob): skip if stderr does not contain '-fdebug-prefix-map=\$WORK' + +cmp $WORK/exe1$GOEXE $WORK/exe2$GOEXE + +-- go.mod -- +module cgotest + +go 1.16 +-- m.go -- +package cgotest + +import "C" + +var _ C.int diff --git a/libgo/go/cmd/go/testdata/script/build_darwin_cc_arch.txt b/libgo/go/cmd/go/testdata/script/build_darwin_cc_arch.txt new file mode 100644 index 0000000..2b81b4c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_darwin_cc_arch.txt @@ -0,0 +1,24 @@ +# Test that we pass -arch flag to C compiler on Darwin (issue 43692). + +[!darwin] skip +[!cgo] skip + +# clear CC, in case user sets it +env CC= + +env CGO_ENABLED=1 + +env GOARCH=amd64 +go build -n -x c.go +stderr 'clang.*-arch x86_64' + +env GOARCH=arm64 +go build -n -x c.go +stderr 'clang.*-arch arm64' + +-- c.go -- +package main + +import "C" + +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/build_dash_n_cgo.txt b/libgo/go/cmd/go/testdata/script/build_dash_n_cgo.txt new file mode 100644 index 0000000..3f49ef6 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_dash_n_cgo.txt @@ -0,0 +1,18 @@ +# Tests golang.org/issue/14944 + +[!cgo] skip + +go build -n foo.go +! stderr 'os.Stat .* no such file or directory' # there shouldn't be a stat of the archive file + +-- foo.go -- +package main + +/* +#include <limits.h> +*/ +import "C" + +func main() { + println(C.INT_MAX) +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/build_dash_o_dev_null.txt b/libgo/go/cmd/go/testdata/script/build_dash_o_dev_null.txt new file mode 100644 index 0000000..e415fc2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_dash_o_dev_null.txt @@ -0,0 +1,13 @@ +# Issue #25579 + +[short] skip + +go build -o $devnull hello.go +! exists 'hello'$GOEXE + +-- hello.go -- +package main + +func main() { + println("hello, world") +} diff --git a/libgo/go/cmd/go/testdata/script/build_dash_x.txt b/libgo/go/cmd/go/testdata/script/build_dash_x.txt new file mode 100644 index 0000000..6fd5bbe1 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_dash_x.txt @@ -0,0 +1,49 @@ +[short] skip +[!cgo] skip + +[!exec:/usr/bin/env] skip +[!exec:bash] skip +[!exec:cat] skip + +mkdir $WORK/tmp/cache +env GOCACHE=$WORK/tmp/cache + +# Before building our test main.go, ensure that an up-to-date copy of +# runtime/cgo is present in the cache. If it isn't, the 'go build' step below +# will fail with "can't open import". See golang.org/issue/29004. +# +# (The fix in golang.org/issue/29004 didn't completely fix the underlying issue: +# cmd/go/internal/load adds a bunch of implicit dependencies +# based on various heuristics, and, due to a bug described in +# https://golang.org/issue/31544#issuecomment-490607180, +# those implicit dependencies are not added early enough during +# loading to properly affect the import graph.) +go build runtime/cgo + +go build -x -o main main.go +cp stderr commands.txt +exec cat header.txt commands.txt +cp stdout test.sh + +exec ./main +cmp stderr hello.txt +rm ./main + +exec /usr/bin/env bash -x test.sh +exec ./main +cmp stderr hello.txt + +grep '^WORK=(.*)\n' commands.txt + +-- main.go -- +package main + +import "C" + +func main() { + print("hello\n") +} +-- header.txt -- +set -e +-- hello.txt -- +hello diff --git a/libgo/go/cmd/go/testdata/script/build_exe.txt b/libgo/go/cmd/go/testdata/script/build_exe.txt new file mode 100644 index 0000000..a994d17 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_exe.txt @@ -0,0 +1,25 @@ +# go build with -o and -buildmode=exe should report an error on a non-main package. + +! go build -buildmode=exe -o out$GOEXE ./not_main +stderr '-buildmode=exe requires exactly one main package' +! exists out$GOEXE +! go build -buildmode=exe -o out$GOEXE ./main_one ./main_two +stderr '-buildmode=exe requires exactly one main package' +! exists out$GOEXE + +-- go.mod -- +module m + +go 1.16 +-- not_main/not_main.go -- +package not_main + +func F() {} +-- main_one/main_one.go -- +package main + +func main() {} +-- main_two/main_two.go -- +package main + +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/build_gopath_order.txt b/libgo/go/cmd/go/testdata/script/build_gopath_order.txt new file mode 100644 index 0000000..caf2502 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_gopath_order.txt @@ -0,0 +1,36 @@ +# golang.org/issue/14176#issuecomment-179895769 +# golang.org/issue/14192 +# -I arguments to compiler could end up not in GOPATH order, +# leading to unexpected import resolution in the compiler. + +env GO111MODULE=off +env GOPATH=$WORK/p1${:}$WORK/p2 +mkdir $WORK/p1/src/foo $WORK/p2/src/baz +mkdir $WORK/p2/pkg/${GOOS}_${GOARCH} $WORK/p1/src/bar +cp foo.go $WORK/p1/src/foo/foo.go +cp baz.go $WORK/p2/src/baz/baz.go +cp foo.a $WORK/p2/pkg/${GOOS}_${GOARCH}/foo.a +cp bar.go $WORK/p1/src/bar/bar.go + +go install -x bar + +# add in baz.a to the mix +mkdir $WORK/p1/pkg/${GOOS}_${GOARCH} +cp baz.a $WORK/p1/pkg/${GOOS}_${GOARCH}/baz.a +env GOPATH=$WORK/p1${:}$WORK/p2 +go install -x bar +env GOPATH=$WORK/p2${:}$WORK/p1 +go install -x bar + +-- foo.go -- +package foo +-- baz.go -- +package baz +-- foo.a -- +bad +-- baz.a -- +bad +-- bar.go -- +package bar +import _ "baz" +import _ "foo" diff --git a/libgo/go/cmd/go/testdata/script/build_i_deprecate.txt b/libgo/go/cmd/go/testdata/script/build_i_deprecate.txt new file mode 100644 index 0000000..71356e5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_i_deprecate.txt @@ -0,0 +1,24 @@ +# Check that deprecation warnings are printed when the -i flag is used. +# TODO(golang.org/issue/41696): remove the -i flag after Go 1.16, and this test. + +go build -n -i +stderr '^go build: -i flag is deprecated$' + +go install -n -i +stderr '^go install: -i flag is deprecated$' + +go test -n -i +stderr '^go test: -i flag is deprecated$' + + +# 'go clean -i' should not print a deprecation warning. +# It will continue working. +go clean -i . +! stderr . + +-- go.mod -- +module m + +go 1.16 +-- m.go -- +package m diff --git a/libgo/go/cmd/go/testdata/script/build_ignore_leading_bom.txt b/libgo/go/cmd/go/testdata/script/build_ignore_leading_bom.txt new file mode 100644 index 0000000..37141f3 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_ignore_leading_bom.txt @@ -0,0 +1,27 @@ +# Per https://golang.org/ref/spec#Source_code_representation: +# a compiler may ignore a UTF-8-encoded byte order mark (U+FEFF) +# if it is the first Unicode code point in the source text. + +go list -f 'Imports: {{.Imports}} EmbedFiles: {{.EmbedFiles}}' . +stdout '^Imports: \[embed m/hello\] EmbedFiles: \[.*file\]$' + +-- go.mod -- +module m + +go 1.16 +-- m.go -- +package main + +import ( + _ "embed" + + "m/hello" +) + +//go:embed file +var s string + +-- hello/hello.go -- +package hello + +-- file -- diff --git a/libgo/go/cmd/go/testdata/script/build_import_comment.txt b/libgo/go/cmd/go/testdata/script/build_import_comment.txt new file mode 100644 index 0000000..b500340 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_import_comment.txt @@ -0,0 +1,68 @@ +# Test in GOPATH mode first. +env GO111MODULE=off +cd m + +# Import comment matches +go build -n works.go + +# Import comment mismatch +! go build -n wrongplace.go +stderr 'wrongplace expects import "my/x"' + +# Import comment syntax error +! go build -n bad.go +stderr 'cannot parse import comment' + +# Import comment conflict +! go build -n conflict.go +stderr 'found import comments' + + +# Test in module mode. +# We ignore import comments, so these commands should succeed. +env GO111MODULE=on + +# Import comment matches +go build -n works.go + +# Import comment mismatch +go build -n wrongplace.go + +# Import comment syntax error +go build -n bad.go + +# Import comment conflict +go build -n conflict.go + +-- m/go.mod -- +module m + +go 1.16 +-- m/bad.go -- +package p + +import "m/bad" +-- m/conflict.go -- +package p + +import "m/conflict" +-- m/works.go -- +package p + +import _ "m/works/x" +-- m/wrongplace.go -- +package p + +import "m/wrongplace" +-- m/bad/bad.go -- +package bad // import +-- m/conflict/a.go -- +package conflict // import "a" +-- m/conflict/b.go -- +package conflict /* import "b" */ +-- m/works/x/x.go -- +package x // import "m/works/x" +-- m/works/x/x1.go -- +package x // important! not an import comment +-- m/wrongplace/x.go -- +package x // import "my/x" diff --git a/libgo/go/cmd/go/testdata/script/build_import_cycle.txt b/libgo/go/cmd/go/testdata/script/build_import_cycle.txt new file mode 100644 index 0000000..16e4e87 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_import_cycle.txt @@ -0,0 +1,13 @@ +# mod_import_cycle covers this error in module mode. +env GO111MODULE=off + +! go build selfimport +stderr -count=1 'import cycle not allowed' + +go list -e -f '{{.Error}}' selfimport # Don't hang forever +stdout -count=1 'import cycle not allowed' + +-- selfimport/selfimport.go -- +package selfimport + +import "selfimport" diff --git a/libgo/go/cmd/go/testdata/script/build_internal.txt b/libgo/go/cmd/go/testdata/script/build_internal.txt new file mode 100644 index 0000000..25aa18c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_internal.txt @@ -0,0 +1,63 @@ +# Test internal package errors are handled +cd testinternal3 +go list . +stdout 'testinternal3' + +# Test internal cache +cd ../testinternal4 +! go build testinternal4/p +stderr 'internal' + +# Test internal packages outside GOROOT are respected +cd ../testinternal2 +! go build -v . +stderr 'p\.go:3:8: use of internal package .*internal/w not allowed' + +[gccgo] skip # gccgo does not have GOROOT +cd ../testinternal +! go build -v . +stderr 'p\.go:3:8: use of internal package net/http/internal not allowed' + +-- testinternal/go.mod -- +module testinternal + +go 1.16 +-- testinternal/p.go -- +package p + +import _ "net/http/internal" +-- testinternal2/go.mod -- +module testinternal2 + +go 1.16 +-- testinternal2/p.go -- +package p + +import _ "./x/y/z/internal/w" +-- testinternal2/x/y/z/internal/w/w.go -- +package w +-- testinternal3/go.mod -- +module testinternal3 + +go 1.16 +-- testinternal3/t.go -- +package t + +import _ "internal/does-not-exist" +-- testinternal4/go.mod -- +module testinternal4 + +go 1.16 +-- testinternal4/p/p.go -- +package p + +import ( + _ "testinternal4/q/internal/x" + _ "testinternal4/q/j" +) +-- testinternal4/q/internal/x/x.go -- +package x +-- testinternal4/q/j/j.go -- +package j + +import _ "testinternal4/q/internal/x" diff --git a/libgo/go/cmd/go/testdata/script/build_issue6480.txt b/libgo/go/cmd/go/testdata/script/build_issue6480.txt new file mode 100644 index 0000000..cf1e9ea --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_issue6480.txt @@ -0,0 +1,128 @@ +# "go test -c -test.bench=XXX errors" should not hang. +# "go test -c" should also produce reproducible binaries. +# "go test -c" should also appear to write a new binary every time, +# even if it's really just updating the mtime on an existing up-to-date binary. + +[gccgo] skip +[short] skip + +# Install some commands to compare mtimes +env GOBIN=$WORK/tmp/bin +go install m/now m/mtime m/before + +# Initial builds +go test -c -test.bench=XXX errors +go test -c -o errors2.test errors +cmp errors.test$GOEXE errors2.test # // errors2.test has no exeSuffix because -o above doesn't have it + +# Check errors.test mtime is updated +exec $GOBIN/now +cp stdout start_time.txt +go test -x -c -test.bench=XXX errors +! stderr '[\\/]link|gccgo' # make sure up-to-date test binary is not relinked +exec $GOBIN/mtime errors.test$GOEXE +cp stdout errors1_mod_time.txt +exec $GOBIN/before start_time.txt errors1_mod_time.txt +rm start_time.txt errors1_mod_time.txt + +# Check errors2.test mtime is updated +exec $GOBIN/now +cp stdout start_time.txt +go test -x -c -o errors2.test errors +! stderr '[\\/]link|gccgo' # make sure up-to-date test binary is not relinked +exec $GOBIN/mtime errors2.test +cp stdout errors2_mod_time.txt +exec $GOBIN/before start_time.txt errors2_mod_time.txt + +-- go.mod -- +module m + +go 1.16 +-- now/now.go -- +// Writes time.Now() to a file +package main + +import ( + "encoding/json" + "fmt" + "os" + "time" +) + +func main() { + if err := json.NewEncoder(os.Stdout).Encode(time.Now()); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} +-- mtime/mtime.go -- +package main + +import ( + "encoding/json" + "fmt" + "os" +) + +func main() { + info, err := os.Stat(os.Args[1]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if err := json.NewEncoder(os.Stdout).Encode(info.ModTime()); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} +-- before/before.go -- +package main + +import ( + "encoding/json" + "fmt" + "os" + "time" +) + +func truncateLike(t, p time.Time) time.Time { + nano := p.UnixNano() + d := 1 * time.Nanosecond + for nano%int64(d) == 0 && d < 1*time.Second { + d *= 10 + } + for nano%int64(d) == 0 && d < 2*time.Second { + d *= 2 + } + return t.Truncate(d) +} + +func main() { + var t1 time.Time + b1, err := os.ReadFile(os.Args[1]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if err := json.Unmarshal(b1, &t1); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + var t2 time.Time + b2, err := os.ReadFile(os.Args[2]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if err := json.Unmarshal(b2, &t2); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + t1 = truncateLike(t1, t2) + if !t1.Before(t2) { + fmt.Fprintf(os.Stderr, "time in %v (%v) is not before time in %v (%v)", os.Args[1], t1, os.Args[2], t2) + os.Exit(1) + } +} diff --git a/libgo/go/cmd/go/testdata/script/build_link_x_import_path_escape.txt b/libgo/go/cmd/go/testdata/script/build_link_x_import_path_escape.txt new file mode 100644 index 0000000..f1de1e4 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_link_x_import_path_escape.txt @@ -0,0 +1,22 @@ +[gccgo] skip 'gccgo does not support -ldflags -X' + +go build -o linkx$GOEXE -ldflags -X=my.pkg.Text=linkXworked my.pkg/main +exec ./linkx$GOEXE +stderr '^linkXworked$' + +-- go.mod -- +module my.pkg + +go 1.16 +-- main/main.go -- +package main + +import "my.pkg" + +func main() { + println(pkg.Text) +} +-- pkg.go -- +package pkg + +var Text = "unset" diff --git a/libgo/go/cmd/go/testdata/script/build_n_cgo.txt b/libgo/go/cmd/go/testdata/script/build_n_cgo.txt new file mode 100644 index 0000000..7aa77ae --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_n_cgo.txt @@ -0,0 +1,17 @@ +[!cgo] skip + +# Test that nothing is prepended to $WORK path prefix. +# See issue golang.org/issue/37012. +go build -n +! stderr '[/\\]\$WORK' + +-- go.mod -- +module m + +go 1.16 +-- main.go -- +package main + +import "C" + +var _ C.int diff --git a/libgo/go/cmd/go/testdata/script/build_no_go.txt b/libgo/go/cmd/go/testdata/script/build_no_go.txt new file mode 100644 index 0000000..b61d752 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_no_go.txt @@ -0,0 +1,41 @@ +! go build ./empty/test +stderr 'no non-test Go files in ' + +! go build ./empty/xtest +stderr 'no non-test Go files in ' + +! go build ./empty/testxtest +stderr 'no non-test Go files in ' + +! go build ./exclude +stderr 'build constraints exclude all Go files in ' + +! go build ./exclude/ignore +stderr 'no Go files in ' + +! go build ./exclude/empty +stderr 'no Go files in ' + +-- go.mod -- +module m + +go 1.16 +-- empty/test/test_test.go -- +package p +-- empty/testxtest/test_test.go -- +package p +-- empty/testxtest/xtest_test.go -- +package p_test +-- empty/xtest/xtest_test.go -- +package p_test +-- exclude/empty/x.txt -- +-- exclude/ignore/_x.go -- +package x +-- exclude/x.go -- +// +build linux,!linux + +package x +-- exclude/x_linux.go -- +// +build windows + +package x diff --git a/libgo/go/cmd/go/testdata/script/build_output.txt b/libgo/go/cmd/go/testdata/script/build_output.txt new file mode 100644 index 0000000..1e82950 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_output.txt @@ -0,0 +1,117 @@ +[gccgo] skip 'gccgo has no standard packages' +[short] skip + +[!windows] env NONEXE='.exe' +[windows] env NONEXE='' + +env GOBIN=$WORK/tmp/bin +go install m/isarchive & + +go build x.go +exists -exec x$GOEXE +rm x$GOEXE +! exists x$NONEXE + +go build -o myprog x.go +! exists x +! exists x.exe +exists -exec myprog +! exists myprogr.exe + +! exists bin +go build -o bin/x x.go +exists -exec bin/x +rm bin + +! exists bin +go build -o bin/ x.go +exists -exec bin/x$GOEXE +rm bin + +[windows] ! exists bin +[windows] go build -o bin\x x.go +[windows] exists -exec bin\x +[windows] rm bin + +[windows] ! exists bin +[windows] go build -o bin\ x.go +[windows] exists -exec bin\x.exe +[windows] rm bin + +! exists bin +mkdir bin +go build -o bin x.go +exists -exec bin/x$GOEXE +rm bin + +go build p.go +! exists p +! exists p.a +! exists p.o +! exists p.exe + +wait # for isarchive + +go build -o p.a p.go +exists p.a +exec $GOBIN/isarchive p.a + +go build cmd/gofmt +exists -exec gofmt$GOEXE +rm gofmt$GOEXE +! exists gofmt$NONEXE + +go build -o mygofmt cmd/gofmt +exists -exec mygofmt +! exists mygofmt.exe +! exists gofmt +! exists gofmt.exe + +go build sync/atomic +! exists atomic +! exists atomic.exe + +go build -o myatomic.a sync/atomic +exists myatomic.a +exec $GOBIN/isarchive myatomic.a +! exists atomic +! exists atomic.a +! exists atomic.exe + +! go build -o whatever cmd/gofmt sync/atomic +stderr 'multiple packages' + +-- go.mod -- +module m + +go 1.16 +-- x.go -- +package main + +func main() {} +-- p.go -- +package p +-- isarchive/isarchive.go -- +package main + +import ( + "bytes" + "fmt" + "io" + "os" +) + +func main() { + f, err := os.Open(os.Args[1]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + buf := make([]byte, 100) + io.ReadFull(f, buf) + f.Close() + if !bytes.HasPrefix(buf, []byte("!<arch>\n")) { + fmt.Fprintf(os.Stderr, "file %s exists but is not an archive\n", os.Args[1]) + os.Exit(1) + } +} diff --git a/libgo/go/cmd/go/testdata/script/build_overlay.txt b/libgo/go/cmd/go/testdata/script/build_overlay.txt new file mode 100644 index 0000000..2932b94 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_overlay.txt @@ -0,0 +1,308 @@ +[short] skip + +# Test building in overlays. +# TODO(#39958): add a test case where the destination file in the replace map +# isn't a go file. Either completely exclude that case in fs.IsDirWithGoFiles +# if the compiler doesn't allow it, or test that it works all the way. +# TODO(#39958): add a test that both gc and gccgo assembly files can include .h +# files. + +# The main package (m) is contained in an overlay. It imports m/dir2 which has one +# file in an overlay and one file outside the overlay, which in turn imports m/dir, +# which only has source files in the overlay. + +cd m + +! go build . +go build -overlay overlay.json -o main$GOEXE . +exec ./main$goexe +stdout '^hello$' + +go build -overlay overlay.json -o print_abspath$GOEXE ./printpath +exec ./print_abspath$GOEXE +stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go + +go build -overlay overlay.json -o print_trimpath$GOEXE -trimpath ./printpath +exec ./print_trimpath$GOEXE +stdout ^m[/\\]printpath[/\\]main.go + +go build -overlay overlay.json -o print_trimpath_two_files$GOEXE printpath/main.go printpath/other.go +exec ./print_trimpath_two_files$GOEXE +stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go +stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]other.go + +go build -overlay overlay.json -o main_cgo_replace$GOEXE ./cgo_hello_replace +exec ./main_cgo_replace$GOEXE +stdout '^hello cgo\r?\n' + +go build -overlay overlay.json -o main_cgo_quote$GOEXE ./cgo_hello_quote +exec ./main_cgo_quote$GOEXE +stdout '^hello cgo\r?\n' + +go build -overlay overlay.json -o main_cgo_angle$GOEXE ./cgo_hello_angle +exec ./main_cgo_angle$GOEXE +stdout '^hello cgo\r?\n' + +go build -overlay overlay.json -o main_call_asm$GOEXE ./call_asm +exec ./main_call_asm$GOEXE +! stdout . + +# Change the contents of a file in the overlay and ensure that makes the target stale +go install -overlay overlay.json ./test_cache +go list -overlay overlay.json -f '{{.Stale}}' ./test_cache +stdout '^false$' +cp overlay/test_cache_different.go overlay/test_cache.go +go list -overlay overlay.json -f '{{.Stale}}' ./test_cache +stdout '^true$' + +go list -compiled -overlay overlay.json -f '{{range .CompiledGoFiles}}{{. | printf "%s\n"}}{{end}}' ./cgo_hello_replace +cp stdout compiled_cgo_sources.txt +go run ../print_line_comments.go compiled_cgo_sources.txt +stdout $GOPATH[/\\]src[/\\]m[/\\]cgo_hello_replace[/\\]cgo_hello_replace.go +! stdout $GOPATH[/\\]src[/\\]m[/\\]overlay[/\\]hello.c + +# Run same tests but with gccgo. +env GO111MODULE=off +[!exec:gccgo] stop + +! go build -compiler=gccgo . +go build -compiler=gccgo -overlay overlay.json -o main_gccgo$GOEXE . +exec ./main_gccgo$goexe +stdout '^hello$' + +go build -compiler=gccgo -overlay overlay.json -o print_abspath_gccgo$GOEXE ./printpath +exec ./print_abspath_gccgo$GOEXE +stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go + +go build -compiler=gccgo -overlay overlay.json -o print_trimpath_gccgo$GOEXE -trimpath ./printpath +exec ./print_trimpath_gccgo$GOEXE +stdout ^\.[/\\]printpath[/\\]main.go + + +go build -compiler=gccgo -overlay overlay.json -o main_cgo_replace_gccgo$GOEXE ./cgo_hello_replace +exec ./main_cgo_replace_gccgo$GOEXE +stdout '^hello cgo\r?\n' + +go build -compiler=gccgo -overlay overlay.json -o main_cgo_quote_gccgo$GOEXE ./cgo_hello_quote +exec ./main_cgo_quote_gccgo$GOEXE +stdout '^hello cgo\r?\n' + +go build -compiler=gccgo -overlay overlay.json -o main_cgo_angle_gccgo$GOEXE ./cgo_hello_angle +exec ./main_cgo_angle_gccgo$GOEXE +stdout '^hello cgo\r?\n' + +go build -compiler=gccgo -overlay overlay.json -o main_call_asm_gccgo$GOEXE ./call_asm +exec ./main_call_asm_gccgo$GOEXE +! stdout . + + +-- m/go.mod -- +// TODO(matloob): how do overlays work with go.mod (especially if mod=readonly) +module m + +go 1.16 + +-- m/dir2/h.go -- +package dir2 + +func PrintMessage() { + printMessage() +} +-- m/dir/foo.txt -- +The build action code currently expects the package directory +to exist, so it can run the compiler in that directory. +TODO(matloob): Remove this requirement. +-- m/printpath/about.txt -- +the actual code is in the overlay +-- m/overlay.json -- +{ + "Replace": { + "f.go": "overlay/f.go", + "dir/g.go": "overlay/dir_g.go", + "dir2/i.go": "overlay/dir2_i.go", + "printpath/main.go": "overlay/printpath.go", + "printpath/other.go": "overlay2/printpath2.go", + "call_asm/asm_gc.s": "overlay/asm_gc.s", + "call_asm/asm_gccgo.s": "overlay/asm_gccgo.s", + "test_cache/main.go": "overlay/test_cache.go", + "cgo_hello_replace/cgo_header.h": "overlay/cgo_head.h", + "cgo_hello_replace/hello.c": "overlay/hello.c", + "cgo_hello_quote/cgo_hello.go": "overlay/cgo_hello_quote.go", + "cgo_hello_quote/cgo_header.h": "overlay/cgo_head.h", + "cgo_hello_angle/cgo_hello.go": "overlay/cgo_hello_angle.go", + "cgo_hello_angle/cgo_header.h": "overlay/cgo_head.h" + } +} +-- m/cgo_hello_replace/cgo_hello_replace.go -- +package main + +// #include "cgo_header.h" +import "C" + +func main() { + C.say_hello() +} +-- m/cgo_hello_replace/cgo_header.h -- + // Test that this header is replaced with one that has the proper declaration. +void say_goodbye(); + +-- m/cgo_hello_replace/hello.c -- +#include <stdio.h> + +void say_goodbye() { puts("goodbye cgo\n"); fflush(stdout); } + +-- m/overlay/f.go -- +package main + +import "m/dir2" + +func main() { + dir2.PrintMessage() +} +-- m/call_asm/main.go -- +package main + +func foo() // There will be a "missing function body" error if the assembly file isn't found. + +func main() { + foo() +} +-- m/overlay/dir_g.go -- +package dir + +import "fmt" + +func PrintMessage() { + fmt.Println("hello") +} +-- m/overlay/printpath.go -- +package main + +import ( + "fmt" + "path/filepath" + "runtime" +) + +func main() { + _, file, _, _ := runtime.Caller(0) + + // Since https://golang.org/cl/214286, the runtime's debug paths are + // slash-separated regardless of platform, so normalize them to system file + // paths. + fmt.Println(filepath.FromSlash(file)) +} +-- m/overlay2/printpath2.go -- +package main + +import ( + "fmt" + "path/filepath" + "runtime" +) + +func init() { + _, file, _, _ := runtime.Caller(0) + fmt.Println(filepath.FromSlash(file)) +} +-- m/overlay/dir2_i.go -- +package dir2 + +import "m/dir" + +func printMessage() { + dir.PrintMessage() +} +-- m/overlay/cgo_hello_quote.go -- +package main + +// #include "cgo_header.h" +import "C" + +func main() { + C.say_hello() +} +-- m/overlay/cgo_hello_angle.go -- +package main + +// #include <cgo_header.h> +import "C" + +func main() { + C.say_hello() +} +-- m/overlay/cgo_head.h -- +void say_hello(); +-- m/overlay/hello.c -- +#include <stdio.h> + +void say_hello() { puts("hello cgo\n"); fflush(stdout); } +-- m/overlay/asm_gc.s -- +// +build gc + +TEXT ·foo(SB),0,$0 + RET + +-- m/overlay/asm_gccgo.s -- +// +build gccgo + +.globl main.foo +.text +main.foo: + ret + +-- m/overlay/test_cache.go -- +package foo + +import "fmt" + +func bar() { + fmt.Println("something") +} +-- m/overlay/test_cache_different.go -- +package foo + +import "fmt" + +func bar() { + fmt.Println("different") +} +-- m/cgo_hello_quote/hello.c -- +#include <stdio.h> + +void say_hello() { puts("hello cgo\n"); fflush(stdout); } +-- m/cgo_hello_angle/hello.c -- +#include <stdio.h> + +void say_hello() { puts("hello cgo\n"); fflush(stdout); } + +-- print_line_comments.go -- +package main + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "strings" +) + +func main() { + compiledGoFilesArg := os.Args[1] + b, err := ioutil.ReadFile(compiledGoFilesArg) + if err != nil { + log.Fatal(err) + } + compiledGoFiles := strings.Split(strings.TrimSpace(string(b)), "\n") + for _, f := range compiledGoFiles { + b, err := ioutil.ReadFile(f) + if err != nil { + log.Fatal(err) + } + for _, line := range strings.Split(string(b), "\n") { + if strings.HasPrefix(line, "#line") || strings.HasPrefix(line, "//line") { + fmt.Println(line) + } + } + } +} diff --git a/libgo/go/cmd/go/testdata/script/build_patterns_outside_gopath.txt b/libgo/go/cmd/go/testdata/script/build_patterns_outside_gopath.txt new file mode 100644 index 0000000..6a600cf --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_patterns_outside_gopath.txt @@ -0,0 +1,36 @@ +# Tests issue #18778 +[short] skip + +cd pkgs + +env GO111MODULE=off +go build ./... +! stdout . +go test ./... +stdout '^ok' +go list ./... +stdout 'pkgs$' +stdout 'pkgs/a' + +-- pkgs/go.mod -- +module pkgs + +go 1.16 +-- pkgs/a.go -- +package x +-- pkgs/a_test.go -- +package x_test + +import "testing" + +func TestX(t *testing.T) { +} +-- pkgs/a/a.go -- +package a +-- pkgs/a/a_test.go -- +package a_test + +import "testing" + +func TestA(t *testing.T) { +} diff --git a/libgo/go/cmd/go/testdata/script/build_plugin_non_main.txt b/libgo/go/cmd/go/testdata/script/build_plugin_non_main.txt new file mode 100644 index 0000000..e0bbbef --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_plugin_non_main.txt @@ -0,0 +1,13 @@ +# Plugins are not supported on all platforms. +[!buildmode:plugin] skip + +go build -n testdep +! go build -buildmode=plugin testdep +stderr '-buildmode=plugin requires exactly one main package' + +-- go.mod -- +module testdep + +go 1.16 +-- testdep.go -- +package p diff --git a/libgo/go/cmd/go/testdata/script/build_tag_goexperiment.txt b/libgo/go/cmd/go/testdata/script/build_tag_goexperiment.txt new file mode 100644 index 0000000..bee218f --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_tag_goexperiment.txt @@ -0,0 +1,31 @@ +[short] skip +# Reset all experiments so fieldtrack is definitely off. +env GOEXPERIMENT=none +go run m +stderr 'fieldtrack off' +# Turn fieldtrack on. +env GOEXPERIMENT=none,fieldtrack +go run m +stderr 'fieldtrack on' + +-- ft_off.go -- +// +build !goexperiment.fieldtrack + +package main + +func main() { + println("fieldtrack off") +} + +-- ft_on.go -- +// +build goexperiment.fieldtrack + +package main + +func main() { + println("fieldtrack on") +} + +-- go.mod -- +module m +go 1.14 diff --git a/libgo/go/cmd/go/testdata/script/build_tags_no_comma.txt b/libgo/go/cmd/go/testdata/script/build_tags_no_comma.txt new file mode 100644 index 0000000..f3eb282 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_tags_no_comma.txt @@ -0,0 +1,4 @@ +[gccgo] skip 'gccgo has no standard packages' +go build -tags 'tag1 tag2' math +! go build -tags 'tag1,tag2 tag3' math +stderr 'space-separated list contains comma'
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/build_test_only.txt b/libgo/go/cmd/go/testdata/script/build_test_only.txt new file mode 100644 index 0000000..8693a80 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_test_only.txt @@ -0,0 +1,19 @@ +# Named explicitly, test-only packages should be reported as +# unbuildable/uninstallable, even if there is a wildcard also matching. +! go build m/testonly m/testonly... +stderr 'no non-test Go files in' +! go install ./testonly +stderr 'no non-test Go files in' + +# Named through a wildcard, the test-only packages should be silently ignored. +go build m/testonly... +go install ./testonly... + +-- go.mod -- +module m + +go 1.16 +-- testonly/t_test.go -- +package testonly +-- testonly2/t.go -- +package testonly2 diff --git a/libgo/go/cmd/go/testdata/script/build_trimpath_cgo.txt b/libgo/go/cmd/go/testdata/script/build_trimpath_cgo.txt new file mode 100644 index 0000000..3187b4d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_trimpath_cgo.txt @@ -0,0 +1,184 @@ +# This test builds a cgo binary and verifies the source directory path +# does not appear in the binary, either literally or in compressed DWARF. +# TODO(golang.org/issue/36072): ideally we should build a binary from identical +# sources in different directories and verify the binary and all intermediate +# files are identical. + +[short] skip +[!cgo] skip + +# Check that the source path appears when -trimpath is not used. +go build -o hello.exe . +grep -q gopath[/\\]src hello.exe +go run ./list-dwarf hello.exe +stdout gopath[/\\]src + +# Check that the source path does not appear when -trimpath is used. +[aix] stop # can't inspect XCOFF binaries +go build -trimpath -o hello.exe . +! grep -q gopath[/\\]src hello.exe +go run ./list-dwarf hello.exe +! stdout gopath/src + + +# Do the above, with the cgo (but not .c) sources in an overlay +# Check that the source path appears when -trimpath is not used. +mkdir $WORK/overlay +cp hello.go $WORK/overlay/hello.go +mkdir hello_overlay +cp hello.c hello_overlay/hello.c +go build -overlay overlay.json -o hello_overlay.exe ./hello_overlay +grep -q gopath[/\\]src hello_overlay.exe +! grep -q $WORK[/\\]overlay hello_overlay.exe +go run ./list-dwarf hello_overlay.exe +stdout gopath[/\\]src +! stdout $WORK[/\\]overlay + +# Check that the source path does not appear when -trimpath is used. +go build -overlay overlay.json -trimpath -o hello_overlay.exe ./hello_overlay +! grep -q gopath[/\\]src hello_overlay.exe +! grep -q $WORK[/\\]overlay hello_overlay.exe +go run ./list-dwarf hello_overlay.exe +! stdout gopath/src +! stdout $WORK[/\\]overlay + +-- go.mod -- +module m + +go 1.14 +-- overlay.json -- +{ + "Replace": { + "hello_overlay/hello.go": "../../overlay/hello.go" + } +} +-- hello.c -- +#include <stdio.h> + +void say_hello() { puts("Hello, world!\n"); } + +-- hello.go -- +package main + +// void say_hello(); +import "C" + +func main() { + C.say_hello() +} + +-- list-dwarf/list-dwarf.go -- +package main + +import ( + "debug/dwarf" + "fmt" + "io" + "log" + "os" + "sort" +) + +func main() { + files, err := run(os.Args[1]) + if err != nil { + log.Fatal(err) + } + for _, file := range files { + fmt.Println(file) + } +} + +func run(exePath string) ([]string, error) { + dwarfData, err := readDWARF(exePath) + if err != nil { + return nil, err + } + + dwarfReader := dwarfData.Reader() + files := make(map[string]bool) + for { + e, err := dwarfReader.Next() + if err != nil { + return nil, err + } + if e == nil { + break + } + lr, err := dwarfData.LineReader(e) + if err != nil { + return nil, err + } + if lr == nil { + continue + } + + var le dwarf.LineEntry + for { + if err := lr.Next(&le); err != nil { + if err == io.EOF { + break + } + return nil, err + } + files[le.File.Name] = true + } + } + + sortedFiles := make([]string, 0, len(files)) + for file := range files { + sortedFiles = append(sortedFiles, file) + } + sort.Strings(sortedFiles) + return sortedFiles, nil +} +-- list-dwarf/read_darwin.go -- +package main + +import ( + "debug/dwarf" + "debug/macho" +) + +func readDWARF(exePath string) (*dwarf.Data, error) { + machoFile, err := macho.Open(exePath) + if err != nil { + return nil, err + } + defer machoFile.Close() + return machoFile.DWARF() +} +-- list-dwarf/read_elf.go -- +// +build android dragonfly freebsd illumos linux netbsd openbsd solaris + +package main + +import ( + "debug/dwarf" + "debug/elf" +) + +func readDWARF(exePath string) (*dwarf.Data, error) { + elfFile, err := elf.Open(exePath) + if err != nil { + return nil, err + } + defer elfFile.Close() + return elfFile.DWARF() +} +-- list-dwarf/read_windows.go -- +package main + +import ( + "debug/dwarf" + "debug/pe" +) + +func readDWARF(exePath string) (*dwarf.Data, error) { + peFile, err := pe.Open(exePath) + if err != nil { + return nil, err + } + defer peFile.Close() + return peFile.DWARF() +} diff --git a/libgo/go/cmd/go/testdata/script/build_unsupported_goos.txt b/libgo/go/cmd/go/testdata/script/build_unsupported_goos.txt new file mode 100644 index 0000000..d61e420 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_unsupported_goos.txt @@ -0,0 +1,6 @@ +[gccgo] skip # gccgo assumes cross-compilation is always possible + +env GOOS=windwos + +! go build -n exclude +stderr 'unsupported GOOS/GOARCH pair'
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/build_vendor.txt b/libgo/go/cmd/go/testdata/script/build_vendor.txt new file mode 100644 index 0000000..f430ff2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_vendor.txt @@ -0,0 +1,42 @@ +# Build +env GO111MODULE=off +go build vend/x +! stdout . +! stderr . + +-- vend/dir1/dir1.go -- +package dir1 +-- vend/subdir/bad.go -- +package subdir + +import _ "r" +-- vend/subdir/good.go -- +package subdir + +import _ "p" +-- vend/vendor/p/p.go -- +package p +-- vend/vendor/q/q.go -- +package q +-- vend/vendor/vend/dir1/dir2/dir2.go -- +package dir2 +-- vend/x/invalid/invalid.go -- +package invalid + +import "vend/x/invalid/vendor/foo" +-- vend/x/vendor/p/p/p.go -- +package p + +import _ "notfound" +-- vend/x/vendor/p/p.go -- +package p +-- vend/x/vendor/r/r.go -- +package r +-- vend/x/x.go -- +package x + +import _ "p" +import _ "q" +import _ "r" +import _ "vend/dir1" // not vendored +import _ "vend/dir1/dir2" // vendored diff --git a/libgo/go/cmd/go/testdata/script/cgo_asm_error.txt b/libgo/go/cmd/go/testdata/script/cgo_asm_error.txt new file mode 100644 index 0000000..7aaa713 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cgo_asm_error.txt @@ -0,0 +1,25 @@ +[!cgo] skip + +# Test that cgo package can't contain a go assembly file. + +# Ensure the build fails and reports that the package has a Go assembly file. +! go build cgoasm +stderr 'package using cgo has Go assembly file' + +-- go.mod -- +module cgoasm + +go 1.16 +-- p.go -- +package p + +/* +// hi +*/ +import "C" + +func F() {} +-- p.s -- +TEXT asm(SB),$0 + RET + diff --git a/libgo/go/cmd/go/testdata/script/cgo_bad_directives.txt b/libgo/go/cmd/go/testdata/script/cgo_bad_directives.txt new file mode 100644 index 0000000..6bf3beb --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cgo_bad_directives.txt @@ -0,0 +1,129 @@ +[!cgo] skip +[short] skip + +cp x.go.txt x.go + +# Only allow //go:cgo_ldflag .* in cgo-generated code +[gc] cp x_gc.go.txt x.go +[gc] ! go build x +[gc] stderr '//go:cgo_ldflag .* only allowed in cgo-generated code' + +# Ignore _* files +rm x.go +! go build . +stderr 'no Go files' +cp cgo_yy.go.txt _cgo_yy.go +! go build . +stderr 'no Go files' #_* files are ignored... + +[gc] ! go build _cgo_yy.go # ... but if forced, the comment is rejected +# Actually, today there is a separate issue that _ files named +# on the command line are ignored. Once that is fixed, +# we want to see the cgo_ldflag error. +[gc] stderr '//go:cgo_ldflag only allowed in cgo-generated code|no Go files' + +rm _cgo_yy.go + +# Reject #cgo CFLAGS: -fplugin=foo.so +cp x.go.txt x.go +cp y_fplugin.go.txt y.go +! go build x +stderr 'invalid flag in #cgo CFLAGS: -fplugin=foo.so' + +# Reject #cgo CFLAGS: -lbar -fplugin=foo.so +cp y_lbar_fplugin.go.txt y.go +! go build x +stderr 'invalid flag in #cgo CFLAGS: -fplugin=foo.so' + +# Reject #cgo pkg-config: -foo +cp y_pkgconfig_dash_foo.txt y.go +! go build x +stderr 'invalid pkg-config package name: -foo' + +# Reject #cgo pkg-config: @foo +cp y_pkgconfig_at_foo.txt y.go +! go build x +stderr 'invalid pkg-config package name: @foo' + +# Reject #cgo CFLAGS: @foo +cp y_cflags_at_foo.txt y.go +! go build x +stderr 'invalid flag in #cgo CFLAGS: @foo' + +# Reject #cgo CFLAGS: -D +cp y_cflags_dash_d.txt y.go +! go build x +stderr 'invalid flag in #cgo CFLAGS: -D without argument' + +# Note that -I @foo is allowed because we rewrite it into -I /path/to/src/@foo +# before the check is applied. There's no such rewrite for -D. + +# Reject #cgo CFLAGS: -D @foo +cp y_cflags_dash_d_space_at_foo.txt y.go +! go build x +stderr 'invalid flag in #cgo CFLAGS: -D @foo' + +# Reject #cgo CFLAGS -D@foo +cp y_cflags_dash_d_at_foo.txt y.go +! go build x +stderr 'invalid flag in #cgo CFLAGS: -D@foo' + +# Check for CFLAGS in commands +env CGO_CFLAGS=-D@foo +cp y_no_cflags.txt y.go +go build -n x +stderr '-D@foo' + +-- go.mod -- +module x + +go 1.16 +-- x_gc.go.txt -- +package x + +//go:cgo_ldflag "-fplugin=foo.so" + +import "C" +-- cgo_yy.go.txt -- +package x + +//go:cgo_ldflag "-fplugin=foo.so" + +import "C" +-- x.go.txt -- +package x +-- y_fplugin.go.txt -- +package x +// #cgo CFLAGS: -fplugin=foo.so +import "C" +-- y_lbar_fplugin.go.txt -- +package x +// #cgo CFLAGS: -Ibar -fplugin=foo.so +import "C" +-- y_pkgconfig_dash_foo.txt -- +package x +// #cgo pkg-config: -foo +import "C" +-- y_pkgconfig_at_foo.txt -- +package x +// #cgo pkg-config: @foo +import "C" +-- y_cflags_at_foo.txt -- +package x +// #cgo CFLAGS: @foo +import "C" +-- y_cflags_dash_d.txt -- +package x +// #cgo CFLAGS: -D +import "C" +-- y_cflags_dash_d_space_at_foo.txt -- +package x +// #cgo CFLAGS: -D @foo +import "C" +-- y_cflags_dash_d_at_foo.txt -- +package x +// #cgo CFLAGS: -D@foo +import "C" +-- y_no_cflags.txt -- +package x +import "C" diff --git a/libgo/go/cmd/go/testdata/script/cgo_depends_on_syscall.txt b/libgo/go/cmd/go/testdata/script/cgo_depends_on_syscall.txt new file mode 100644 index 0000000..bd4777c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cgo_depends_on_syscall.txt @@ -0,0 +1,15 @@ +[!cgo] skip +[!race] skip + +go list -race -deps foo +stdout syscall + +-- go.mod -- +module foo + +go 1.16 +-- foo.go -- +package foo + +// #include <stdio.h> +import "C" diff --git a/libgo/go/cmd/go/testdata/script/cgo_flag_contains_space.txt b/libgo/go/cmd/go/testdata/script/cgo_flag_contains_space.txt new file mode 100644 index 0000000..a3372bb --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cgo_flag_contains_space.txt @@ -0,0 +1,16 @@ +[short] skip +[!cgo] skip + +env GOCACHE=$WORK/gocache # Looking for compile flags, so need a clean cache. +go build -x -n main.go +stderr '"-I[^"]+c flags"' # find quoted c flags +! stderr '"-I[^"]+c flags".*"-I[^"]+c flags"' # don't find too many quoted c flags per line +stderr '"-L[^"]+ld flags"' # find quoted ld flags +! stderr '"-L[^"]+c flags".*"-L[^"]+c flags"' # don't find too many quoted ld flags per line + +-- main.go -- +package main +// #cgo CFLAGS: -I"c flags" +// #cgo LDFLAGS: -L"ld flags" +import "C" +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/cgo_path.txt b/libgo/go/cmd/go/testdata/script/cgo_path.txt new file mode 100644 index 0000000..be9609e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cgo_path.txt @@ -0,0 +1,43 @@ +[!cgo] skip + +# Set CC explicitly to something that requires a PATH lookup. +# Normally, the default is gcc or clang, but if CC was set during make.bash, +# that becomes the default. +[exec:clang] env CC=clang +[exec:gcc] env CC=gcc +[!exec:clang] [!exec:gcc] skip 'Unknown C compiler' + +env GOCACHE=$WORK/gocache # Looking for compile flags, so need a clean cache. +[!windows] env PATH=.:$PATH +[!windows] chmod 0755 p/gcc p/clang +[!windows] exists -exec p/gcc p/clang +[windows] exists -exec p/gcc.bat p/clang.bat +! exists p/bug.txt +! go build -x +stderr '^cgo: exec (clang|gcc): (clang|gcc) resolves to executable relative to current directory \(.[/\\](clang|gcc)(.bat)?\)$' +! exists p/bug.txt + +-- go.mod -- +module m + +-- m.go -- +package m + +import _ "m/p" + +-- p/p.go -- +package p + +// #define X 1 +import "C" + +-- p/gcc -- +#!/bin/sh +echo ran gcc >bug.txt +-- p/clang -- +#!/bin/sh +echo ran clang >bug.txt +-- p/gcc.bat -- +echo ran gcc >bug.txt +-- p/clang.bat -- +echo ran clang >bug.txt diff --git a/libgo/go/cmd/go/testdata/script/cgo_path_space.txt b/libgo/go/cmd/go/testdata/script/cgo_path_space.txt new file mode 100644 index 0000000..654295d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cgo_path_space.txt @@ -0,0 +1,56 @@ +# Check that if the PATH directory containing the C compiler has a space, +# we can still use that compiler with cgo. +# Verifies #43808. +[!cgo] skip + +# Set CC explicitly to something that requires a PATH lookup. +# Normally, the default is gcc or clang, but if CC was set during make.bash, +# that becomes the default. +[exec:clang] env CC=clang +[exec:gcc] env CC=gcc +[!exec:clang] [!exec:gcc] skip 'Unknown C compiler' + +[!windows] chmod 0755 $WORK/'program files'/clang +[!windows] chmod 0755 $WORK/'program files'/gcc +[!windows] exists -exec $WORK/'program files'/clang +[!windows] exists -exec $WORK/'program files'/gcc +[!windows] env PATH=$WORK/'program files':$PATH +[windows] exists -exec $WORK/'program files'/gcc.bat +[windows] exists -exec $WORK/'program files'/clang.bat +[windows] env PATH=$WORK\'program files';%PATH% + +! exists $WORK/log.txt +? go build -x +exists $WORK/log.txt +rm $WORK/log.txt + +# TODO(#41400, #43078): when CC is set explicitly, it should be allowed to +# contain spaces separating arguments, and it should be possible to quote +# arguments with spaces (including the path), as in CGO_CFLAGS and other +# variables. For now, this doesn't work. +[!windows] env CC=$WORK/'program files'/gcc +[windows] env CC=$WORK\'program files'\gcc.bat +! go build -x +! exists $WORK/log.txt + +-- go.mod -- +module m + +-- m.go -- +package m + +// #define X 1 +import "C" + +-- $WORK/program files/gcc -- +#!/bin/sh + +echo ok >$WORK/log.txt +-- $WORK/program files/clang -- +#!/bin/sh + +echo ok >$WORK/log.txt +-- $WORK/program files/gcc.bat -- +echo ok >%WORK%\log.txt +-- $WORK/program files/clang.bat -- +echo ok >%WORK%\log.txt diff --git a/libgo/go/cmd/go/testdata/script/cgo_stale.txt b/libgo/go/cmd/go/testdata/script/cgo_stale.txt new file mode 100644 index 0000000..9e46855 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cgo_stale.txt @@ -0,0 +1,39 @@ +# golang.org/issue/46347: a stale runtime/cgo should only force a single rebuild + +[!cgo] skip +[short] skip + + +# If we set a unique CGO_CFLAGS, the installed copy of runtime/cgo +# should be reported as stale. + +env CGO_CFLAGS=-DTestScript_cgo_stale=true +stale runtime/cgo + + +# If we then build a package that uses cgo, runtime/cgo should be rebuilt and +# cached with the new flag, but not installed to GOROOT (and thus still stale). + +env GOCACHE=$WORK/cache # Use a fresh cache to avoid interference between runs. + +go build -x . +stderr '[/\\]cgo'$GOEXE'["]? .* -importpath runtime/cgo' +stale runtime/cgo + + +# After runtime/cgo has been rebuilt and cached, it should not be rebuilt again +# even though it is still reported as stale. + +go build -x . +! stderr '[/\\]cgo'$GOEXE'["]? .* -importpath runtime/cgo' +stale runtime/cgo + + +-- go.mod -- +module example.com/m + +go 1.17 +-- m.go -- +package m + +import "C" diff --git a/libgo/go/cmd/go/testdata/script/clean_binary.txt b/libgo/go/cmd/go/testdata/script/clean_binary.txt new file mode 100644 index 0000000..7335f8a --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/clean_binary.txt @@ -0,0 +1,78 @@ +# Build something to create the executable, including several cases +[short] skip + +# --------------------- clean executables ------------------------- + +# case1: test file-named executable 'main' +env GO111MODULE=on + +! exists main$GOEXE +go build main.go +exists -exec main$GOEXE +go clean +! exists main$GOEXE + +# case2: test module-named executable 'a.b.c' +! exists a.b.c$GOEXE +go build +exists -exec a.b.c$GOEXE +go clean +! exists a.b.c$GOEXE + +# case3: directory-named executable 'src' +env GO111MODULE=off + +! exists src$GOEXE +go build +exists -exec src$GOEXE +go clean +! exists src$GOEXE + +# --------------------- clean test files ------------------------- + +# case1: test file-named test file +env GO111MODULE=on + +! exists main.test$GOEXE +go test -c main_test.go +exists -exec main.test$GOEXE +go clean +! exists main.test$GOEXE + +# case2: test module-named test file +! exists a.b.c.test$GOEXE +go test -c +exists -exec a.b.c.test$GOEXE +go clean +! exists a.b.c.test$GOEXE + +# case3: test directory-based test file +env GO111MODULE=off + +! exists src.test$GOEXE +go test -c +exists -exec src.test$GOEXE +go clean +! exists src.test$GOEXE + +-- main.go -- +package main + +import "fmt" + +func main() { + fmt.Println("hello!") +} + +-- main_test.go -- +package main + +import "testing" + +func TestSomething(t *testing.T) { +} + +-- go.mod -- +module example.com/a.b.c/v2 + +go 1.12
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/clean_cache_n.txt b/libgo/go/cmd/go/testdata/script/clean_cache_n.txt new file mode 100644 index 0000000..4497b36 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/clean_cache_n.txt @@ -0,0 +1,25 @@ +# We're testing cache behavior, so start with a clean GOCACHE. +env GOCACHE=$WORK/cache + +# Build something so that the cache gets populates +go build main.go + +# Check that cache contains directories before running +exists $GOCACHE/00 + +# Run go clean -cache -n and ensure that directories weren't deleted +go clean -cache -n +exists $GOCACHE/00 + +# Re-run go clean cache without the -n flag go ensure that directories were properly removed +go clean -cache +! exists $GOCACHE/00 + +-- main.go -- +package main + +import "fmt" + +func main() { + fmt.Println("hello!") +} diff --git a/libgo/go/cmd/go/testdata/script/cover_asm.txt b/libgo/go/cmd/go/testdata/script/cover_asm.txt new file mode 100644 index 0000000..57f76d6 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_asm.txt @@ -0,0 +1,33 @@ +[short] skip +[gccgo] skip # gccgo has no cover tool + +# Test cover for a package that has an assembly function. + +go test -outputdir=$WORK -coverprofile=cover.out coverasm +go tool cover -func=$WORK/cover.out +stdout '\tg\t*100.0%' # Check g is 100% covered. +! stdout '\tf\t*[0-9]' # Check for no coverage on the assembly function + +-- go.mod -- +module coverasm + +go 1.16 +-- p.go -- +package p + +func f() + +func g() { + println("g") +} +-- p.s -- +// empty asm file, +// so go test doesn't complain about declaration of f in p.go. +-- p_test.go -- +package p + +import "testing" + +func Test(t *testing.T) { + g() +} diff --git a/libgo/go/cmd/go/testdata/script/cover_blank_func_decl.txt b/libgo/go/cmd/go/testdata/script/cover_blank_func_decl.txt new file mode 100644 index 0000000..e7d5250 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_blank_func_decl.txt @@ -0,0 +1,35 @@ +[short] skip +go test -cover coverblank +stdout 'coverage: 100.0% of statements' + + +-- go.mod -- +module coverblank + +go 1.16 +-- a.go -- +package coverblank + +func _() { + println("unreachable") +} + +type X int + +func (x X) Print() { + println(x) +} + +func (x X) _() { + println("unreachable") +} + +-- a_test.go -- +package coverblank + +import "testing" + +func TestX(t *testing.T) { + var x X + x.Print() +} diff --git a/libgo/go/cmd/go/testdata/script/cover_cgo.txt b/libgo/go/cmd/go/testdata/script/cover_cgo.txt new file mode 100644 index 0000000..9cf78f7 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_cgo.txt @@ -0,0 +1,42 @@ +[short] skip +[!cgo] skip +[gccgo] skip # gccgo has no cover tool + +# Test coverage on cgo code. + +go test -short -cover cgocover +stdout 'coverage:.*[1-9][0-9.]+%' +! stderr '[^0-9]0\.0%' + +-- go.mod -- +module cgocover + +go 1.16 +-- p.go -- +package p + +/* +void +f(void) +{ +} +*/ +import "C" + +var b bool + +func F() { + if b { + for { + } + } + C.f() +} +-- p_test.go -- +package p + +import "testing" + +func TestF(t *testing.T) { + F() +} diff --git a/libgo/go/cmd/go/testdata/script/cover_cgo_extra_file.txt b/libgo/go/cmd/go/testdata/script/cover_cgo_extra_file.txt new file mode 100644 index 0000000..c53b979 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_cgo_extra_file.txt @@ -0,0 +1,48 @@ +[short] skip +[!cgo] skip +[gccgo] skip # gccgo has no cover tool + +# Test coverage on cgo code. This test case includes an +# extra empty non-cgo file in the package being checked. + +go test -short -cover cgocover4 +stdout 'coverage:.*[1-9][0-9.]+%' +! stderr '[^0-9]0\.0%' + +-- go.mod -- +module cgocover4 + +go 1.16 +-- notcgo.go -- +package p +-- p.go -- +package p + +/* +void +f(void) +{ +} +*/ +import "C" + +var b bool + +func F() { + if b { + for { + } + } + C.f() +} +-- x_test.go -- +package p_test + +import ( + . "cgocover4" + "testing" +) + +func TestF(t *testing.T) { + F() +} diff --git a/libgo/go/cmd/go/testdata/script/cover_cgo_extra_test.txt b/libgo/go/cmd/go/testdata/script/cover_cgo_extra_test.txt new file mode 100644 index 0000000..b501ab0 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_cgo_extra_test.txt @@ -0,0 +1,49 @@ +[short] skip +[!cgo] skip +[gccgo] skip # gccgo has no cover tool + +# Test coverage on cgo code. This test case has an external +# test that tests the code and an in-package test file with +# no test cases. + +go test -short -cover cgocover3 +stdout 'coverage:.*[1-9][0-9.]+%' +! stderr '[^0-9]0\.0%' + +-- go.mod -- +module cgocover3 + +go 1.16 +-- p.go -- +package p + +/* +void +f(void) +{ +} +*/ +import "C" + +var b bool + +func F() { + if b { + for { + } + } + C.f() +} +-- p_test.go -- +package p +-- x_test.go -- +package p_test + +import ( + . "cgocover3" + "testing" +) + +func TestF(t *testing.T) { + F() +} diff --git a/libgo/go/cmd/go/testdata/script/cover_cgo_xtest.txt b/libgo/go/cmd/go/testdata/script/cover_cgo_xtest.txt new file mode 100644 index 0000000..79cc08c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_cgo_xtest.txt @@ -0,0 +1,45 @@ +[short] skip +[!cgo] skip +[gccgo] skip # gccgo has no cover tool + +# Test cgo coverage with an external test. + +go test -short -cover cgocover2 +stdout 'coverage:.*[1-9][0-9.]+%' +! stderr '[^0-9]0\.0%' + +-- go.mod -- +module cgocover2 + +go 1.16 +-- p.go -- +package p + +/* +void +f(void) +{ +} +*/ +import "C" + +var b bool + +func F() { + if b { + for { + } + } + C.f() +} +-- x_test.go -- +package p_test + +import ( + . "cgocover2" + "testing" +) + +func TestF(t *testing.T) { + F() +} diff --git a/libgo/go/cmd/go/testdata/script/cover_dash_c.txt b/libgo/go/cmd/go/testdata/script/cover_dash_c.txt new file mode 100644 index 0000000..8950f8d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_dash_c.txt @@ -0,0 +1,31 @@ +[short] skip +[gccgo] skip + +# Test for issue 24588 + +go test -c -o $WORK/coverdep -coverprofile=$WORK/no/such/dir/cover.out coverdep +exists -exec $WORK/coverdep + +-- go.mod -- +module coverdep + +go 1.16 +-- p.go -- +package p + +import _ "coverdep/p1" + +func F() { +} +-- p1/p1.go -- +package p1 + +import _ "errors" +-- p_test.go -- +package p + +import "testing" + +func Test(t *testing.T) { + F() +} diff --git a/libgo/go/cmd/go/testdata/script/cover_dep_loop.txt b/libgo/go/cmd/go/testdata/script/cover_dep_loop.txt new file mode 100644 index 0000000..36ea6e0 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_dep_loop.txt @@ -0,0 +1,36 @@ +[short] skip +[gccgo] skip + +# coverdep2/p1's xtest imports coverdep2/p2 which imports coverdep2/p1. +# Make sure that coverage on coverdep2/p2 recompiles coverdep2/p2. + +go test -short -cover coverdep2/p1 +stdout 'coverage: 100.0% of statements' # expect 100.0% coverage + +-- go.mod -- +module coverdep2 + +go 1.16 +-- p1/p.go -- +package p1 + +func F() int { return 1 } +-- p1/p_test.go -- +package p1_test + +import ( + "coverdep2/p2" + "testing" +) + +func Test(t *testing.T) { + p2.F() +} +-- p2/p2.go -- +package p2 + +import "coverdep2/p1" + +func F() { + p1.F() +} diff --git a/libgo/go/cmd/go/testdata/script/cover_dot_import.txt b/libgo/go/cmd/go/testdata/script/cover_dot_import.txt new file mode 100644 index 0000000..d492e42 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_dot_import.txt @@ -0,0 +1,29 @@ +[short] skip +[gccgo] skip # gccgo has no cover tool + +go test -coverpkg=coverdot/a,coverdot/b coverdot/b +! stderr '[^0-9]0\.0%' +! stdout '[^0-9]0\.0%' + +-- go.mod -- +module coverdot + +go 1.16 +-- a/a.go -- +package a + +func F() {} +-- b/b.go -- +package b + +import . "coverdot/a" + +func G() { F() } +-- b/b_test.go -- +package b + +import "testing" + +func TestG(t *testing.T) { + G() +} diff --git a/libgo/go/cmd/go/testdata/script/cover_error.txt b/libgo/go/cmd/go/testdata/script/cover_error.txt new file mode 100644 index 0000000..583a664 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_error.txt @@ -0,0 +1,74 @@ +[short] skip +[gccgo] skip + +# Test line numbers in cover errors. + +# Get errors from a go test into stderr.txt +! go test coverbad +stderr 'p\.go:4' # look for error at coverbad/p.go:4 +[cgo] stderr 'p1\.go:6' # look for error at coverbad/p.go:6 +! stderr $WORK # make sure temporary directory isn't in error + +cp stderr $WORK/stderr.txt + +# Clean out character positions from stderr.txt +# It's OK that stderr2 drops the character position in the error, +# because of the //line directive (see golang.org/issue/22662). +go run clean_charpos.go $WORK/stderr.txt & + +# Get errors from coverage into stderr2.txt +! go test -cover coverbad +cp stderr $WORK/stderr2.txt + +wait # for go run above + +cmp $WORK/stderr.txt $WORK/stderr2.txt + +-- go.mod -- +module coverbad + +go 1.16 +-- p.go -- +package p + +func f() { + g() +} +-- p1.go -- +package p + +import "C" + +func h() { + j() +} +-- p_test.go -- +package p + +import "testing" + +func Test(t *testing.T) {} +-- clean_charpos.go -- +// +build ignore + +package main + +import ( + "log" + "os" + "strings" +) + +func main() { + log.SetFlags(0) + b, err := os.ReadFile(os.Args[1]) + if err != nil { + log.Fatal(err) + } + s := strings.ReplaceAll(string(b), "p.go:4:2:", "p.go:4:") + s = strings.ReplaceAll(s, "p1.go:6:2:", "p1.go:6:") + os.WriteFile(os.Args[1], []byte(s), 0644) + if err != nil { + log.Fatal(err) + } +} diff --git a/libgo/go/cmd/go/testdata/script/cover_import_main_loop.txt b/libgo/go/cmd/go/testdata/script/cover_import_main_loop.txt new file mode 100644 index 0000000..eb6de67 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_import_main_loop.txt @@ -0,0 +1,26 @@ +[gccgo] skip # gccgo has no cover tool + +! go test -n importmain/test +stderr 'not an importable package' # check that import main was detected +! go test -n -cover importmain/test +stderr 'not an importable package' # check that import main was detected + +-- go.mod -- +module importmain + +go 1.16 +-- ismain/main.go -- +package main + +import _ "importmain/test" + +func main() {} +-- test/test.go -- +package test +-- test/test_test.go -- +package test_test + +import "testing" +import _ "importmain/ismain" + +func TestCase(t *testing.T) {} diff --git a/libgo/go/cmd/go/testdata/script/cover_pattern.txt b/libgo/go/cmd/go/testdata/script/cover_pattern.txt new file mode 100644 index 0000000..ec0850c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_pattern.txt @@ -0,0 +1,41 @@ +[gccgo] skip + +# If coverpkg=m/sleepy... expands by package loading +# (as opposed to pattern matching on deps) +# then it will try to load sleepybad, which does not compile, +# and the test command will fail. +! go list m/sleepy... +go test -c -n -coverprofile=$TMPDIR/cover.out -coverpkg=m/sleepy... -run=^$ m/sleepy1 + +-- go.mod -- +module m + +go 1.16 +-- sleepy1/p_test.go -- +package p + +import ( + "testing" + "time" +) + +func Test1(t *testing.T) { + time.Sleep(200 * time.Millisecond) +} +-- sleepy2/p_test.go -- +package p + +import ( + "testing" + "time" +) + +func Test1(t *testing.T) { + time.Sleep(200 * time.Millisecond) +} +-- sleepybad/p.go -- +package p + +import ^ + +var _ = io.DoesNotExist diff --git a/libgo/go/cmd/go/testdata/script/cover_pkgall_imports.txt b/libgo/go/cmd/go/testdata/script/cover_pkgall_imports.txt new file mode 100644 index 0000000..4e51726 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_pkgall_imports.txt @@ -0,0 +1,48 @@ +# This test checks that -coverpkg=all can be used +# when the package pattern includes packages +# which only have tests. +# Verifies golang.org/issue/27333, golang.org/issue/43242. + +[short] skip +cd $GOPATH/src/example.com/cov + +env GO111MODULE=on +go test -coverpkg=all ./... + +env GO111MODULE=off +go test -coverpkg=all ./... + +-- $GOPATH/src/example.com/cov/go.mod -- +module example.com/cov + +-- $GOPATH/src/example.com/cov/notest/notest.go -- +package notest + +func Foo() {} + +-- $GOPATH/src/example.com/cov/onlytest/onlytest_test.go -- +package onlytest_test + +import ( + "testing" + + "example.com/cov/notest" +) + +func TestFoo(t *testing.T) { + notest.Foo() +} + +-- $GOPATH/src/example.com/cov/withtest/withtest.go -- +package withtest + +func Bar() {} + +-- $GOPATH/src/example.com/cov/withtest/withtest_test.go -- +package withtest + +import "testing" + +func TestBar(t *testing.T) { + Bar() +} diff --git a/libgo/go/cmd/go/testdata/script/cover_runs.txt b/libgo/go/cmd/go/testdata/script/cover_runs.txt new file mode 100644 index 0000000..38a7bb7 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_runs.txt @@ -0,0 +1,13 @@ +[gccgo] skip 'gccgo has no cover tool' +[short] skip + +go test -short -coverpkg=strings strings regexp +! stdout '[^0-9]0\.0%' +stdout 'strings.*coverage:.*[1-9][0-9.]+%' +stdout 'regexp.*coverage:.*[1-9][0-9.]+%' + +go test -short -cover strings math regexp +! stdout '[^0-9]0\.0%' +stdout 'strings.*coverage:.*[1-9][0-9.]+%' +stdout 'math.*coverage:.*[1-9][0-9.]+%' +stdout 'regexp.*coverage:.*[1-9][0-9.]+%'
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/cover_statements.txt b/libgo/go/cmd/go/testdata/script/cover_statements.txt new file mode 100644 index 0000000..4f3c9ca --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_statements.txt @@ -0,0 +1,61 @@ +[short] skip +go test -cover ./pkg1 ./pkg2 ./pkg3 ./pkg4 +stdout 'pkg1 \[no test files\]' +stdout 'pkg2 \S+ coverage: 0.0% of statements \[no tests to run\]' +stdout 'pkg3 \S+ coverage: 100.0% of statements' +stdout 'pkg4 \S+ coverage: \[no statements\]' + +-- go.mod -- +module m + +go 1.16 +-- pkg1/a.go -- +package pkg1 + +import "fmt" + +func F() { + fmt.Println("pkg1") +} +-- pkg2/a.go -- +package pkg2 + +import "fmt" + +func F() { + fmt.Println("pkg2") +} +-- pkg2/a_test.go -- +package pkg2 +-- pkg3/a.go -- +package pkg3 + +import "fmt" + +func F() { + fmt.Println("pkg3") +} +-- pkg3/a_test.go -- +package pkg3 + +import "testing" + +func TestF(t *testing.T) { + F() +} +-- pkg4/a.go -- +package pkg4 + +type T struct { + X bool +} +-- pkg4/a_test.go -- +package pkg4 + +import ( + "testing" +) + +func TestT(t *testing.T) { + _ = T{} +} diff --git a/libgo/go/cmd/go/testdata/script/cover_sync_atomic_import.txt b/libgo/go/cmd/go/testdata/script/cover_sync_atomic_import.txt new file mode 100644 index 0000000..433af9a --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_sync_atomic_import.txt @@ -0,0 +1,28 @@ +[short] skip +[gccgo] skip # gccgo has no cover tool + +go test -short -cover -covermode=atomic -coverpkg=coverdep/p1 coverdep + +-- go.mod -- +module coverdep + +go 1.16 +-- p.go -- +package p + +import _ "coverdep/p1" + +func F() { +} +-- p1/p1.go -- +package p1 + +import _ "errors" +-- p_test.go -- +package p + +import "testing" + +func Test(t *testing.T) { + F() +} diff --git a/libgo/go/cmd/go/testdata/script/doc.txt b/libgo/go/cmd/go/testdata/script/doc.txt new file mode 100644 index 0000000..670308c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/doc.txt @@ -0,0 +1,77 @@ +[gccgo] skip + +# go doc --help +! go doc --help +stderr 'go doc' +stderr 'go doc <pkg>' +stderr 'go doc <sym>\[\.<methodOrField>\]' +stderr 'go doc \[<pkg>\.\]<sym>\[\.<methodOrField>\]' +stderr 'go doc \[<pkg>\.\]\[<sym>\.\]<methodOrField>' +stderr 'go doc <pkg> <sym>\[\.<methodOrField>\]' + +# go help doc +go help doc +stdout 'go doc' +stdout 'go doc <pkg>' +stdout 'go doc <sym>\[\.<methodOrField>\]' +stdout 'go doc \[<pkg>\.\]<sym>\[\.<methodOrField>\]' +stdout 'go doc \[<pkg>\.\]\[<sym>\.\]<methodOrField>' +stdout 'go doc <pkg> <sym>\[\.<methodOrField>\]' + +# go doc <pkg> +go doc p/v2 +stdout . + +# go doc <pkg> <sym> +go doc p/v2 Symbol +stdout . + +# go doc <pkg> <sym> <method> +! go doc p/v2 Symbol Method +stderr . + +# go doc <pkg>.<sym> +go doc p/v2.Symbol +stdout . + +# go doc <pkg>.<sym>.<method> +go doc p/v2.Symbol.Method +stdout . + +# go doc <sym> +go doc Symbol +stdout . + +# go doc <sym> <method> +! go doc Symbol Method +stderr . + +# go doc <sym>.<method> +go doc Symbol.Method +stdout . + +# go doc <pkg>.<method> +go doc p/v2.Method +stdout . + +# go doc <pkg> <method> +go doc p/v2 Method +stdout . + +# go doc <method> +go doc Method +stdout . + +-- go.mod -- +module p/v2 + +go 1.13 + +-- p.go -- +package p + +type Symbol struct{} + +func (Symbol) Method() error { + return nil +} diff --git a/libgo/go/cmd/go/testdata/script/embed.txt b/libgo/go/cmd/go/testdata/script/embed.txt new file mode 100644 index 0000000..04b17cd --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/embed.txt @@ -0,0 +1,110 @@ +# go list shows patterns and files +go list -f '{{.EmbedPatterns}}' +stdout '\[x\*t\*t\]' +go list -f '{{.EmbedFiles}}' +stdout '\[x.txt\]' +go list -test -f '{{.TestEmbedPatterns}}' +stdout '\[y\*t\*t\]' +go list -test -f '{{.TestEmbedFiles}}' +stdout '\[y.txt\]' +go list -test -f '{{.XTestEmbedPatterns}}' +stdout '\[z\*t\*t\]' +go list -test -f '{{.XTestEmbedFiles}}' +stdout '\[z.txt\]' + +# build embeds x.txt +go build -x +stderr 'x.txt' + +# build uses cache correctly +go build -x +! stderr 'x.txt' +cp x.txt2 x.txt +go build -x +stderr 'x.txt' + +# build rejects invalid names +cp x.go2 x.go +go build -x +cp x.txt .git +! go build -x +stderr '^x.go:5:12: pattern [*]t: cannot embed file [.]git: invalid name [.]git$' +rm .git + +# build rejects symlinks +[symlink] symlink x.tzt -> x.txt +[symlink] ! go build -x +[symlink] stderr 'pattern [*]t: cannot embed irregular file x.tzt' +[symlink] rm x.tzt + +# build rejects empty directories +mkdir t +! go build -x +stderr '^x.go:5:12: pattern [*]t: cannot embed directory t: contains no embeddable files$' + +# build ignores symlinks and invalid names in directories +cp x.txt t/.git +! go build -x +stderr '^x.go:5:12: pattern [*]t: cannot embed directory t: contains no embeddable files$' +go list -e -f '{{.Incomplete}}' +stdout 'true' +[symlink] symlink t/x.link -> ../x.txt +[symlink] ! go build -x +[symlink] stderr '^x.go:5:12: pattern [*]t: cannot embed directory t: contains no embeddable files$' + +cp x.txt t/x.txt +go build -x + +# build reports errors with positions in imported packages +rm t/x.txt +! go build m/use +stderr '^x.go:5:12: pattern [*]t: cannot embed directory t: contains no embeddable files$' + +-- x.go -- +package p + +import "embed" + +//go:embed x*t*t +var X embed.FS + +-- x_test.go -- +package p + +import "embed" + +//go:embed y*t*t +var Y string + +-- x_x_test.go -- +package p_test + +import "embed" + +//go:embed z*t*t +var Z string + +-- x.go2 -- +package p + +import "embed" + +//go:embed *t +var X embed.FS + +-- x.txt -- +hello + +-- y.txt -- +-- z.txt -- +-- x.txt2 -- +not hello + +-- use/use.go -- +package use + +import _ "m" +-- go.mod -- +module m + +go 1.16 diff --git a/libgo/go/cmd/go/testdata/script/embed_fmt.txt b/libgo/go/cmd/go/testdata/script/embed_fmt.txt new file mode 100644 index 0000000..8a16afe --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/embed_fmt.txt @@ -0,0 +1,22 @@ +# go fmt ignores file not found +go fmt xnofmt.go +cmp xnofmt.go xfmt.ref +! go build xnofmt.go +stderr 'xnofmt.go:5:12: pattern missing.txt: no matching files found' + +-- xnofmt.go -- +package p + +import "embed" + +//go:embed missing.txt +var X embed.FS +-- xfmt.ref -- +package p + +import "embed" + +//go:embed missing.txt +var X embed.FS +-- go.mod -- +module m diff --git a/libgo/go/cmd/go/testdata/script/env_cross_build.txt b/libgo/go/cmd/go/testdata/script/env_cross_build.txt new file mode 100644 index 0000000..0643282 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/env_cross_build.txt @@ -0,0 +1,31 @@ +# Test that the corect default GOEXPERIMENT is used when cross +# building with GOENV (#46815). + +[gccgo] skip + +# Unset variables set by the TestScript harness. Users typically won't +# explicitly configure these, and #46815 doesn't repro if they are. +env GOOS= +env GOARCH= +env GOEXPERIMENT= + +env GOENV=windows-amd64 +go build internal/abi + +env GOENV=ios-arm64 +go build internal/abi + +env GOENV=linux-mips +go build internal/abi + +-- windows-amd64 -- +GOOS=windows +GOARCH=amd64 + +-- ios-arm64 -- +GOOS=ios +GOARCH=arm64 + +-- linux-mips -- +GOOS=linux +GOARCH=mips diff --git a/libgo/go/cmd/go/testdata/script/env_exp.txt b/libgo/go/cmd/go/testdata/script/env_exp.txt new file mode 100644 index 0000000..681512d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/env_exp.txt @@ -0,0 +1,17 @@ +# Test GOEXPERIMENT variable + +# go env shows default empty GOEXPERIMENT +go env +stdout GOEXPERIMENT= + +# go env shows valid experiments +env GOEXPERIMENT=fieldtrack,staticlockranking +go env GOEXPERIMENT +stdout '.*fieldtrack.*staticlockranking.*' +go env +stdout 'GOEXPERIMENT=.*fieldtrack.*staticlockranking.*' + +# go env rejects unknown experiments +env GOEXPERIMENT=bad +! go env GOEXPERIMENT +stderr 'unknown GOEXPERIMENT bad' diff --git a/libgo/go/cmd/go/testdata/script/env_unset.txt b/libgo/go/cmd/go/testdata/script/env_unset.txt new file mode 100644 index 0000000..647f265 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/env_unset.txt @@ -0,0 +1,32 @@ +# Test that we can unset variables, even if initially invalid, +# as long as resulting config is valid. + +[gccgo] skip + +env GOENV=badenv +env GOOS= +env GOARCH= +env GOEXPERIMENT= + +! go env +stderr '^go(\.exe)?: unknown GOEXPERIMENT badexp$' + +go env -u GOEXPERIMENT + +! go env +stderr '^cmd/go: unsupported GOOS/GOARCH pair bados/badarch$' + +! go env -u GOOS +stderr '^go env -u: unsupported GOOS/GOARCH pair \w+/badarch$' + +! go env -u GOARCH +stderr '^go env -u: unsupported GOOS/GOARCH pair bados/\w+$' + +go env -u GOOS GOARCH + +go env + +-- badenv -- +GOOS=bados +GOARCH=badarch +GOEXPERIMENT=badexp diff --git a/libgo/go/cmd/go/testdata/script/env_write.txt b/libgo/go/cmd/go/testdata/script/env_write.txt index dc69652..7920fba 100644 --- a/libgo/go/cmd/go/testdata/script/env_write.txt +++ b/libgo/go/cmd/go/testdata/script/env_write.txt @@ -174,3 +174,15 @@ go env -w GOOS=linux GOARCH=mips env GOOS=windows ! go env -u GOOS stderr 'unsupported GOOS/GOARCH.*windows/mips$' + +# go env -w should reject relative paths in GOMODCACHE environment. +! go env -w GOMODCACHE=~/test +stderr 'go env -w: GOMODCACHE entry is relative; must be absolute path: "~/test"' +! go env -w GOMODCACHE=./test +stderr 'go env -w: GOMODCACHE entry is relative; must be absolute path: "./test"' + +# go env -w checks validity of GOEXPERIMENT +env GOEXPERIMENT= +! go env -w GOEXPERIMENT=badexp +stderr 'unknown GOEXPERIMENT badexp' +go env -w GOEXPERIMENT=fieldtrack diff --git a/libgo/go/cmd/go/testdata/script/fmt_load_errors.txt b/libgo/go/cmd/go/testdata/script/fmt_load_errors.txt index 297ec0f..84bf41c 100644 --- a/libgo/go/cmd/go/testdata/script/fmt_load_errors.txt +++ b/libgo/go/cmd/go/testdata/script/fmt_load_errors.txt @@ -6,6 +6,17 @@ go fmt -n exclude stdout 'exclude[/\\]x\.go' stdout 'exclude[/\\]x_linux\.go' +# Test edge cases with gofmt. +# Note that this execs GOROOT/bin/gofmt. + +! exec gofmt does-not-exist + +exec gofmt gofmt-dir/no-extension +stdout 'package x' + +exec gofmt gofmt-dir +! stdout 'package x' + -- exclude/empty/x.txt -- -- exclude/ignore/_x.go -- package x @@ -17,3 +28,5 @@ package x // +build windows package x +-- gofmt-dir/no-extension -- +package x diff --git a/libgo/go/cmd/go/testdata/script/gccgo_link_c.txt b/libgo/go/cmd/go/testdata/script/gccgo_link_c.txt new file mode 100644 index 0000000..db2a291 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/gccgo_link_c.txt @@ -0,0 +1,16 @@ +# Issue #7573 +# cmd/cgo: undefined reference when linking a C-library using gccgo + +[!cgo] skip +[!exec:gccgo] skip + +go build -n -compiler gccgo cgoref +stderr 'gccgo.*\-L [^ ]*alibpath \-lalib' # make sure that Go-inline "#cgo LDFLAGS:" ("-L alibpath -lalib") passed to gccgo linking stage + +-- cgoref/cgoref.go -- +package main +// #cgo LDFLAGS: -L alibpath -lalib +// void f(void) {} +import "C" + +func main() { C.f() } diff --git a/libgo/go/cmd/go/testdata/script/generate.txt b/libgo/go/cmd/go/testdata/script/generate.txt new file mode 100644 index 0000000..73f5bbd --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/generate.txt @@ -0,0 +1,99 @@ +[short] skip + +# Install an echo command because Windows doesn't have it. +env GOBIN=$WORK/tmp/bin +go install echo.go +env PATH=$GOBIN${:}$PATH + +# Test go generate handles a simple command +go generate ./generate/simple.go +stdout 'Success' + +# Test go generate handles a command alias +go generate './generate/alias.go' +stdout 'Now is the time for all good men' + +# Test go generate's variable substitution +go generate './generate/substitution.go' +stdout $GOARCH' substitution.go:7 pabc xyzp/substitution.go/123' + +# Test go generate's run flag +go generate -run y.s './generate/flag.go' +stdout 'yes' # flag.go should select yes +! stdout 'no' # flag.go should not select no + +# Test go generate provides the right "$GOPACKAGE" name in an x_test +go generate './generate/env_test.go' +stdout 'main_test' + +# Test go generate provides the right "$PWD" +go generate './generate/env_pwd.go' +stdout $WORK'[/\\]gopath[/\\]src[/\\]generate' + +-- echo.go -- +package main + +import ( + "fmt" + "os" + "strings" +) + +func main() { + fmt.Println(strings.Join(os.Args[1:], " ")) + fmt.Println() +} +-- generate/simple.go -- +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Simple test for go generate. + +// We include a build tag that go generate should ignore. + +// +build ignore + +//go:generate echo Success + +package p +-- generate/alias.go -- +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test that go generate handles command aliases. + +//go:generate -command run echo Now is the time +//go:generate run for all good men + +package p +-- generate/substitution.go -- +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test go generate variable substitution. + +//go:generate echo $GOARCH $GOFILE:$GOLINE ${GOPACKAGE}abc xyz$GOPACKAGE/$GOFILE/123 + +package p +-- generate/flag.go -- +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test -run flag + +//go:generate echo oh yes my man +//go:generate echo no, no, a thousand times no + +package p +-- generate/env_test.go -- +package main_test + +//go:generate echo $GOPACKAGE +-- generate/env_pwd.go -- +package p + +//go:generate echo $PWD diff --git a/libgo/go/cmd/go/testdata/script/generate_bad_imports.txt b/libgo/go/cmd/go/testdata/script/generate_bad_imports.txt new file mode 100644 index 0000000..4d31573 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/generate_bad_imports.txt @@ -0,0 +1,15 @@ +[windows] skip # skip because windows has no echo command + +go generate gencycle +stdout 'hello world' # check go generate gencycle ran the generator + +-- go.mod -- +module gencycle + +go 1.16 +-- gencycle.go -- +//go:generate echo hello world + +package gencycle + +import _ "gencycle" diff --git a/libgo/go/cmd/go/testdata/script/generate_env.txt b/libgo/go/cmd/go/testdata/script/generate_env.txt new file mode 100644 index 0000000..2df1663 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/generate_env.txt @@ -0,0 +1,32 @@ +# Install an env command because Windows and plan9 don't have it. +env GOBIN=$WORK/tmp/bin +go install env.go +[plan9] env path=$GOBIN${:}$path +[!plan9] env PATH=$GOBIN${:}$PATH + +# Test generators have access to the environment +go generate ./printenv.go +stdout '^GOARCH='$GOARCH +stdout '^GOOS='$GOOS +stdout '^GOFILE=' +stdout '^GOLINE=' +stdout '^GOPACKAGE=' +stdout '^DOLLAR=' + +-- env.go -- +package main + +import ( + "fmt" + "os" +) + +func main() { + for _, v := range os.Environ() { + fmt.Println(v) + } +} +-- printenv.go -- +package main + +//go:generate env
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/generate_invalid.txt b/libgo/go/cmd/go/testdata/script/generate_invalid.txt new file mode 100644 index 0000000..e18e62c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/generate_invalid.txt @@ -0,0 +1,203 @@ +[short] skip + +# Install an echo command because Windows doesn't have it. +env GOBIN=$WORK/tmp/bin +go install echo.go +env PATH=$GOBIN${:}$PATH + +# Test go generate for directory with no go files +go generate ./nogo +! stdout 'Fail' + +# Test go generate for package where all .go files are excluded by build +# constraints +go generate -v ./excluded +! stdout 'Fail' +! stderr 'go' # -v shouldn't list any files + +# Test go generate for "package" with no package clause in any file +go generate ./nopkg +stdout 'Success a' +! stdout 'Fail' + +# Test go generate for package with inconsistent package clauses +# $GOPACKAGE should depend on each file's package clause +go generate ./inconsistent +stdout 'Success a' +stdout 'Success b' +stdout -count=2 'Success c' +! stdout 'Fail' + +# Test go generate for syntax errors before and after package clauses +go generate ./syntax +stdout 'Success a' +stdout 'Success b' +! stdout 'Fail' + +# Test go generate for files importing non-existent packages +go generate ./importerr +stdout 'Success a' +stdout 'Success b' +stdout 'Success c' + +-- echo.go -- +package main + +import ( + "fmt" + "os" + "strings" +) + +func main() { + fmt.Println(strings.Join(os.Args[1:], " ")) + fmt.Println() +} + +-- go.mod -- +module m + +go 1.16 +-- nogo/foo.txt -- +Text file in a directory without go files. +Go generate should ignore this directory. +//go:generate echo Fail nogo + +-- excluded/a.go -- +// Include a build tag that go generate should exclude. +// Go generate should ignore this file. + +// +build a + +//go:generate echo Fail a + +package excluded + +-- excluded/b.go -- +// Include a build tag that go generate should exclude. +// Go generate should ignore this file. + +//go:generate echo Fail b + +// +build b + +package excluded + + +-- nopkg/a.go -- +// Go file with package clause after comment. +// Go generate should process this file. + +/* Pre-comment */ package nopkg +//go:generate echo Success a + +-- nopkg/b.go -- +// Go file with commented package clause. +// Go generate should ignore this file. + +//package nopkg + +//go:generate echo Fail b + +-- nopkg/c.go -- +// Go file with package clause inside multiline comment. +// Go generate should ignore this file. + +/* +package nopkg +*/ + +//go:generate echo Fail c + +-- nopkg/d.go -- +// Go file with package clause inside raw string literal. +// Go generate should ignore this file. + +const foo = ` +package nopkg +` +//go:generate echo Fail d + +-- nopkg/e.go -- +// Go file without package clause. +// Go generate should ignore this file. + +//go:generate echo Fail e + +-- inconsistent/a.go -- +// Valid go file with inconsistent package name. +// Go generate should process this file with GOPACKAGE=a + +package a +//go:generate echo Success $GOPACKAGE + +-- inconsistent/b.go -- +// Valid go file with inconsistent package name. +// Go generate should process this file with GOPACKAGE=b + +//go:generate echo Success $GOPACKAGE +package b + +-- inconsistent/c.go -- +// Go file with two package clauses. +// Go generate should process this file with GOPACKAGE=c + +//go:generate echo Success $GOPACKAGE +package c +// Invalid package clause, should be ignored: +package cinvalid +//go:generate echo Success $GOPACKAGE + +-- inconsistent/d.go -- +// Go file with invalid package name. +// Go generate should ignore this file. + +package +d+ +//go:generate echo Fail $GOPACKAGE + +-- syntax/a.go -- +// Go file with syntax error after package clause. +// Go generate should process this file. + +package syntax +123 +//go:generate echo Success a + +-- syntax/b.go -- +// Go file with syntax error after package clause. +// Go generate should process this file. + +package syntax; 123 +//go:generate echo Success b + +-- syntax/c.go -- +// Go file with syntax error before package clause. +// Go generate should ignore this file. + +foo +package syntax +//go:generate echo Fail c + +-- importerr/a.go -- +// Go file which imports non-existing package. +// Go generate should process this file. + +package importerr +//go:generate echo Success a +import "foo" + +-- importerr/b.go -- +// Go file which imports non-existing package. +// Go generate should process this file. + +//go:generate echo Success b +package importerr +import "bar" + +-- importerr/c.go -- +// Go file which imports non-existing package. +// Go generate should process this file. + +package importerr +import "moo" +//go:generate echo Success c diff --git a/libgo/go/cmd/go/testdata/script/get_404_meta.txt b/libgo/go/cmd/go/testdata/script/get_404_meta.txt index b71cc7f..ec4f8d3 100644 --- a/libgo/go/cmd/go/testdata/script/get_404_meta.txt +++ b/libgo/go/cmd/go/testdata/script/get_404_meta.txt @@ -3,9 +3,10 @@ [!net] skip [!exec:git] skip +env GONOSUMDB=bazil.org,github.com,golang.org env GO111MODULE=off -go get -d -insecure bazil.org/fuse/fs/fstestutil +go get -d bazil.org/fuse/fs/fstestutil env GO111MODULE=on env GOPROXY=direct -go get -d -insecure bazil.org/fuse/fs/fstestutil +go get -d bazil.org/fuse/fs/fstestutil diff --git a/libgo/go/cmd/go/testdata/script/get_custom_domain_wildcard.txt b/libgo/go/cmd/go/testdata/script/get_custom_domain_wildcard.txt new file mode 100644 index 0000000..cda25e1 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_custom_domain_wildcard.txt @@ -0,0 +1,6 @@ +[!net] skip +[!exec:git] skip +env GO111MODULE=off + +go get -u rsc.io/pdf/... +exists $GOPATH/bin/pdfpasswd$GOEXE diff --git a/libgo/go/cmd/go/testdata/script/get_dash_t.txt b/libgo/go/cmd/go/testdata/script/get_dash_t.txt new file mode 100644 index 0000000..baac916 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_dash_t.txt @@ -0,0 +1,9 @@ +# Tests issue 8181 + +[!net] skip +[!exec:git] skip +env GO111MODULE=off + +go get -v -t github.com/rsc/go-get-issue-8181/a github.com/rsc/go-get-issue-8181/b +go list ... +stdout 'x/build/gerrit' diff --git a/libgo/go/cmd/go/testdata/script/get_domain_root.txt b/libgo/go/cmd/go/testdata/script/get_domain_root.txt new file mode 100644 index 0000000..9187848 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_domain_root.txt @@ -0,0 +1,20 @@ +# Tests issue #9357 +# go get foo.io (not foo.io/subdir) was not working consistently. + +[!net] skip +[!exec:git] skip +env GO111MODULE=off + +# go-get-issue-9357.appspot.com is running +# the code at github.com/rsc/go-get-issue-9357, +# a trivial Go on App Engine app that serves a +# <meta> tag for the domain root. +go get -d go-get-issue-9357.appspot.com +go get go-get-issue-9357.appspot.com +go get -u go-get-issue-9357.appspot.com + +rm $GOPATH/src/go-get-issue-9357.appspot.com +go get go-get-issue-9357.appspot.com + +rm $GOPATH/src/go-get-issue-9357.appspot.com +go get -u go-get-issue-9357.appspot.com diff --git a/libgo/go/cmd/go/testdata/script/get_dot_slash_download.txt b/libgo/go/cmd/go/testdata/script/get_dot_slash_download.txt new file mode 100644 index 0000000..dbaf46c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_dot_slash_download.txt @@ -0,0 +1,10 @@ +[!net] skip +[!exec:git] skip +env GO111MODULE=off + +# Tests Issues #9797 and #19769 + +mkdir $WORK/tmp/src/rsc.io +env GOPATH=$WORK/tmp +cd $WORK/tmp/src/rsc.io +go get ./pprof_mac_fix diff --git a/libgo/go/cmd/go/testdata/script/get_go_file.txt b/libgo/go/cmd/go/testdata/script/get_go_file.txt new file mode 100644 index 0000000..bed8720 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_go_file.txt @@ -0,0 +1,60 @@ +# Tests Issue #38478 +# Tests that go get in GOPATH mode returns a specific error if the argument +# ends with '.go', and either has no slash or refers to an existing file. + +env GO111MODULE=off + +# argument doesn't have .go suffix +go get -d test + +# argument has .go suffix, is a file and exists +! go get -d test.go +stderr 'go get test.go: arguments must be package or module paths' + +# argument has .go suffix, doesn't exist and has no slashes +! go get -d test_missing.go +stderr 'go get test_missing.go: arguments must be package or module paths' + +# argument has .go suffix, is a file and exists in sub-directory +! go get -d test/test.go +stderr 'go get: test/test.go exists as a file, but ''go get'' requires package arguments' + +# argument has .go suffix, doesn't exist and has slashes +! go get -d test/test_missing.go +! stderr 'arguments must be package or module paths' +! stderr 'exists as a file, but ''go get'' requires package arguments' + +# argument has .go suffix, is a symlink and exists +[symlink] symlink test_sym.go -> test.go +[symlink] ! go get -d test_sym.go +[symlink] stderr 'go get test_sym.go: arguments must be package or module paths' +[symlink] rm test_sym.go + +# argument has .go suffix, is a symlink and exists in sub-directory +[symlink] symlink test/test_sym.go -> test.go +[symlink] ! go get -d test/test_sym.go +[symlink] stderr 'go get: test/test_sym.go exists as a file, but ''go get'' requires package arguments' +[symlink] rm test_sym.go + +# argument has .go suffix, is a directory and exists +mkdir test_dir.go +! go get -d test_dir.go +stderr 'go get test_dir.go: arguments must be package or module paths' +rm test_dir.go + +# argument has .go suffix, is a directory and exists in sub-directory +mkdir test/test_dir.go +! go get -d test/test_dir.go +! stderr 'arguments must be package or module paths' +! stderr 'exists as a file, but ''go get'' requires package arguments' +rm test/test_dir.go + + +-- test.go -- +package main +func main() {println("test")} + + +-- test/test.go -- +package main +func main() {println("test")} diff --git a/libgo/go/cmd/go/testdata/script/get_goroot.txt b/libgo/go/cmd/go/testdata/script/get_goroot.txt new file mode 100644 index 0000000..929435a --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_goroot.txt @@ -0,0 +1,53 @@ +[!net] skip +env GO111MODULE=off + +# Issue 4186. go get cannot be used to download packages to $GOROOT. +# Test that without GOPATH set, go get should fail. + +# Fails because GOROOT=GOPATH +env GOPATH=$WORK/tmp +env GOROOT=$WORK/tmp +! go get -d github.com/golang/example/hello +stderr 'warning: GOPATH set to GOROOT' +stderr '\$GOPATH must not be set to \$GOROOT' + +# Fails because GOROOT=GOPATH after cleaning. +env GOPATH=$WORK/tmp/ +env GOROOT=$WORK/tmp +! go get -d github.com/golang/example/hello +stderr 'warning: GOPATH set to GOROOT' +stderr '\$GOPATH must not be set to \$GOROOT' + +env GOPATH=$WORK/tmp +env GOROOT=$WORK/tmp/ +! go get -d github.com/golang/example/hello +stderr 'warning: GOPATH set to GOROOT' +stderr '\$GOPATH must not be set to \$GOROOT' + +# Make a home directory +mkdir $WORK/home/go + +# Fails because GOROOT=$HOME/go so default GOPATH unset. +[windows] env USERPROFILE=$WORK/home +[plan9] env home=$WORK/home +[!windows] [!plan9] env HOME=$WORK/home +env GOPATH= +env GOROOT=$WORK/home/go +! go get -d github.com/golang/example/hello +stderr '\$GOPATH not set' + +[windows] env USERPROFILE=$WORK/home/ +[plan9] env home=$WORK/home/ +[!windows] [!plan9] env HOME=$WORK/home/ +env GOPATH= +env GOROOT=$WORK/home/go +! go get -d github.com/golang/example/hello +stderr '\$GOPATH not set' + +[windows] env USERPROFILE=$WORK/home +[plan9] env home=$WORK/home +[!windows] [!plan9] env HOME=$WORK/home +env GOPATH= +env GOROOT=$WORK/home/go/ +! go get -d github.com/golang/example/hello +stderr '\$GOPATH not set' diff --git a/libgo/go/cmd/go/testdata/script/get_insecure.txt b/libgo/go/cmd/go/testdata/script/get_insecure.txt new file mode 100644 index 0000000..69930f7 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_insecure.txt @@ -0,0 +1,57 @@ +# TODO(matloob): Split this test into two? It's one of the slowest tests we have. + +[!net] skip +[!exec:git] skip + +env PATH=$WORK/tmp/bin${:}$PATH +go build -o $WORK/tmp/bin/ssh ssh.go + +# GOPATH: Set up +env GO111MODULE=off + +# GOPATH: Try go get -d of HTTP-only repo (should fail). +! go get -d insecure.go-get-issue-15410.appspot.com/pkg/p + +# GOPATH: Try again with GOINSECURE (should succeed). +env GOINSECURE=insecure.go-get-issue-15410.appspot.com +go get -d insecure.go-get-issue-15410.appspot.com/pkg/p + +# GOPATH: Try updating without GOINSECURE (should fail). +env GOINSECURE='' +! go get -d -u -f insecure.go-get-issue-15410.appspot.com/pkg/p + +# Modules: Set up +env GOPATH=$WORK/m/gp +mkdir $WORK/m +cp module_file $WORK/m/go.mod +cd $WORK/m +env GO111MODULE=on +env GOPROXY='' + +# Modules: Try go get -d of HTTP-only repo (should fail). +! go get -d insecure.go-get-issue-15410.appspot.com/pkg/p + +# Modules: Try again with GOINSECURE (should succeed). +env GOINSECURE=insecure.go-get-issue-15410.appspot.com +env GONOSUMDB=insecure.go-get-issue-15410.appspot.com +go get -d insecure.go-get-issue-15410.appspot.com/pkg/p + +# Modules: Try updating without GOINSECURE (should fail). +env GOINSECURE='' +env GONOSUMDB='' +! go get -d -u -f insecure.go-get-issue-15410.appspot.com/pkg/p + +go list -m ... +stdout 'insecure.go-get-issue' + +-- ssh.go -- +// stub out uses of ssh by go get +package main + +import "os" + +func main() { + os.Exit(1) +} +-- module_file -- +module m diff --git a/libgo/go/cmd/go/testdata/script/get_insecure_custom_domain.txt b/libgo/go/cmd/go/testdata/script/get_insecure_custom_domain.txt new file mode 100644 index 0000000..7eba42e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_insecure_custom_domain.txt @@ -0,0 +1,8 @@ +[!net] skip +[!exec:git] skip +env GO111MODULE=off + +! go get -d insecure.go-get-issue-15410.appspot.com/pkg/p + +env GOINSECURE=insecure.go-get-issue-15410.appspot.com +go get -d insecure.go-get-issue-15410.appspot.com/pkg/p diff --git a/libgo/go/cmd/go/testdata/script/get_insecure_env.txt b/libgo/go/cmd/go/testdata/script/get_insecure_env.txt new file mode 100644 index 0000000..8d88427 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_insecure_env.txt @@ -0,0 +1,29 @@ +[!net] skip +[!exec:git] skip + +# GOPATH: Set up +env GO111MODULE=off + +# GOPATH: Try go get -d of HTTP-only repo (should fail). +! go get -d insecure.go-get-issue-15410.appspot.com/pkg/p + +# GOPATH: Try again with invalid GOINSECURE (should fail). +env GOINSECURE=insecure.go-get-issue-15410.appspot.com/pkg/q +! go get -d insecure.go-get-issue-15410.appspot.com/pkg/p + +# GOPATH: Try with correct GOINSECURE (should succeed). +env GOINSECURE=insecure.go-get-issue-15410.appspot.com/pkg/p +go get -d insecure.go-get-issue-15410.appspot.com/pkg/p + +# GOPATH: Try updating without GOINSECURE (should fail). +env GOINSECURE= +! go get -d -u -f insecure.go-get-issue-15410.appspot.com/pkg/p + +# GOPATH: Try updating with GOINSECURE glob (should succeed). +env GOINSECURE=*.go-get-*.appspot.com +go get -d -u -f insecure.go-get-issue-15410.appspot.com/pkg/p + +# GOPATH: Try updating with GOINSECURE base URL (should succeed). +env GOINSECURE=insecure.go-get-issue-15410.appspot.com +go get -d -u -f insecure.go-get-issue-15410.appspot.com/pkg/p + diff --git a/libgo/go/cmd/go/testdata/script/get_insecure_no_longer_supported.txt b/libgo/go/cmd/go/testdata/script/get_insecure_no_longer_supported.txt new file mode 100644 index 0000000..2517664 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_insecure_no_longer_supported.txt @@ -0,0 +1,13 @@ +# GOPATH: Set up +env GO111MODULE=off + +# GOPATH: Fetch with insecure, should error +! go get -insecure test +stderr 'go get: -insecure flag is no longer supported; use GOINSECURE instead' + +# Modules: Set up +env GO111MODULE=on + +# Modules: Fetch with insecure, should error +! go get -insecure test +stderr 'go get: -insecure flag is no longer supported; use GOINSECURE instead' diff --git a/libgo/go/cmd/go/testdata/script/get_insecure_redirect.txt b/libgo/go/cmd/go/testdata/script/get_insecure_redirect.txt index 0478d1f..fb5f269 100644 --- a/libgo/go/cmd/go/testdata/script/get_insecure_redirect.txt +++ b/libgo/go/cmd/go/testdata/script/get_insecure_redirect.txt @@ -1,4 +1,4 @@ -# golang.org/issue/29591: 'go get' was following plain-HTTP redirects even without -insecure. +# golang.org/issue/29591: 'go get' was following plain-HTTP redirects even without -insecure (now replaced by GOINSECURE). # golang.org/issue/34049: 'go get' would panic in case of an insecure redirect in GOPATH mode [!net] skip @@ -9,4 +9,5 @@ env GO111MODULE=off ! go get -d vcs-test.golang.org/insecure/go/insecure stderr 'redirected .* to insecure URL' -go get -d -insecure vcs-test.golang.org/insecure/go/insecure +env GOINSECURE=vcs-test.golang.org/insecure/go/insecure +go get -d vcs-test.golang.org/insecure/go/insecure diff --git a/libgo/go/cmd/go/testdata/script/get_insecure_update.txt b/libgo/go/cmd/go/testdata/script/get_insecure_update.txt new file mode 100644 index 0000000..e1a1a23 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_insecure_update.txt @@ -0,0 +1,14 @@ +[!net] skip +[!exec:git] skip +env GO111MODULE=off + +# Clone the repo via HTTP manually. +exec git clone -q http://github.com/golang/example github.com/golang/example + +# Update without GOINSECURE should fail. +# We need -f to ignore import comments. +! go get -d -u -f github.com/golang/example/hello + +# Update with GOINSECURE should succeed. +env GOINSECURE=github.com/golang/example/hello +go get -d -u -f github.com/golang/example/hello diff --git a/libgo/go/cmd/go/testdata/script/get_internal_wildcard.txt b/libgo/go/cmd/go/testdata/script/get_internal_wildcard.txt new file mode 100644 index 0000000..ff20d4b --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_internal_wildcard.txt @@ -0,0 +1,6 @@ +[!net] skip +[!exec:git] skip +env GO111MODULE=off + +# This used to fail with errors about internal packages +go get github.com/rsc/go-get-issue-11960/... diff --git a/libgo/go/cmd/go/testdata/script/get_issue11307.txt b/libgo/go/cmd/go/testdata/script/get_issue11307.txt new file mode 100644 index 0000000..9d6b7dd --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_issue11307.txt @@ -0,0 +1,9 @@ +# go get -u was not working except in checkout directory + +[!net] skip +[!exec:git] skip +env GO111MODULE=off + +env GOPATH=$WORK/tmp/gopath +go get github.com/rsc/go-get-issue-11307 +go get -u github.com/rsc/go-get-issue-11307 # was failing diff --git a/libgo/go/cmd/go/testdata/script/get_legacy.txt b/libgo/go/cmd/go/testdata/script/get_legacy.txt new file mode 100644 index 0000000..938d428 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_legacy.txt @@ -0,0 +1,58 @@ +# This test was converted from a test in vendor_test.go (which no longer exists). +# That seems to imply that it's about vendoring semantics, but the test doesn't +# use 'go -mod=vendor' (and none of the fetched repos have vendor folders). +# The test still seems to be useful as a test of direct-mode go get. + +[short] skip +[!exec:git] skip +env GO111MODULE=off + +env GOPATH=$WORK/tmp/d1 +go get vcs-test.golang.org/git/modlegacy1-old.git/p1 +go list -f '{{.Deps}}' vcs-test.golang.org/git/modlegacy1-old.git/p1 +stdout 'new.git/p2' # old/p1 should depend on new/p2 +! stdout new.git/v2/p2 # old/p1 should NOT depend on new/v2/p2 +go build vcs-test.golang.org/git/modlegacy1-old.git/p1 vcs-test.golang.org/git/modlegacy1-new.git/p1 +! stdout . + +env GOPATH=$WORK/tmp/d2 + +rm $GOPATH +go get github.com/rsc/vgotest5 +go get github.com/rsc/vgotest4 +go get github.com/myitcv/vgo_example_compat + +rm $GOPATH +go get github.com/rsc/vgotest4 +go get github.com/rsc/vgotest5 +go get github.com/myitcv/vgo_example_compat + +rm $GOPATH +go get github.com/rsc/vgotest4 github.com/rsc/vgotest5 +go get github.com/myitcv/vgo_example_compat + +rm $GOPATH +go get github.com/rsc/vgotest5 github.com/rsc/vgotest4 +go get github.com/myitcv/vgo_example_compat + +rm $GOPATH +go get github.com/myitcv/vgo_example_compat +go get github.com/rsc/vgotest5 github.com/rsc/vgotest4 + +rm $GOPATH +go get github.com/myitcv/vgo_example_compat github.com/rsc/vgotest4 github.com/rsc/vgotest5 + +rm $GOPATH +go get github.com/myitcv/vgo_example_compat github.com/rsc/vgotest5 github.com/rsc/vgotest4 + +rm $GOPATH +go get github.com/rsc/vgotest4 github.com/myitcv/vgo_example_compat github.com/rsc/vgotest5 + +rm $GOPATH +go get github.com/rsc/vgotest4 github.com/rsc/vgotest5 github.com/myitcv/vgo_example_compat + +rm $GOPATH +go get github.com/rsc/vgotest5 github.com/myitcv/vgo_example_compat github.com/rsc/vgotest4 + +rm $GOPATH +go get github.com/rsc/vgotest5 github.com/rsc/vgotest4 github.com/myitcv/vgo_example_compat diff --git a/libgo/go/cmd/go/testdata/script/get_non_pkg.txt b/libgo/go/cmd/go/testdata/script/get_non_pkg.txt new file mode 100644 index 0000000..a878530 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_non_pkg.txt @@ -0,0 +1,14 @@ +[!net] skip +[!exec:git] skip + +env GOBIN=$WORK/tmp/gobin +env GO111MODULE=off + +! go get -d golang.org/x/tools +stderr 'golang.org/x/tools: no Go files' + +! go get -d -u golang.org/x/tools +stderr 'golang.org/x/tools: no Go files' + +! go get -d golang.org/x/tools +stderr 'golang.org/x/tools: no Go files'
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/get_race.txt b/libgo/go/cmd/go/testdata/script/get_race.txt new file mode 100644 index 0000000..16a560a --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_race.txt @@ -0,0 +1,8 @@ +# Tests issue #20502 + +[!net] skip +[!exec:git] skip +[!race] skip +env GO111MODULE=off + +go get -race github.com/rsc/go-get-issue-9224-cmd diff --git a/libgo/go/cmd/go/testdata/script/get_test_only.txt b/libgo/go/cmd/go/testdata/script/get_test_only.txt new file mode 100644 index 0000000..a3f38dd --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_test_only.txt @@ -0,0 +1,6 @@ +[!net] skip +[!exec:git] skip +env GO111MODULE=off + +go get golang.org/x/tour/content... +go get -t golang.org/x/tour/content... diff --git a/libgo/go/cmd/go/testdata/script/get_update.txt b/libgo/go/cmd/go/testdata/script/get_update.txt new file mode 100644 index 0000000..9afce6a --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_update.txt @@ -0,0 +1,25 @@ +# Tests Issue #9224 +# The recursive updating was trying to walk to +# former dependencies, not current ones. + +[!net] skip +[!exec:git] skip +env GO111MODULE=off + +# Rewind +go get github.com/rsc/go-get-issue-9224-cmd +cd $GOPATH/src/github.com/rsc/go-get-issue-9224-lib +exec git reset --hard HEAD~ +cd $GOPATH/src + +# Run get +go get -u 'github.com/rsc/go-get-issue-9224-cmd' + +# (Again with -d -u) Rewind +go get github.com/rsc/go-get-issue-9224-cmd +cd $GOPATH/src/github.com/rsc/go-get-issue-9224-lib +exec git reset --hard HEAD~ +cd $GOPATH/src + +# (Again with -d -u) Run get +go get -d -u 'github.com/rsc/go-get-issue-9224-cmd' diff --git a/libgo/go/cmd/go/testdata/script/get_update_all.txt b/libgo/go/cmd/go/testdata/script/get_update_all.txt new file mode 100644 index 0000000..2b75849 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_update_all.txt @@ -0,0 +1,9 @@ +# Issue 14444: go get -u .../ duplicate loads errors +# Check that go get update -u ... does not try to load duplicates + +[!net] skip + +env GO111MODULE=off + +go get -u -n .../ +! stderr 'duplicate loads of' # make sure old packages are removed from cache diff --git a/libgo/go/cmd/go/testdata/script/get_update_unknown_protocol.txt b/libgo/go/cmd/go/testdata/script/get_update_unknown_protocol.txt new file mode 100644 index 0000000..b00adea --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_update_unknown_protocol.txt @@ -0,0 +1,14 @@ +[!net] skip +[!exec:git] skip +env GO111MODULE=off + +# Clone the repo via HTTPS manually. +exec git clone -q https://github.com/golang/example github.com/golang/example + +# Configure the repo to use a protocol unknown to cmd/go +# that still actually works. +cd github.com/golang/example +exec git remote set-url origin xyz://github.com/golang/example +exec git config --local url.https://github.com/.insteadOf xyz://github.com/ + +go get -d -u -f github.com/golang/example/hello diff --git a/libgo/go/cmd/go/testdata/script/get_update_wildcard.txt b/libgo/go/cmd/go/testdata/script/get_update_wildcard.txt new file mode 100644 index 0000000..4e66004 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_update_wildcard.txt @@ -0,0 +1,16 @@ +# Issue 14450: go get -u .../ tried to import not downloaded package + +[!net] skip +[!exec:git] skip +env GO111MODULE=off + +go get github.com/tmwh/go-get-issue-14450/a +! go get -u .../ +stderr 'cannot find package.*d-dependency/e' + +# Even though get -u failed, the source for others should be downloaded. +exists github.com/tmwh/go-get-issue-14450/b +exists github.com/tmwh/go-get-issue-14450-b-dependency/c +exists github.com/tmwh/go-get-issue-14450-b-dependency/d + +! exists github.com/tmwh/go-get-issue-14450-c-dependency/e diff --git a/libgo/go/cmd/go/testdata/script/get_vcs_error_message.txt b/libgo/go/cmd/go/testdata/script/get_vcs_error_message.txt new file mode 100644 index 0000000..8dc84fc --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_vcs_error_message.txt @@ -0,0 +1,9 @@ +# Test that the Version Control error message includes the correct directory +env GO111MODULE=off +! go get -u foo +stderr gopath(\\\\|/)src(\\\\|/)foo + +-- foo/foo.go -- +package foo +-- math/math.go -- +package math diff --git a/libgo/go/cmd/go/testdata/script/get_vendor.txt b/libgo/go/cmd/go/testdata/script/get_vendor.txt new file mode 100644 index 0000000..4ebb8a2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_vendor.txt @@ -0,0 +1,95 @@ +[short] skip +env GO111MODULE=off + +cd $GOPATH/src/v +go run m.go +go test +go list -f '{{.Imports}}' +stdout 'v/vendor/vendor.org/p' +go list -f '{{.TestImports}}' +stdout 'v/vendor/vendor.org/p' +go get -d +go get -t -d + +[!net] stop +[!exec:git] stop + +cd $GOPATH/src + +# Update +go get 'github.com/rsc/go-get-issue-11864' +go get -u 'github.com/rsc/go-get-issue-11864' +exists github.com/rsc/go-get-issue-11864/vendor + +# get -u +rm $GOPATH +mkdir $GOPATH/src +go get -u 'github.com/rsc/go-get-issue-11864' +exists github.com/rsc/go-get-issue-11864/vendor + +# get -t -u +rm $GOPATH +mkdir $GOPATH/src +go get -t -u 'github.com/rsc/go-get-issue-11864/...' +exists github.com/rsc/go-get-issue-11864/vendor + +# Submodules +rm $GOPATH +mkdir $GOPATH/src +go get -d 'github.com/rsc/go-get-issue-12612' +go get -u -d 'github.com/rsc/go-get-issue-12612' +exists github.com/rsc/go-get-issue-12612/vendor/golang.org/x/crypto/.git + +# Bad vendor (bad/imp) +rm $GOPATH +mkdir $GOPATH/src +! go get -t -u 'github.com/rsc/go-get-issue-18219/bad/imp' +stderr 'must be imported as' +! exists github.com/rsc/go-get-issue-11864/vendor + +# Bad vendor (bad/imp2) +rm $GOPATH +mkdir $GOPATH/src +! go get -t -u 'github.com/rsc/go-get-issue-18219/bad/imp2' +stderr 'must be imported as' +! exists github.com/rsc/go-get-issue-11864/vendor + +# Bad vendor (bad/imp3) +rm $GOPATH +mkdir $GOPATH/src +! go get -t -u 'github.com/rsc/go-get-issue-18219/bad/imp3' +stderr 'must be imported as' +! exists github.com/rsc/go-get-issue-11864/vendor + +# Bad vendor (bad/...) +rm $GOPATH +mkdir $GOPATH/src +! go get -t -u 'github.com/rsc/go-get-issue-18219/bad/...' +stderr 'must be imported as' +! exists github.com/rsc/go-get-issue-11864/vendor + +-- v/m.go -- +package main + +import ( + "fmt" + "vendor.org/p" +) + +func main() { + fmt.Println(p.C) +} +-- v/m_test.go -- +package main +import ( + "fmt" + "testing" + "vendor.org/p" +) + +func TestNothing(t *testing.T) { + fmt.Println(p.C) +} +-- v/vendor/vendor.org/p/p.go -- +package p +const C = 1 diff --git a/libgo/go/cmd/go/testdata/script/gopath_vendor_dup_err.txt b/libgo/go/cmd/go/testdata/script/gopath_vendor_dup_err.txt new file mode 100644 index 0000000..22e6048 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/gopath_vendor_dup_err.txt @@ -0,0 +1,25 @@ +[!net] skip +env GO111MODULE=off + +# Issue 17119: Test more duplicate load errors. +! go build dupload +! stderr 'duplicate load|internal error' +stderr 'dupload/vendor/p must be imported as p' + +-- dupload/dupload.go -- +package main + +import ( + _ "dupload/p2" + _ "p" +) + +func main() {} +-- dupload/p/p.go -- +package p +-- dupload/p2/p2.go -- +package p2 + +import _ "dupload/vendor/p" +-- dupload/vendor/p/p.go -- +package p diff --git a/libgo/go/cmd/go/testdata/script/goroot_executable.txt b/libgo/go/cmd/go/testdata/script/goroot_executable.txt new file mode 100644 index 0000000..fdbcde0 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/goroot_executable.txt @@ -0,0 +1,111 @@ +[gccgo] skip + +mkdir $WORK/new/bin + +# In this test, we are specifically checking the logic for deriving +# the value of GOROOT from runtime.GOROOT. +# GOROOT_FINAL changes the default behavior of runtime.GOROOT, +# and will thus cause the test to fail if it is set when our +# new cmd/go is built. +env GOROOT_FINAL= + +go build -o $WORK/new/bin/go$GOEXE cmd/go & +go build -o $WORK/bin/check$GOEXE check.go & +wait + +env TESTGOROOT=$GOROOT +env GOROOT= + +# Relocated Executable +# cp $TESTGOROOT/bin/go$GOEXE $WORK/new/bin/go$GOEXE +exec $WORK/bin/check$GOEXE $WORK/new/bin/go$GOEXE $TESTGOROOT + +# Relocated Tree: +# If the binary is sitting in a bin dir next to ../pkg/tool, that counts as a GOROOT, +# so it should find the new tree. +mkdir $WORK/new/pkg/tool +exec $WORK/bin/check$GOEXE $WORK/new/bin/go$GOEXE $WORK/new + +[!symlink] stop 'The rest of the test cases require symlinks' + +# Symlinked Executable: +# With a symlink into go tree, we should still find the go tree. +mkdir $WORK/other/bin +symlink $WORK/other/bin/go$GOEXE -> $WORK/new/bin/go$GOEXE +exec $WORK/bin/check$GOEXE $WORK/new/bin/go$GOEXE $WORK/new + +rm $WORK/new/pkg + +# Runtime GOROOT: +# Binaries built in the new tree should report the +# new tree when they call runtime.GOROOT. +symlink $WORK/new/src -> $TESTGOROOT/src +symlink $WORK/new/pkg -> $TESTGOROOT/pkg +exec $WORK/new/bin/go$GOEXE run check_runtime_goroot.go $WORK/new + +-- check.go -- +package main + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" +) + +func main() { + exe := os.Args[1] + want := os.Args[2] + cmd := exec.Command(exe, "env", "GOROOT") + out, err := cmd.CombinedOutput() + if err != nil { + fmt.Fprintf(os.Stderr, "%s env GOROOT: %v, %s\n", exe, err, out) + os.Exit(1) + } + goroot, err := filepath.EvalSymlinks(strings.TrimSpace(string(out))) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + want, err = filepath.EvalSymlinks(want) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if !strings.EqualFold(goroot, want) { + fmt.Fprintf(os.Stderr, "go env GOROOT:\nhave %s\nwant %s\n", goroot, want) + os.Exit(1) + } + fmt.Fprintf(os.Stderr, "go env GOROOT: %s\n", goroot) + +} +-- check_runtime_goroot.go -- +package main + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "strings" +) + +func main() { + goroot, err := filepath.EvalSymlinks(runtime.GOROOT()) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + want, err := filepath.EvalSymlinks(os.Args[1]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if !strings.EqualFold(goroot, want) { + fmt.Fprintf(os.Stderr, "go env GOROOT:\nhave %s\nwant %s\n", goroot, want) + os.Exit(1) + } + fmt.Fprintf(os.Stderr, "go env GOROOT: %s\n", goroot) + +} diff --git a/libgo/go/cmd/go/testdata/script/govcs.txt b/libgo/go/cmd/go/testdata/script/govcs.txt new file mode 100644 index 0000000..4180d7d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/govcs.txt @@ -0,0 +1,174 @@ +env GO111MODULE=on +env proxy=$GOPROXY +env GOPROXY=direct + +# GOVCS stops go get +env GOVCS='*:none' +! go get github.com/google/go-cmp +stderr '^go get: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$' +env GOPRIVATE='github.com/google' +! go get github.com/google/go-cmp +stderr '^go get: GOVCS disallows using git for private github.com/google/go-cmp; see ''go help vcs''$' + +# public pattern works +env GOPRIVATE='github.com/google' +env GOVCS='public:all,private:none' +! go get github.com/google/go-cmp +stderr '^go get: GOVCS disallows using git for private github.com/google/go-cmp; see ''go help vcs''$' + +# private pattern works +env GOPRIVATE='hubgit.com/google' +env GOVCS='private:all,public:none' +! go get github.com/google/go-cmp +stderr '^go get: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$' + +# other patterns work (for more patterns, see TestGOVCS) +env GOPRIVATE= +env GOVCS='github.com:svn|hg' +! go get github.com/google/go-cmp +stderr '^go get: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$' +env GOVCS='github.com/google/go-cmp/inner:git,github.com:svn|hg' +! go get github.com/google/go-cmp +stderr '^go get: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$' + +# bad patterns are reported (for more bad patterns, see TestGOVCSErrors) +env GOVCS='git' +! go get github.com/google/go-cmp +stderr '^go get github.com/google/go-cmp: malformed entry in GOVCS \(missing colon\): "git"$' + +env GOVCS=github.com:hg,github.com:git +! go get github.com/google/go-cmp +stderr '^go get github.com/google/go-cmp: unreachable pattern in GOVCS: "github.com:git" after "github.com:hg"$' + +# bad GOVCS patterns do not stop commands that do not need to check VCS +go list +env GOPROXY=$proxy +go get -d rsc.io/quote # ok because used proxy +env GOPROXY=direct + +# svn is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.svn/hello +stderr '^go get rsc.io/nonexist.svn/hello: GOVCS disallows using svn for public rsc.io/nonexist.svn; see ''go help vcs''$' + +# fossil is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.fossil/hello +stderr '^go get rsc.io/nonexist.fossil/hello: GOVCS disallows using fossil for public rsc.io/nonexist.fossil; see ''go help vcs''$' + +# bzr is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.bzr/hello +stderr '^go get rsc.io/nonexist.bzr/hello: GOVCS disallows using bzr for public rsc.io/nonexist.bzr; see ''go help vcs''$' + +# git is OK by default +env GOVCS= +env GONOSUMDB='*' +[net] [exec:git] [!short] go get rsc.io/sampler + +# hg is OK by default +env GOVCS= +env GONOSUMDB='*' +[net] [exec:hg] [!short] go get vcs-test.golang.org/go/custom-hg-hello + +# git can be disallowed +env GOVCS=public:hg +! go get rsc.io/nonexist.git/hello +stderr '^go get rsc.io/nonexist.git/hello: GOVCS disallows using git for public rsc.io/nonexist.git; see ''go help vcs''$' + +# hg can be disallowed +env GOVCS=public:git +! go get rsc.io/nonexist.hg/hello +stderr '^go get rsc.io/nonexist.hg/hello: GOVCS disallows using hg for public rsc.io/nonexist.hg; see ''go help vcs''$' + +# Repeat in GOPATH mode. Error texts slightly different. + +env GO111MODULE=off + +# GOVCS stops go get +env GOVCS='*:none' +! go get github.com/google/go-cmp +stderr '^package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$' +env GOPRIVATE='github.com/google' +! go get github.com/google/go-cmp +stderr '^package github.com/google/go-cmp: GOVCS disallows using git for private github.com/google/go-cmp; see ''go help vcs''$' + +# public pattern works +env GOPRIVATE='github.com/google' +env GOVCS='public:all,private:none' +! go get github.com/google/go-cmp +stderr '^package github.com/google/go-cmp: GOVCS disallows using git for private github.com/google/go-cmp; see ''go help vcs''$' + +# private pattern works +env GOPRIVATE='hubgit.com/google' +env GOVCS='private:all,public:none' +! go get github.com/google/go-cmp +stderr '^package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$' + +# other patterns work (for more patterns, see TestGOVCS) +env GOPRIVATE= +env GOVCS='github.com:svn|hg' +! go get github.com/google/go-cmp +stderr '^package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$' +env GOVCS='github.com/google/go-cmp/inner:git,github.com:svn|hg' +! go get github.com/google/go-cmp +stderr '^package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp; see ''go help vcs''$' + +# bad patterns are reported (for more bad patterns, see TestGOVCSErrors) +env GOVCS='git' +! go get github.com/google/go-cmp +stderr '^package github.com/google/go-cmp: malformed entry in GOVCS \(missing colon\): "git"$' + +env GOVCS=github.com:hg,github.com:git +! go get github.com/google/go-cmp +stderr '^package github.com/google/go-cmp: unreachable pattern in GOVCS: "github.com:git" after "github.com:hg"$' + +# bad GOVCS patterns do not stop commands that do not need to check VCS +go list + +# svn is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.svn/hello +stderr '^package rsc.io/nonexist.svn/hello: GOVCS disallows using svn for public rsc.io/nonexist.svn; see ''go help vcs''$' + +# fossil is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.fossil/hello +stderr '^package rsc.io/nonexist.fossil/hello: GOVCS disallows using fossil for public rsc.io/nonexist.fossil; see ''go help vcs''$' + +# bzr is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.bzr/hello +stderr '^package rsc.io/nonexist.bzr/hello: GOVCS disallows using bzr for public rsc.io/nonexist.bzr; see ''go help vcs''$' + +# git is OK by default +env GOVCS= +env GONOSUMDB='*' +[net] [exec:git] [!short] go get rsc.io/sampler + +# hg is OK by default +env GOVCS= +env GONOSUMDB='*' +[net] [exec:hg] [!short] go get vcs-test.golang.org/go/custom-hg-hello + +# git can be disallowed +env GOVCS=public:hg +! go get rsc.io/nonexist.git/hello +stderr '^package rsc.io/nonexist.git/hello: GOVCS disallows using git for public rsc.io/nonexist.git; see ''go help vcs''$' + +# hg can be disallowed +env GOVCS=public:git +! go get rsc.io/nonexist.hg/hello +stderr '^package rsc.io/nonexist.hg/hello: GOVCS disallows using hg for public rsc.io/nonexist.hg; see ''go help vcs''$' + +-- go.mod -- +module m + +-- p.go -- +package p diff --git a/libgo/go/cmd/go/testdata/script/import_cycle.txt b/libgo/go/cmd/go/testdata/script/import_cycle.txt new file mode 100644 index 0000000..901f43c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/import_cycle.txt @@ -0,0 +1,12 @@ +env GO111MODULE=off + +! go build selfimport +stderr -count=1 'import cycle not allowed' + +# 'go list' shouldn't hang forever. +go list -e -json selfimport + +-- $GOPATH/src/selfimport/selfimport.go -- +package selfimport + +import "selfimport" diff --git a/libgo/go/cmd/go/testdata/script/import_ignore.txt b/libgo/go/cmd/go/testdata/script/import_ignore.txt new file mode 100644 index 0000000..83a39a0 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/import_ignore.txt @@ -0,0 +1,11 @@ +cp go.mod go.mod.orig +go mod tidy +cmp go.mod go.mod.orig + +-- go.mod -- +module m.test + +go 1.16 +-- .ignore.go -- +package p +import _ "golang.org/x/mod/modfile"
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/install_cgo_excluded.txt b/libgo/go/cmd/go/testdata/script/install_cgo_excluded.txt new file mode 100644 index 0000000..5a2b460 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/install_cgo_excluded.txt @@ -0,0 +1,15 @@ +env CGO_ENABLED=0 + +! go install cgotest +stderr 'build constraints exclude all Go files' + +-- go.mod -- +module cgotest + +go 1.16 +-- m.go -- +package cgotest + +import "C" + +var _ C.int diff --git a/libgo/go/cmd/go/testdata/script/install_msan_and_race_require_cgo.txt b/libgo/go/cmd/go/testdata/script/install_msan_and_race_require_cgo.txt new file mode 100644 index 0000000..7985cd2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/install_msan_and_race_require_cgo.txt @@ -0,0 +1,18 @@ +# Tests Issue #21895 + +[!msan] [!race] skip 'skipping because both msan and the race detector are not supported' + +env CGO_ENABLED=0 + +[race] ! go install -race triv.go +[race] stderr '-race requires cgo' +[race] ! stderr '-msan' + +[msan] ! go install -msan triv.go +[msan] stderr '-msan requires cgo' +[msan] ! stderr '-race' + +-- triv.go -- +package main + +func main() {}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/install_relative_gobin_fail.txt b/libgo/go/cmd/go/testdata/script/install_relative_gobin_fail.txt new file mode 100644 index 0000000..aa14524 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/install_relative_gobin_fail.txt @@ -0,0 +1,12 @@ +env GOBIN=. +! go install +stderr 'cannot install, GOBIN must be an absolute path' + +-- go.mod -- +module triv + +go 1.16 +-- triv.go -- +package main + +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/install_shadow_gopath.txt b/libgo/go/cmd/go/testdata/script/install_shadow_gopath.txt new file mode 100644 index 0000000..2039d9e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/install_shadow_gopath.txt @@ -0,0 +1,20 @@ +# Tests Issue #3562 +# go get foo.io (not foo.io/subdir) was not working consistently. + +[!net] skip + +env GO111MODULE=off +env GOPATH=$WORK/gopath1${:}$WORK/gopath2 + +mkdir $WORK/gopath1/src/test +mkdir $WORK/gopath2/src/test +cp main.go $WORK/gopath2/src/test/main.go +cd $WORK/gopath2/src/test + +! go install +stderr 'no install location for.*gopath2.src.test: hidden by .*gopath1.src.test' + +-- main.go -- +package main + +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/issue36000.txt b/libgo/go/cmd/go/testdata/script/issue36000.txt new file mode 100644 index 0000000..4173275 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/issue36000.txt @@ -0,0 +1,6 @@ +# Tests golang.org/issue/36000 + +[!cgo] skip + +# go env with CGO flags should not make NUL file +go env CGO_CFLAGS diff --git a/libgo/go/cmd/go/testdata/script/ldflag.txt b/libgo/go/cmd/go/testdata/script/ldflag.txt new file mode 100644 index 0000000..258af8d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/ldflag.txt @@ -0,0 +1,44 @@ +# Issue #42565 + +[!cgo] skip + +# We can't build package bad, which uses #cgo LDFLAGS. +cd bad +! go build +stderr no-such-warning + +# We can build package ok with the same flags in CGO_LDFLAGS. +env CGO_LDFLAGS=-Wno-such-warning -Wno-unknown-warning-option +cd ../ok +go build + +# Build a main program that actually uses LDFLAGS. +cd .. +[!gccgo] go build -ldflags=-v + +# Because we passed -v the Go linker should print the external linker +# command which should include the flag we passed in CGO_LDFLAGS. +[!gccgo] stderr no-such-warning + +-- go.mod -- +module ldflag + +-- bad/bad.go -- +package bad + +// #cgo LDFLAGS: -Wno-such-warning -Wno-unknown-warning +import "C" + +func F() {} +-- ok/ok.go -- +package ok + +import "C" + +func F() {} +-- main.go -- +package main + +import _ "ldflag/ok" + +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/link_matching_actionid.txt b/libgo/go/cmd/go/testdata/script/link_matching_actionid.txt new file mode 100644 index 0000000..b8d423d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/link_matching_actionid.txt @@ -0,0 +1,38 @@ +# Checks that an identical binary is built with -trimpath from the same +# source files, with GOROOT in two different locations. +# Verifies golang.org/issue/38989 + +[short] skip +[!symlink] skip + +# Symlink the compiler to a local path +env GOROOT=$WORK/goroot1 +symlink $GOROOT -> $TESTGO_GOROOT + +# Set up fresh GOCACHE +env GOCACHE=$WORK/gocache1 +mkdir $GOCACHE + +# Build a simple binary +go build -o binary1 -trimpath -x main.go + +# Now repeat the same process with the compiler at a different local path +env GOROOT=$WORK/goroot2 +symlink $GOROOT -> $TESTGO_GOROOT + +env GOCACHE=$WORK/gocache2 +mkdir $GOCACHE + +go build -o binary2 -trimpath -x main.go + +# Check that the binaries match exactly +go tool buildid binary1 +cp stdout buildid1 +go tool buildid binary2 +cp stdout buildid2 +cmp buildid1 buildid2 + + +-- main.go -- +package main +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/list_case_collision.txt b/libgo/go/cmd/go/testdata/script/list_case_collision.txt new file mode 100644 index 0000000..181a202 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_case_collision.txt @@ -0,0 +1,41 @@ +# Tests golang.org/issue/4773 + +go list -json example/a +stdout 'case-insensitive import collision' + +! go build example/a +stderr 'case-insensitive import collision' + +# List files explicitly on command line, to encounter case-checking +# logic even on case-insensitive filesystems. +cp b/file.go b/FILE.go # no-op on case-insensitive filesystems +! go list b/file.go b/FILE.go +stderr 'case-insensitive file name collision' + +mkdir a/Pkg # no-op on case-insensitive filesystems +cp a/pkg/pkg.go a/Pkg/pkg.go # no-op on case-insensitive filesystems +! go list example/a/pkg example/a/Pkg + +# Test that the path reported with an indirect import is correct. +cp b/file.go b/FILE.go +[case-sensitive] ! go build example/c +[case-sensitive] stderr '^package example/c\n\timports example/b: case-insensitive file name collision: "FILE.go" and "file.go"$' + +-- go.mod -- +module example + +go 1.16 +-- a/a.go -- +package p +import ( + _ "example/a/pkg" + _ "example/a/Pkg" +) +-- a/pkg/pkg.go -- +package pkg +-- b/file.go -- +package b +-- c/c.go -- +package c + +import _ "example/b" diff --git a/libgo/go/cmd/go/testdata/script/list_cgo_compiled_importmap.txt b/libgo/go/cmd/go/testdata/script/list_cgo_compiled_importmap.txt new file mode 100644 index 0000000..3d68ef3 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_cgo_compiled_importmap.txt @@ -0,0 +1,38 @@ +# Regression test for https://golang.org/issue/46462. +# +# The "runtime/cgo" import found in synthesized .go files (reported in +# the CompiledGoFiles field) should have a corresponding entry in the +# ImportMap field when a runtime/cgo variant (such as a test variant) +# will be used. + +[short] skip # -compiled can be slow (because it compiles things) +[!cgo] skip + +env CGO_ENABLED=1 +env GOFLAGS=-tags=netcgo # Force net to use cgo even on Windows. + + +# "runtime/cgo [runtime.test]" appears in the the test dependencies of "runtime", +# because "runtime/cgo" itself depends on "runtime" + +go list -deps -test -compiled -f '{{if eq .ImportPath "net [runtime.test]"}}{{printf "%q" .Imports}}{{end}}' runtime + + # Control case: the explicitly-imported package "sync" is a test variant, + # because "sync" depends on "runtime". +stdout '"sync \[runtime\.test\]"' +! stdout '"sync"' + + # Experiment: the implicitly-imported package "runtime/cgo" is also a test variant, + # because "runtime/cgo" also depends on "runtime". +stdout '"runtime/cgo \[runtime\.test\]"' +! stdout '"runtime/cgo"' + + +# Because the import of "runtime/cgo" in the cgo-generated file actually refers +# to "runtime/cgo [runtime.test]", the latter should be listed in the ImportMap. +# BUG(#46462): Today, it is not. + +go list -deps -test -compiled -f '{{if eq .ImportPath "net [runtime.test]"}}{{printf "%q" .ImportMap}}{{end}}' runtime + +stdout '"sync":"sync \[runtime\.test\]"' # control +stdout '"runtime/cgo":"runtime/cgo \[runtime\.test\]"' # experiment diff --git a/libgo/go/cmd/go/testdata/script/list_dedup_packages.txt b/libgo/go/cmd/go/testdata/script/list_dedup_packages.txt new file mode 100644 index 0000000..30c68dd --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_dedup_packages.txt @@ -0,0 +1,31 @@ +# Setup +env GO111MODULE=off +mkdir $WORK/tmp/testdata/src/xtestonly +cp f.go $WORK/tmp/testdata/src/xtestonly/f.go +cp f_test.go $WORK/tmp/testdata/src/xtestonly/f_test.go +env GOPATH=$WORK/tmp/testdata +cd $WORK + +# Check output of go list to ensure no duplicates +go list xtestonly ./tmp/testdata/src/xtestonly/... +cmp stdout $WORK/gopath/src/wantstdout + +-- wantstdout -- +xtestonly +-- f.go -- +package xtestonly + +func F() int { return 42 } +-- f_test.go -- +package xtestonly_test + +import ( + "testing" + "xtestonly" +) + +func TestF(t *testing.T) { + if x := xtestonly.F(); x != 42 { + t.Errorf("f.F() = %d, want 42", x) + } +} diff --git a/libgo/go/cmd/go/testdata/script/list_err_cycle.txt b/libgo/go/cmd/go/testdata/script/list_err_cycle.txt new file mode 100644 index 0000000..44b82a6 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_err_cycle.txt @@ -0,0 +1,15 @@ +# Check that we don't get infinite recursion when loading a package with +# an import cycle and another error. Verifies #25830. +! go list +stderr 'found packages a \(a.go\) and b \(b.go\)' + +-- go.mod -- +module errcycle + +go 1.16 +-- a.go -- +package a + +import _ "errcycle" +-- b.go -- +package b
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/list_err_stack.txt b/libgo/go/cmd/go/testdata/script/list_err_stack.txt new file mode 100644 index 0000000..a7be9fd --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_err_stack.txt @@ -0,0 +1,27 @@ + +# golang.org/issue/40544: regression in error stacks for parse errors + +env GO111MODULE=off +cd sandbox/foo +go list -e -json . +stdout '"sandbox/foo"' +stdout '"sandbox/bar"' +stdout '"Pos": "..(/|\\\\)bar(/|\\\\)bar.go:1:1"' +stdout '"Err": "expected ''package'', found ackage"' + +env GO111MODULE=on +go list -e -json . +stdout '"sandbox/foo"' +stdout '"sandbox/bar"' +stdout '"Pos": "..(/|\\\\)bar(/|\\\\)bar.go:1:1"' +stdout '"Err": "expected ''package'', found ackage"' + +-- sandbox/go.mod -- +module sandbox + +-- sandbox/foo/foo.go -- +package pkg + +import "sandbox/bar" +-- sandbox/bar/bar.go -- +ackage bar
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/list_find_nodeps.txt b/libgo/go/cmd/go/testdata/script/list_find_nodeps.txt new file mode 100644 index 0000000..e08ce78 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_find_nodeps.txt @@ -0,0 +1,49 @@ +# Issue #46092 +# go list -find should always return a package with an empty Deps list + +# The linker loads implicit dependencies +go list -find -f {{.Deps}} ./cmd +stdout '\[\]' + +# Cgo translation may add imports of "unsafe", "runtime/cgo" and "syscall" +go list -find -f {{.Deps}} ./cgo +stdout '\[\]' + +# SWIG adds imports of some standard packages +go list -find -f {{.Deps}} ./swig +stdout '\[\]' + +-- go.mod -- +module listfind + +-- cmd/main.go -- +package main + +func main() {} + +-- cgo/pkg.go -- +package cgopkg + +/* +#include <limits.h> +*/ +import "C" + +func F() { + println(C.INT_MAX) +} + +-- cgo/pkg_notcgo.go -- +//go:build !cgo +// +build !cgo + +package cgopkg + +func F() { + println(0) +} + +-- swig/pkg.go -- +package swigpkg + +-- swig/a.swigcxx -- diff --git a/libgo/go/cmd/go/testdata/script/list_gofile_in_goroot.txt b/libgo/go/cmd/go/testdata/script/list_gofile_in_goroot.txt new file mode 100644 index 0000000..d3d7cc8 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_gofile_in_goroot.txt @@ -0,0 +1,78 @@ +# Return an error if the user tries to list a go source file directly in $GOROOT/src. +# Tests golang.org/issue/36587 + +[gccgo] skip + +env GOROOT=$WORK/goroot +env GOPATH=$WORK/gopath + +go env GOROOT +stdout $WORK[/\\]goroot + +# switch to GOROOT/src +cd $GOROOT/src + +# In module mode, 'go list ./...' should not treat .go files in GOROOT/src as an +# importable package, since that directory has no valid import path. +env GO111MODULE=on +go list ... +stdout -count=1 '^.+$' +stdout '^fmt$' +! stdout foo + +go list ./... +stdout -count=1 '^.+$' +stdout '^fmt$' +! stdout foo + +go list std +stdout -count=1 '^.+$' +stdout '^fmt$' + +! go list . +stderr '^GOROOT/src is not an importable package$' + +# In GOPATH mode, 'go list ./...' should synthesize a legacy GOPATH-mode path — +# not a standard-library or empty path — for the errant package. +env GO111MODULE=off +go list ./... +stdout -count=2 '^.+$' # Both 'fmt' and GOROOT/src should be listed. +stdout '^fmt$' +[!windows] stdout ^_$WORK/goroot/src$ +[windows] stdout goroot/src$ # On windows the ":" in the volume name is mangled + +go list ... +! stdout goroot/src + +go list std +! stdout goroot/src + +go list . +[!windows] stdout ^_$WORK/goroot/src$ +[windows] stdout goroot/src$ + +# switch to GOPATH/src +cd $GOPATH/src + +# GO111MODULE=off,GOPATH +env GO111MODULE=off +go list ./... +[!windows] stdout ^_$WORK/gopath/src$ +[windows] stdout gopath/src$ + +go list all +! stdout gopath/src + +-- $WORK/goroot/src/go.mod -- +module std + +go 1.14 +-- $WORK/goroot/src/foo.go -- +package foo +-- $WORK/goroot/src/fmt/fmt.go -- +package fmt +-- $WORK/goroot/src/cmd/README -- +This directory must exist in order for the 'cmd' pattern to have something to +match against. +-- $GOPATH/src/foo.go -- +package foo diff --git a/libgo/go/cmd/go/testdata/script/list_gomod_in_gopath.txt b/libgo/go/cmd/go/testdata/script/list_gomod_in_gopath.txt new file mode 100644 index 0000000..064f33a --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_gomod_in_gopath.txt @@ -0,0 +1,23 @@ +# Issue 46119 + +# When a module is inside a GOPATH workspace, Package.Root should be set to +# Module.Dir instead of $GOPATH/src. + +env GOPATH=$WORK/tmp +cd $WORK/tmp/src/test + +go list -f {{.Root}} +stdout ^$PWD$ + +# Were we really inside a GOPATH workspace? +env GO111MODULE=off +go list -f {{.Root}} +stdout ^$WORK/tmp$ + +-- $WORK/tmp/src/test/go.mod -- +module test + +-- $WORK/tmp/src/test/main.go -- +package main + +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/list_json_with_f.txt b/libgo/go/cmd/go/testdata/script/list_json_with_f.txt new file mode 100644 index 0000000..2011a6e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_json_with_f.txt @@ -0,0 +1,20 @@ +[short] skip + +# list -json should generate output on stdout +go list -json ./... +stdout . +# list -f should generate output on stdout +go list -f '{{.}}' ./... +stdout . + +# test passing first -json then -f +! go list -json -f '{{.}}' ./... +stderr '^go list -f cannot be used with -json$' + +# test passing first -f then -json +! go list -f '{{.}}' -json ./... +stderr '^go list -f cannot be used with -json$' +-- go.mod -- +module m +-- list_test.go -- +package list_test diff --git a/libgo/go/cmd/go/testdata/script/list_load_err.txt b/libgo/go/cmd/go/testdata/script/list_load_err.txt new file mode 100644 index 0000000..0cfa7fb --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_load_err.txt @@ -0,0 +1,95 @@ +# go list -e -deps should list imports from any file it can read, even if +# other files in the same package cause go/build.Import to return an error. +# Verfifies golang.org/issue/38568 + +go list -e -deps ./scan +stdout m/want + +go list -e -deps ./multi +stdout m/want + +go list -e -deps ./constraint +stdout m/want + +[cgo] go list -e -test -deps ./cgotest +[cgo] stdout m/want + +[cgo] go list -e -deps ./cgoflag +[cgo] stdout m/want + + +# go list -e should include files with errors in GoFiles, TestGoFiles, and +# other lists, assuming they match constraints. +# Verifies golang.org/issue/39986 +go list -e -f '{{range .GoFiles}}{{.}},{{end}}' ./scan +stdout '^good.go,scan.go,$' + +go list -e -f '{{range .GoFiles}}{{.}},{{end}}' ./multi +stdout '^a.go,b.go,$' + +go list -e -f '{{range .GoFiles}}{{.}},{{end}}' ./constraint +stdout '^good.go,$' +go list -e -f '{{range .IgnoredGoFiles}}{{.}},{{end}}' ./constraint +stdout '^constraint.go,$' + +[cgo] go list -e -f '{{range .XTestGoFiles}}{{.}},{{end}}' ./cgotest +[cgo] stdout '^cgo_test.go,$' + +[cgo] go list -e -f '{{range .GoFiles}}{{.}},{{end}}' ./cgoflag +[cgo] stdout '^cgoflag.go,$' + +-- go.mod -- +module m + +go 1.14 + +-- want/want.go -- +package want + +-- scan/scan.go -- +// scan error +ʕ◔ϖ◔ʔ + +-- scan/good.go -- +package scan + +import _ "m/want" + +-- multi/a.go -- +package a + +-- multi/b.go -- +package b + +import _ "m/want" + +-- constraint/constraint.go -- +// +build !!nope + +package constraint + +-- constraint/good.go -- +package constraint + +import _ "m/want" + +-- cgotest/cgo_test.go -- +package cgo_test + +// cgo is not allowed in tests. +// See golang.org/issue/18647 + +import "C" +import ( + "testing" + _ "m/want" +) + +func Test(t *testing.T) {} + +-- cgoflag/cgoflag.go -- +package cgoflag + +// #cgo ʕ◔ϖ◔ʔ: + +import _ "m/want" diff --git a/libgo/go/cmd/go/testdata/script/list_module_when_error.txt b/libgo/go/cmd/go/testdata/script/list_module_when_error.txt new file mode 100644 index 0000000..844164c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_module_when_error.txt @@ -0,0 +1,19 @@ +# The Module field should be populated even if there is an error loading the package. + +env GO111MODULE=on + +go list -e -f {{.Module}} +stdout '^mod.com$' + +-- go.mod -- +module mod.com + +go 1.16 + +-- blah.go -- +package blah + +import _ "embed" + +//go:embed README.md +var readme string diff --git a/libgo/go/cmd/go/testdata/script/list_overlay.txt b/libgo/go/cmd/go/testdata/script/list_overlay.txt new file mode 100644 index 0000000..1153975 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_overlay.txt @@ -0,0 +1,63 @@ +# Test listing with overlays + +# Overlay in an existing directory +go list -overlay overlay.json -f '{{.GoFiles}}' . +stdout '^\[f.go\]$' + +# Overlays in a non-existing directory +go list -overlay overlay.json -f '{{.GoFiles}}' ./dir +stdout '^\[g.go\]$' + +# Overlays in an existing directory with already existing files +go list -overlay overlay.json -f '{{.GoFiles}}' ./dir2 +stdout '^\[h.go i.go\]$' + +# Overlay that removes a file from a directory +! go list ./dir3 # contains a file without a package statement +go list -overlay overlay.json -f '{{.GoFiles}}' ./dir3 # overlay removes that file + +# Walking through an overlay +go list -overlay overlay.json ./... +cmp stdout want-list.txt + +# TODO(#39958): assembly files, C files, files that require cgo preprocessing + +-- want-list.txt -- +m +m/dir +m/dir2 +m/dir3 +-- go.mod -- +// TODO(#39958): Support and test overlays including go.mod itself (especially if mod=readonly) +module m + +go 1.16 + +-- dir2/h.go -- +package dir2 + +-- dir3/good.go -- +package dir3 +-- dir3/bad.go -- +// no package statement +-- overlay.json -- +{ + "Replace": { + "f.go": "overlay/f_go", + "dir/g.go": "overlay/dir_g_go", + "dir2/i.go": "overlay/dir2_i_go", + "dir3/bad.go": "" + } +} +-- overlay/f_go -- +package m + +func f() { +} +-- overlay/dir_g_go -- +package m + +func g() { +} +-- overlay/dir2_i_go -- +package dir2 diff --git a/libgo/go/cmd/go/testdata/script/list_permissions.txt b/libgo/go/cmd/go/testdata/script/list_permissions.txt new file mode 100644 index 0000000..f65896c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_permissions.txt @@ -0,0 +1,84 @@ +env GO111MODULE=on + +# Establish baseline behavior, before mucking with file permissions. + +go list ./noread/... +stdout '^example.com/noread$' + +go list example.com/noread/... +stdout '^example.com/noread$' + +go list ./empty/... +stderr 'matched no packages' + +[root] stop # Root typically ignores file permissions. + +# Make the directory ./noread unreadable, and verify that 'go list' reports an +# explicit error for a pattern that should match it (rather than treating it as +# equivalent to an empty directory). + +[windows] skip # Does not have Unix-style directory permissions. +[plan9] skip # Might not have Unix-style directory permissions. + +chmod 000 noread + +# Check explicit paths. + +! go list ./noread +! stdout '^example.com/noread$' +! stderr 'matched no packages' + +! go list example.com/noread +! stdout '^example.com/noread$' +! stderr 'matched no packages' + +# Check filesystem-relative patterns. + +! go list ./... +! stdout '^example.com/noread$' +! stderr 'matched no packages' +stderr '^pattern ./...: ' + +! go list ./noread/... +! stdout '^example.com/noread$' +! stderr 'matched no packages' +stderr '^pattern ./noread/...: ' + + +# Check module-prefix patterns. + +! go list example.com/... +! stdout '^example.com/noread$' +! stderr 'matched no packages' +stderr '^pattern example.com/...: ' + +! go list example.com/noread/... +! stdout '^example.com/noread$' +! stderr 'matched no packages' +stderr '^pattern example.com/noread/...: ' + + +[short] stop + +# Check global patterns, which should still +# fail due to errors in the local module. + +! go list all +! stdout '^example.com/noread$' +! stderr 'matched no packages' +stderr '^pattern all: ' + +! go list ... +! stdout '^example.com/noread$' +! stderr 'matched no packages' +stderr '^pattern ...: ' + + +-- go.mod -- +module example.com +go 1.15 +-- noread/noread.go -- +// Package noread exists, but will be made unreadable. +package noread +-- empty/README.txt -- +This directory intentionally left empty. diff --git a/libgo/go/cmd/go/testdata/script/list_shadow.txt b/libgo/go/cmd/go/testdata/script/list_shadow.txt new file mode 100644 index 0000000..00e3f6f --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_shadow.txt @@ -0,0 +1,27 @@ +[gccgo] skip + +env GO111MODULE=off +env GOPATH=$WORK/gopath/src/shadow/root1${:}$WORK/gopath/src/shadow/root2 + +# The math in root1 is not "math" because the standard math is. +go list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./shadow/root1/src/math +stdout '^\(.*(\\|/)src(\\|/)shadow(\\|/)root1(\\|/)src(\\|/)math\) \('$GOROOT'(\\|/)?src(\\|/)math\)$' + +# The foo in root1 is "foo". +go list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./shadow/root1/src/foo +stdout '^\(foo\) \(\)$' + +# The foo in root2 is not "foo" because the foo in root1 got there first. +go list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./shadow/root2/src/foo +stdout '^\(.*gopath(\\|/)src(\\|/)shadow(\\|/)root2(\\|/)src(\\|/)foo\) \('$WORK'(\\|/)?gopath(\\|/)src(\\|/)shadow(\\|/)root1(\\|/)src(\\|/)foo\)$' + +# The error for go install should mention the conflicting directory. +! go install -n ./shadow/root2/src/foo +stderr 'go install: no install location for '$WORK'(\\|/)?gopath(\\|/)src(\\|/)shadow(\\|/)root2(\\|/)src(\\|/)foo: hidden by '$WORK'(\\|/)?gopath(\\|/)src(\\|/)shadow(\\|/)root1(\\|/)src(\\|/)foo' + +-- shadow/root1/src/foo/foo.go -- +package foo +-- shadow/root1/src/math/math.go -- +package math +-- shadow/root2/src/foo/foo.go -- +package foo diff --git a/libgo/go/cmd/go/testdata/script/list_std_vendor.txt b/libgo/go/cmd/go/testdata/script/list_std_vendor.txt new file mode 100644 index 0000000..821ec14 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_std_vendor.txt @@ -0,0 +1,34 @@ +# https://golang.org/issue/44725: packages in std should have the same +# dependencies regardless of whether they are listed from within or outside +# GOROOT/src. + +[gccgo] skip + +# Control case: net, viewed from outside the 'std' module, +# should depend on vendor/golang.org/… instead of golang.org/…. + +go list -deps net +stdout '^vendor/golang.org/x/net' +! stdout '^golang.org/x/net' +cp stdout $WORK/net-deps.txt + + +# It should still report the same package dependencies when viewed from +# within GOROOT/src. + +cd $GOROOT/src + +go list -deps net +stdout '^vendor/golang.org/x/net' +! stdout '^golang.org/x/net' +cmp stdout $WORK/net-deps.txt + + +# However, 'go mod' and 'go get' subcommands should report the original module +# dependencies, not the vendored packages. + +[!net] stop + +env GOPROXY= +go mod why -m golang.org/x/net +stdout '^# golang.org/x/net\nnet\ngolang.org/x/net' diff --git a/libgo/go/cmd/go/testdata/script/list_swigcxx.txt b/libgo/go/cmd/go/testdata/script/list_swigcxx.txt new file mode 100644 index 0000000..c6acd9e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_swigcxx.txt @@ -0,0 +1,27 @@ +# go list should not report SWIG-generated C++ files in CompiledGoFiles. + +[!exec:swig] skip +[!exec:g++] skip + +# CompiledGoFiles should contain 4 files: +# a.go +# a.swigcxx.go +# _cgo_gotypes.go +# a.cgo1.go + +go list -f '{{.CompiledGoFiles}}' -compiled=true example/swig + +# These names we see here, other than a.go, will be from the build cache, +# so we just count them. +stdout a\.go +stdout -count=3 $GOCACHE + +-- go.mod -- +module example + +go 1.16 + +-- swig/a.go -- +package swig + +-- swig/a.swigcxx -- diff --git a/libgo/go/cmd/go/testdata/script/list_symlink.txt b/libgo/go/cmd/go/testdata/script/list_symlink.txt new file mode 100644 index 0000000..f74ca86 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_symlink.txt @@ -0,0 +1,12 @@ +[!symlink] skip +env GO111MODULE=off + +mkdir $WORK/tmp/src +symlink $WORK/tmp/src/dir1 -> $WORK/tmp +cp p.go $WORK/tmp/src/dir1/p.go +env GOPATH=$WORK/tmp +go list -f '{{.Root}}' dir1 +stdout '^'$WORK/tmp'$' + +-- p.go -- +package p diff --git a/libgo/go/cmd/go/testdata/script/list_symlink_internal.txt b/libgo/go/cmd/go/testdata/script/list_symlink_internal.txt new file mode 100644 index 0000000..f756a56 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_symlink_internal.txt @@ -0,0 +1,27 @@ +[!symlink] skip +env GO111MODULE=off + +mkdir $WORK/tmp/gopath/src/dir1/internal/v +cp p.go $WORK/tmp/gopath/src/dir1/p.go +cp v.go $WORK/tmp/gopath/src/dir1/internal/v/v.go +symlink $WORK/tmp/symdir1 -> $WORK/tmp/gopath/src/dir1 +env GOPATH=$WORK/tmp/gopath +cd $WORK/tmp/symdir1 +go list -f '{{.Root}}' . +stdout '^'$WORK/tmp/gopath'$' + +# All of these should succeed, not die in internal-handling code. +go run p.go & +go build & +go install & + +wait + +-- p.go -- +package main + +import _ `dir1/internal/v` + +func main() {} +-- v.go -- +package v diff --git a/libgo/go/cmd/go/testdata/script/list_symlink_issue35941.txt b/libgo/go/cmd/go/testdata/script/list_symlink_issue35941.txt new file mode 100644 index 0000000..eb12bde --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_symlink_issue35941.txt @@ -0,0 +1,18 @@ +[!symlink] skip +env GO111MODULE=off + +# Issue 35941: suppress symlink warnings when running 'go list all'. +symlink goproj/css -> $GOPATH/src/css + +go list all +! stderr 'warning: ignoring symlink' + +# Show symlink warnings when patterns contain '...'. +go list goproj/... +stderr 'warning: ignoring symlink' + +-- goproj/a.go -- +package a + +-- css/index.css -- +body {} diff --git a/libgo/go/cmd/go/testdata/script/list_symlink_vendor_issue14054.txt b/libgo/go/cmd/go/testdata/script/list_symlink_vendor_issue14054.txt new file mode 100644 index 0000000..8e63a5a --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_symlink_vendor_issue14054.txt @@ -0,0 +1,28 @@ +[!symlink] skip +env GO111MODULE=off + +mkdir $WORK/tmp/gopath/src/dir1/vendor/v +cp p.go $WORK/tmp/gopath/src/dir1/p.go +cp v.go $WORK/tmp/gopath/src/dir1/vendor/v/v.go +symlink $WORK/tmp/symdir1 -> $WORK/tmp/gopath/src/dir1 +env GOPATH=$WORK/tmp/gopath +cd $WORK/tmp/symdir1 + +go list -f '{{.Root}}' . +stdout '^'$WORK/tmp/gopath'$' + +# All of these should succeed, not die in vendor-handling code. +go run p.go & +go build & +go install & + +wait + +-- p.go -- +package main + +import _ `v` + +func main () {} +-- v.go -- +package v diff --git a/libgo/go/cmd/go/testdata/script/list_symlink_vendor_issue15201.txt b/libgo/go/cmd/go/testdata/script/list_symlink_vendor_issue15201.txt new file mode 100644 index 0000000..19f2138 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_symlink_vendor_issue15201.txt @@ -0,0 +1,21 @@ +[!symlink] skip +env GO111MODULE=off + +mkdir $WORK/tmp/gopath/src/x/y/_vendor/src/x +symlink $WORK/tmp/gopath/src/x/y/_vendor/src/x/y -> ../../.. +mkdir $WORK/tmp/gopath/src/x/y/_vendor/src/x/y/w +cp w.go $WORK/tmp/gopath/src/x/y/w/w.go +symlink $WORK/tmp/gopath/src/x/y/w/vendor -> ../_vendor/src +mkdir $WORK/tmp/gopath/src/x/y/_vendor/src/x/y/z +cp z.go $WORK/tmp/gopath/src/x/y/z/z.go + +env GOPATH=$WORK/tmp/gopath/src/x/y/_vendor${:}$WORK/tmp/gopath +cd $WORK/tmp/gopath/src +go list ./... + +-- w.go -- +package w + +import "x/y/z" +-- z.go -- +package z diff --git a/libgo/go/cmd/go/testdata/script/list_test_simple.txt b/libgo/go/cmd/go/testdata/script/list_test_simple.txt new file mode 100644 index 0000000..954897c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_test_simple.txt @@ -0,0 +1,67 @@ +[short] skip + +# Test +go test -list=Test +stdout TestSimple + +# Benchmark +go test -list=Benchmark +stdout BenchmarkSimple + +# Examples +go test -list=Example +stdout ExampleSimple +stdout ExampleWithEmptyOutput + +-- go.mod -- +module m + +go 1.16 +-- bench_test.go -- +package testlist + +import ( + "fmt" + "testing" +) + +func BenchmarkSimplefunc(b *testing.B) { + b.StopTimer() + b.StartTimer() + for i := 0; i < b.N; i++ { + _ = fmt.Sprint("Test for bench") + } +} +-- example_test.go -- +package testlist + +import ( + "fmt" +) + +func ExampleSimple() { + fmt.Println("Test with Output.") + + // Output: Test with Output. +} + +func ExampleWithEmptyOutput() { + fmt.Println("") + + // Output: +} + +func ExampleNoOutput() { + _ = fmt.Sprint("Test with no output") +} +-- test_test.go -- +package testlist + +import ( + "fmt" + "testing" +) + +func TestSimple(t *testing.T) { + _ = fmt.Sprint("Test simple") +} diff --git a/libgo/go/cmd/go/testdata/script/list_wildcard_skip_nonmatching.txt b/libgo/go/cmd/go/testdata/script/list_wildcard_skip_nonmatching.txt new file mode 100644 index 0000000..02b1088 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_wildcard_skip_nonmatching.txt @@ -0,0 +1,17 @@ +# Test that wildcards don't look in useless directories. + +# First make sure that badpkg fails the list of '...'. +! go list ./... +stderr badpkg + +# Check that the list of './goodpkg...' succeeds. That implies badpkg was skipped. +go list ./goodpkg... + +-- go.mod -- +module m + +go 1.16 +-- goodpkg/x.go -- +package goodpkg +-- badpkg/x.go -- +pkg badpkg diff --git a/libgo/go/cmd/go/testdata/script/load_test_pkg_err.txt b/libgo/go/cmd/go/testdata/script/load_test_pkg_err.txt new file mode 100644 index 0000000..d088ee4 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/load_test_pkg_err.txt @@ -0,0 +1,30 @@ +# Tests issue 37971. Check that tests are still loaded even when the package has an error. + +go list -e -test d +cmp stdout want_stdout + +go list -e -test -deps d +stdout golang.org/fake/d + +-- want_stdout -- +d +d.test +d_test [d.test] +-- go.mod -- +module d + +go 1.16 +-- d.go -- +package d + +import "net/http" + +const d = http.MethodGet +func Get() string { return d; } +-- d2.go -- +-- d_test.go -- +package d_test + +import "testing" +import "golang.org/fake/d" +func TestD(t *testing.T) { d.Get(); } diff --git a/libgo/go/cmd/go/testdata/script/mod_all.txt b/libgo/go/cmd/go/testdata/script/mod_all.txt new file mode 100644 index 0000000..090eeee --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_all.txt @@ -0,0 +1,468 @@ +# This test illustrates the relationship between the 'all' pattern and +# the dependencies of the main module. + +# The package import graph used in this test looks like: +# +# main --------- a --------- b +# | | +# | a_test ---- c +# | | +# | c_test ---- d +# | +# main_test ---- t --------- u +# | +# t_test ---- w +# | +# w_test ---- x +# +# main/testonly_test ---- q --------- r +# | +# q_test ---- s +# +# And the module dependency graph looks like: +# +# main --- a.1 ---- b.1 +# \ \ \ +# \ \ c.1 -- d.1 +# \ \ +# \ t.1 ---- u.1 +# \ \ +# \ w.1 -- x.1 +# \ +# q.1 ---- r.1 +# \ +# s.1 + +env PKGFMT='{{if .Module}}{{.ImportPath}}{{end}}' +env MODFMT='{{.Path}}' + + +# 'go list -deps' lists packages and tests in the main module, +# along with their transitive dependencies. + +go list -f $PKGFMT -deps ./... +stdout -count=4 '^.' +stdout '^example.com/a$' +stdout '^example.com/b$' +stdout '^example.com/main$' +stdout '^example.com/main/testonly' + + +# 'go list -deps -test' lists transitive imports of tests and non-tests in the +# main module. + +go list -f $PKGFMT -deps -test ./... +stdout -count=13 '^.' +stdout '^example.com/a$' +stdout '^example.com/b$' +stdout '^example.com/main$' +stdout '^example.com/main.test$' +stdout '^example.com/main \[example.com/main.test\]$' +stdout '^example.com/main_test \[example.com/main.test\]$' +stdout '^example.com/main/testonly$' +stdout '^example.com/main/testonly.test$' +stdout '^example.com/main/testonly_test \[example.com/main/testonly.test\]$' +stdout '^example.com/q$' +stdout '^example.com/r$' +stdout '^example.com/t$' +stdout '^example.com/u$' + + +# 'go list all' lists the fixpoint of iterating 'go list -deps -test' starting +# with the packages in the main module, then reducing to only the non-test +# variants of those packages. + +go list -f $PKGFMT all +stdout -count=13 '^.' +stdout '^example.com/a$' +stdout '^example.com/b$' +stdout '^example.com/c$' +stdout '^example.com/d$' +stdout '^example.com/main$' +stdout '^example.com/main/testonly$' +stdout '^example.com/q$' +stdout '^example.com/r$' +stdout '^example.com/s$' +stdout '^example.com/t$' +stdout '^example.com/u$' +stdout '^example.com/w$' +stdout '^example.com/x$' + + +# 'go list -test all' is equivalent to 'go list -test $(go list all)' +# and both should include tests for every package in 'all'. + +go list -test -f $PKGFMT example.com/a example.com/b example.com/c example.com/d example.com/main example.com/main/testonly example.com/q example.com/r example.com/s example.com/t example.com/u example.com/w example.com/x +cp stdout list-test-explicit.txt + +go list -test -f $PKGFMT all +cmp stdout list-test-explicit.txt +stdout -count=36 '^.' +stdout '^example.com/a$' +stdout '^example.com/b$' +stdout '^example.com/c$' +stdout '^example.com/d$' +stdout '^example.com/main$' +stdout '^example.com/main/testonly$' +stdout '^example.com/q$' +stdout '^example.com/r$' +stdout '^example.com/s$' +stdout '^example.com/t$' +stdout '^example.com/u$' +stdout '^example.com/w$' +stdout '^example.com/x$' +stdout '^example.com/a.test$' +stdout '^example.com/a_test \[example.com/a.test\]$' +stdout '^example.com/b.test$' +stdout '^example.com/b_test \[example.com/b.test\]$' +stdout '^example.com/c.test$' +stdout '^example.com/c_test \[example.com/c.test\]$' +stdout '^example.com/main.test$' +stdout '^example.com/main \[example.com/main.test\]$' +stdout '^example.com/main_test \[example.com/main.test\]$' +stdout '^example.com/main/testonly.test$' +stdout '^example.com/main/testonly_test \[example.com/main/testonly.test\]$' +stdout '^example.com/q.test$' +stdout '^example.com/q_test \[example.com/q.test\]$' +stdout '^example.com/r.test$' +stdout '^example.com/r_test \[example.com/r.test\]$' +stdout '^example.com/s.test$' +stdout '^example.com/s_test \[example.com/s.test\]$' +stdout '^example.com/t.test$' +stdout '^example.com/t_test \[example.com/t.test\]$' +stdout '^example.com/u.test$' +stdout '^example.com/u_test \[example.com/u.test\]$' +stdout '^example.com/w.test$' +stdout '^example.com/w_test \[example.com/w.test\]$' + + +# 'go list -m all' covers the packages in 'go list -test -deps all'. + +go list -m -f $MODFMT all +stdout -count=12 '^.' +stdout '^example.com/a$' +stdout '^example.com/b$' +stdout '^example.com/c$' +stdout '^example.com/d$' +stdout '^example.com/main$' +stdout '^example.com/q$' +stdout '^example.com/r$' +stdout '^example.com/s$' +stdout '^example.com/t$' +stdout '^example.com/u$' +stdout '^example.com/w$' +stdout '^example.com/x$' + + +# 'go mod vendor' copies in only the packages transitively imported by the main +# module, and omits their tests. As a result, the 'all' and '...' patterns +# report fewer packages when using '-mod=vendor'. + +go mod vendor + +go list -f $PKGFMT -mod=vendor all +stdout -count=8 '^.' +stdout '^example.com/a$' +stdout '^example.com/b$' +stdout '^example.com/main$' +stdout '^example.com/main/testonly$' +stdout '^example.com/q$' +stdout '^example.com/r$' +stdout '^example.com/t$' +stdout '^example.com/u$' + +go list -test -f $PKGFMT -mod=vendor all +stdout -count=13 '^.' +stdout '^example.com/a$' +stdout '^example.com/b$' +stdout '^example.com/main$' +stdout '^example.com/main/testonly$' +stdout '^example.com/q$' +stdout '^example.com/r$' +stdout '^example.com/t$' +stdout '^example.com/u$' +stdout '^example.com/main.test$' +stdout '^example.com/main \[example.com/main.test\]$' +stdout '^example.com/main_test \[example.com/main.test\]$' +stdout '^example.com/main/testonly.test$' +stdout '^example.com/main/testonly_test \[example.com/main/testonly.test\]$' + +rm vendor + +# Convert all modules to go 1.17 to enable lazy loading. +go mod edit -go=1.17 a/go.mod +go mod edit -go=1.17 b/go.mod +go mod edit -go=1.17 c/go.mod +go mod edit -go=1.17 d/go.mod +go mod edit -go=1.17 q/go.mod +go mod edit -go=1.17 r/go.mod +go mod edit -go=1.17 s/go.mod +go mod edit -go=1.17 t/go.mod +go mod edit -go=1.17 u/go.mod +go mod edit -go=1.17 w/go.mod +go mod edit -go=1.17 x/go.mod +go mod edit -go=1.17 +cp go.mod go.mod.orig +go mod tidy +cmp go.mod go.mod.orig + +# With lazy loading, 'go list all' with neither -mod=vendor nor -test should +# match -mod=vendor without -test in 1.15. + +go list -f $PKGFMT all +stdout -count=8 '^.' +stdout '^example.com/a$' +stdout '^example.com/b$' +stdout '^example.com/main$' +stdout '^example.com/main/testonly$' +stdout '^example.com/q$' +stdout '^example.com/r$' +stdout '^example.com/t$' +stdout '^example.com/u$' + +# 'go list -test all' should expand that to include the test variants of the +# packages in 'all', but not the dependencies of outside tests. + +go list -test -f $PKGFMT all +stdout -count=25 '^.' +stdout '^example.com/a$' +stdout '^example.com/b$' +stdout '^example.com/main$' +stdout '^example.com/main/testonly$' +stdout '^example.com/q$' +stdout '^example.com/r$' +stdout '^example.com/t$' +stdout '^example.com/u$' +stdout '^example.com/a.test$' +stdout '^example.com/a_test \[example.com/a.test\]$' +stdout '^example.com/b.test$' +stdout '^example.com/b_test \[example.com/b.test\]$' +stdout '^example.com/main.test$' +stdout '^example.com/main \[example.com/main.test\]$' +stdout '^example.com/main_test \[example.com/main.test\]$' +stdout '^example.com/main/testonly.test$' +stdout '^example.com/main/testonly_test \[example.com/main/testonly.test\]$' +stdout '^example.com/q.test$' +stdout '^example.com/q_test \[example.com/q.test\]$' +stdout '^example.com/r.test$' +stdout '^example.com/r_test \[example.com/r.test\]$' +stdout '^example.com/t.test$' +stdout '^example.com/t_test \[example.com/t.test\]$' +stdout '^example.com/u.test$' +stdout '^example.com/u_test \[example.com/u.test\]$' + +# 'go list -test -deps all' should include the dependencies of those tests, +# but not the tests of the dependencies of outside tests. + +go list -test -deps -f $PKGFMT all +stdout -count=28 '^.' +stdout '^example.com/a$' +stdout '^example.com/b$' +stdout '^example.com/c$' +stdout '^example.com/main$' +stdout '^example.com/main/testonly$' +stdout '^example.com/q$' +stdout '^example.com/r$' +stdout '^example.com/s$' +stdout '^example.com/t$' +stdout '^example.com/u$' +stdout '^example.com/w$' +stdout '^example.com/a.test$' +stdout '^example.com/a_test \[example.com/a.test\]$' +stdout '^example.com/b.test$' +stdout '^example.com/b_test \[example.com/b.test\]$' +stdout '^example.com/main.test$' +stdout '^example.com/main \[example.com/main.test\]$' +stdout '^example.com/main_test \[example.com/main.test\]$' +stdout '^example.com/main/testonly.test$' +stdout '^example.com/main/testonly_test \[example.com/main/testonly.test\]$' +stdout '^example.com/q.test$' +stdout '^example.com/q_test \[example.com/q.test\]$' +stdout '^example.com/r.test$' +stdout '^example.com/r_test \[example.com/r.test\]$' +stdout '^example.com/t.test$' +stdout '^example.com/t_test \[example.com/t.test\]$' +stdout '^example.com/u.test$' +stdout '^example.com/u_test \[example.com/u.test\]$' + +# 'go list -m all' should cover all of the modules providing packages in +# 'go list -test -deps all', but should exclude modules d and x, +# which are not relevant to the main module and are outside of the +# lazy-loading horizon. + +go list -m -f $MODFMT all +stdout -count=10 '^.' +stdout '^example.com/a$' +stdout '^example.com/b$' +stdout '^example.com/c$' +! stdout '^example.com/d$' +stdout '^example.com/main$' +stdout '^example.com/q$' +stdout '^example.com/r$' +stdout '^example.com/s$' +stdout '^example.com/t$' +stdout '^example.com/u$' +stdout '^example.com/w$' +! stdout '^example.com/x$' + +-- go.mod -- +module example.com/main + +// Note: this go.mod file initially specifies go 1.15, +// but includes some redundant roots so that it +// also already obeys the 1.17 lazy loading invariants. +go 1.15 + +require ( + example.com/a v0.1.0 + example.com/b v0.1.0 + example.com/q v0.1.0 + example.com/r v0.1.0 // indirect + example.com/t v0.1.0 + example.com/u v0.1.0 // indirect +) + +replace ( + example.com/a v0.1.0 => ./a + example.com/b v0.1.0 => ./b + example.com/c v0.1.0 => ./c + example.com/d v0.1.0 => ./d + example.com/q v0.1.0 => ./q + example.com/r v0.1.0 => ./r + example.com/s v0.1.0 => ./s + example.com/t v0.1.0 => ./t + example.com/u v0.1.0 => ./u + example.com/w v0.1.0 => ./w + example.com/x v0.1.0 => ./x +) +-- main.go -- +package main + +import _ "example.com/a" + +func main() {} +-- main_test.go -- +package main_test + +import _ "example.com/t" +-- testonly/testonly_test.go -- +package testonly_test + +import _ "example.com/q" +-- a/go.mod -- +module example.com/a + +go 1.15 + +require ( + example.com/b v0.1.0 + example.com/c v0.1.0 +) +-- a/a.go -- +package a + +import _ "example.com/b" +-- a/a_test.go -- +package a_test + +import _ "example.com/c" +-- b/go.mod -- +module example.com/b + +go 1.15 +-- b/b.go -- +package b +-- b/b_test.go -- +package b_test +-- c/go.mod -- +module example.com/c + +go 1.15 + +require example.com/d v0.1.0 +-- c/c.go -- +package c +-- c/c_test.go -- +package c_test + +import _ "example.com/d" +-- d/go.mod -- +module example.com/d + +go 1.15 +-- d/d.go -- +package d +-- q/go.mod -- +module example.com/q + +go 1.15 + +require ( + example.com/r v0.1.0 + example.com/s v0.1.0 +) +-- q/q.go -- +package q +import _ "example.com/r" +-- q/q_test.go -- +package q_test +import _ "example.com/s" +-- r/go.mod -- +module example.com/r + +go 1.15 +-- r/r.go -- +package r +-- r/r_test.go -- +package r_test +-- s/go.mod -- +module example.com/s + +go 1.15 +-- s/s.go -- +package s +-- s/s_test.go -- +package s_test +-- t/go.mod -- +module example.com/t + +go 1.15 + +require ( + example.com/u v0.1.0 + example.com/w v0.1.0 +) +-- t/t.go -- +package t + +import _ "example.com/u" +-- t/t_test.go -- +package t_test + +import _ "example.com/w" +-- u/go.mod -- +module example.com/u + +go 1.15 +-- u/u.go -- +package u +-- u/u_test.go -- +package u_test +-- w/go.mod -- +module example.com/w + +go 1.15 + +require example.com/x v0.1.0 +-- w/w.go -- +package w +-- w/w_test.go -- +package w_test + +import _ "example.com/x" +-- x/go.mod -- +module example.com/x + +go 1.15 +-- x/x.go -- +package x diff --git a/libgo/go/cmd/go/testdata/script/mod_cache_dir.txt b/libgo/go/cmd/go/testdata/script/mod_cache_dir.txt new file mode 100644 index 0000000..7284ccf --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_cache_dir.txt @@ -0,0 +1,11 @@ +env GO111MODULE=on + +# Go should reject relative paths in GOMODCACHE environment. + +env GOMODCACHE="~/test" +! go get example.com/tools/cmd/hello +stderr 'must be absolute path' + +env GOMODCACHE="./test" +! go get example.com/tools/cmd/hello +stderr 'must be absolute path' diff --git a/libgo/go/cmd/go/testdata/script/mod_convert.txt b/libgo/go/cmd/go/testdata/script/mod_convert.txt new file mode 100644 index 0000000..f60fe87 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_convert.txt @@ -0,0 +1,66 @@ +[short] skip +[!net] skip +[!exec:git] skip + +env GO111MODULE=on +env GOPROXY= +env GOSUMDB= + +go mod download github.com/docker/distribution@v0.0.0-20150410205453-85de3967aa93 +mkdir x/Godeps +cp $GOPATH/pkg/mod/github.com/docker/distribution@v0.0.0-20150410205453-85de3967aa93/Godeps/Godeps.json x/Godeps +cd x +go mod init github.com/docker/distribution +cmpenv go.mod go.mod.want + +go mod download github.com/fishy/gcsbucket@v0.0.0-20180217031846-618d60fe84e0 +cp $GOPATH/pkg/mod/github.com/fishy/gcsbucket@v0.0.0-20180217031846-618d60fe84e0/Gopkg.lock ../y +cd ../y +go mod init github.com/fishy/gcsbucket +cmpenv go.mod go.mod.want + +-- x/go.mod.want -- +module github.com/docker/distribution + +go $goversion + +require ( + github.com/AdRoll/goamz v0.0.0-20150130162828-d3664b76d905 + github.com/MSOpenTech/azure-sdk-for-go v0.0.0-20150323223030-d90753bcad2e + github.com/Sirupsen/logrus v0.7.3 + github.com/bugsnag/bugsnag-go v1.0.3-0.20141110184014-b1d153021fcd + github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b + github.com/bugsnag/panicwrap v0.0.0-20141110184334-e5f9854865b9 + github.com/codegangsta/cli v1.4.2-0.20150131031259-6086d7927ec3 + github.com/docker/docker v1.4.2-0.20150204013315-165ea5c158cf + github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 + github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7 + github.com/gorilla/context v0.0.0-20140604161150-14f550f51af5 + github.com/gorilla/handlers v0.0.0-20140825150757-0e84b7d810c1 + github.com/gorilla/mux v0.0.0-20140926153814-e444e69cbd2e + github.com/jlhawn/go-crypto v0.0.0-20150401213827-cd738dde20f0 + github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 + github.com/yvasiyarov/gorelic v0.0.7-0.20141212073537-a9bba5b9ab50 + github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f + golang.org/x/net v0.0.0-20150202051010-1dfe7915deaf + gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789 + gopkg.in/yaml.v2 v2.0.0-20150116202057-bef53efd0c76 +) +-- y/go.mod.want -- +module github.com/fishy/gcsbucket + +go $goversion + +require ( + cloud.google.com/go v0.18.0 + github.com/fishy/fsdb v0.0.0-20180217030800-5527ded01371 + github.com/golang/protobuf v1.0.0 + github.com/googleapis/gax-go v2.0.0+incompatible + golang.org/x/net v0.0.0-20180216171745-136a25c244d3 + golang.org/x/oauth2 v0.0.0-20180207181906-543e37812f10 + golang.org/x/text v0.3.1-0.20180208041248-4e4a3210bb54 + google.golang.org/api v0.0.0-20180217000815-c7a403bb5fe1 + google.golang.org/appengine v1.0.0 + google.golang.org/genproto v0.0.0-20180206005123-2b5a72b8730b + google.golang.org/grpc v1.10.0 +) diff --git a/libgo/go/cmd/go/testdata/script/mod_convert_tsv_insecure.txt b/libgo/go/cmd/go/testdata/script/mod_convert_tsv_insecure.txt index ddb0c08..283e2d9 100644 --- a/libgo/go/cmd/go/testdata/script/mod_convert_tsv_insecure.txt +++ b/libgo/go/cmd/go/testdata/script/mod_convert_tsv_insecure.txt @@ -1,4 +1,6 @@ env GO111MODULE=on +env GOPROXY=direct +env GOSUMDB=off [!net] skip [!exec:git] skip diff --git a/libgo/go/cmd/go/testdata/script/mod_deprecate_message.txt b/libgo/go/cmd/go/testdata/script/mod_deprecate_message.txt new file mode 100644 index 0000000..5670279 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_deprecate_message.txt @@ -0,0 +1,73 @@ +# When there is a short single-line message, 'go get' should print it all. +go get -d short +stderr '^go: module short is deprecated: short$' +go list -m -u -f '{{.Deprecated}}' short +stdout '^short$' + +# When there is a multi-line message, 'go get' should print the first line. +go get -d multiline +stderr '^go: module multiline is deprecated: first line$' +! stderr 'second line' +go list -m -u -f '{{.Deprecated}}' multiline +stdout '^first line\nsecond line.$' + +# When there is a long message, 'go get' should print a placeholder. +go get -d long +stderr '^go: module long is deprecated: \(message omitted: too long\)$' +go list -m -u -f '{{.Deprecated}}' long +stdout '^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$' + +# When a message contains unprintable chracters, 'go get' should say that +# without printing the message. +go get -d unprintable +stderr '^go: module unprintable is deprecated: \(message omitted: contains non-printable characters\)$' +go list -m -u -f '{{.Deprecated}}' unprintable +stdout '^message contains ASCII BEL\x07$' + +-- go.mod -- +module use + +go 1.16 + +require ( + short v0.0.0 + multiline v0.0.0 + long v0.0.0 + unprintable v0.0.0 +) + +replace ( + short v0.0.0 => ./short + multiline v0.0.0 => ./multiline + long v0.0.0 => ./long + unprintable v0.0.0 => ./unprintable +) +-- short/go.mod -- +// Deprecated: short +module short + +go 1.16 +-- short/short.go -- +package short +-- multiline/go.mod -- +// Deprecated: first line +// second line. +module multiline + +go 1.16 +-- multiline/multiline.go -- +package multiline +-- long/go.mod -- +// Deprecated: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +module long + +go 1.16 +-- long/long.go -- +package long +-- unprintable/go.mod -- +// Deprecated: message contains ASCII BEL +module unprintable + +go 1.16 +-- unprintable/unprintable.go -- +package unprintable diff --git a/libgo/go/cmd/go/testdata/script/mod_download_concurrent_read.txt b/libgo/go/cmd/go/testdata/script/mod_download_concurrent_read.txt new file mode 100644 index 0000000..231babd --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_download_concurrent_read.txt @@ -0,0 +1,110 @@ +# This test simulates a process watching for changes and reading files in +# module cache as a module is extracted. +# +# Before Go 1.16, we extracted each module zip to a temporary directory with +# a random name, then renamed that into place with os.Rename. On Windows, +# this failed with ERROR_ACCESS_DENIED when another process (usually an +# anti-virus scanner) opened files in the temporary directory. This test +# simulates that behavior, verifying golang.org/issue/36568. +# +# Since 1.16, we extract to the final directory, but we create a .partial file +# so that if we crash, other processes know the directory is incomplete. + +[!windows] skip +[short] skip + +go run downloader.go + +-- go.mod -- +module example.com/m + +go 1.14 + +-- downloader.go -- +package main + +import ( + "fmt" + "log" + "os" + "os/exec" + "path/filepath" +) + +func main() { + if err := run(); err != nil { + log.Fatal(err) + } +} + +// run repeatedly downloads a module while opening files in the module cache +// in a background goroutine. +// +// run uses a different temporary module cache in each iteration so that we +// don't need to clean the cache or synchronize closing files after each +// iteration. +func run() (err error) { + tmpDir, err := os.MkdirTemp("", "") + if err != nil { + return err + } + defer func() { + if rmErr := os.RemoveAll(tmpDir); err == nil && rmErr != nil { + err = rmErr + } + }() + for i := 0; i < 10; i++ { + gopath := filepath.Join(tmpDir, fmt.Sprintf("gopath%d", i)) + var err error + done := make(chan struct{}) + go func() { + err = download(gopath) + close(done) + }() + readCache(gopath, done) + if err != nil { + return err + } + } + return nil +} + +// download downloads a module into the given cache using 'go mod download'. +func download(gopath string) error { + cmd := exec.Command("go", "mod", "download", "-modcacherw", "rsc.io/quote@v1.5.2") + cmd.Stderr = os.Stderr + cmd.Env = append(os.Environ(), "GOPATH="+gopath) + return cmd.Run() +} + +// readCache repeatedly globs for go.mod files in the given cache, then opens +// those files for reading. When the done chan is closed, readCache closes +// files and returns. +func readCache(gopath string, done <-chan struct{}) { + files := make(map[string]*os.File) + defer func() { + for _, f := range files { + f.Close() + } + }() + + pattern := filepath.Join(gopath, "pkg/mod/rsc.io/quote@v1.5.2*/go.mod") + for { + select { + case <-done: + return + default: + } + + names, _ := filepath.Glob(pattern) + for _, name := range names { + if files[name] != nil { + continue + } + f, _ := os.Open(name) + if f != nil { + files[name] = f + } + } + } +} diff --git a/libgo/go/cmd/go/testdata/script/mod_download_partial.txt b/libgo/go/cmd/go/testdata/script/mod_download_partial.txt new file mode 100644 index 0000000..0aab60d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_download_partial.txt @@ -0,0 +1,68 @@ +# Download modules and populate go.sum. +go get -d -modcacherw +exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod + +# 'go mod verify' should fail if we delete a file. +go mod verify +rm $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod +! go mod verify + +# Create a .partial file to simulate an failure extracting the zip file. +cp empty $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.partial + +# 'go mod verify' should not fail, since the module hasn't been completely +# ingested into the cache. +go mod verify + +# 'go list' should not load packages from the directory. +# NOTE: the message "directory $dir outside available modules" is reported +# for directories not in the main module, active modules in the module cache, +# or local replacements. In this case, the directory is in the right place, +# but it's incomplete, so 'go list' acts as if it's not an active module. +! go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.2 +stderr 'outside available modules' + +# 'go list -m' should not print the directory. +go list -m -f '{{.Dir}}' rsc.io/quote +! stdout . + +# 'go mod download' should re-extract the module and remove the .partial file. +go mod download -modcacherw rsc.io/quote +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.partial +exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod + +# 'go list' should succeed. +go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.2 +stdout '^rsc.io/quote$' + +# 'go list -m' should print the directory. +go list -m -f '{{.Dir}}' rsc.io/quote +stdout 'pkg[/\\]mod[/\\]rsc.io[/\\]quote@v1.5.2' + +# go mod verify should fail if we delete a file. +go mod verify +rm $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/go.mod +! go mod verify + +# 'go mod download' should not leave behind a directory or a .partial file +# if there is an error extracting the zip file. +rm $GOPATH/pkg/mod/rsc.io/quote@v1.5.2 +cp empty $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip +! go mod download +stderr 'not a valid zip file' +! exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2 +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.partial + +-- go.mod -- +module m + +go 1.14 + +require rsc.io/quote v1.5.2 + +-- use.go -- +package use + +import _ "rsc.io/quote" + +-- empty -- diff --git a/libgo/go/cmd/go/testdata/script/mod_e.txt b/libgo/go/cmd/go/testdata/script/mod_e.txt new file mode 100644 index 0000000..3a0d18d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_e.txt @@ -0,0 +1,89 @@ +cp go.mod go.mod.orig + + +# If a dependency cannot be resolved, 'go mod tidy' fails with an error message +# explaining the problem and does not update the go.mod file. +# TODO(bcmills): Ideally, with less redundancy than these error messages! + +! go mod tidy + +stderr '^example.com/untidy imports\n\texample.net/directnotfound: cannot find module providing package example.net/directnotfound: module example.net/directnotfound: reading http://.*: 404 Not Found$' + +stderr '^example.com/untidy imports\n\texample.net/m imports\n\texample.net/indirectnotfound: cannot find module providing package example.net/indirectnotfound: module example.net/indirectnotfound: reading http://.*: 404 Not Found$' + +stderr '^example.com/untidy tested by\n\texample.com/untidy.test imports\n\texample.net/directtestnotfound: cannot find module providing package example.net/directtestnotfound: module example.net/directtestnotfound: reading http://.*: 404 Not Found$' + +stderr '^example.com/untidy imports\n\texample.net/m tested by\n\texample.net/m.test imports\n\texample.net/indirecttestnotfound: cannot find module providing package example.net/indirecttestnotfound: module example.net/indirecttestnotfound: reading http://.*: 404 Not Found$' + +cmp go.mod.orig go.mod + + +# If a dependency cannot be resolved, 'go mod vendor' fails with an error message +# explaining the problem, does not update the go.mod file, and does not create +# the vendor directory. + +! go mod vendor + +stderr '^example.com/untidy imports\n\texample.net/directnotfound: cannot find module providing package example.net/directnotfound: module example.net/directnotfound: reading http://.*: 404 Not Found$' + +stderr '^example.com/untidy imports\n\texample.net/m imports\n\texample.net/indirectnotfound: cannot find module providing package example.net/indirectnotfound: module example.net/indirectnotfound: reading http://.*: 404 Not Found$' + +stderr '^example.com/untidy tested by\n\texample.com/untidy.test imports\n\texample.net/directtestnotfound: cannot find module providing package example.net/directtestnotfound: module example.net/directtestnotfound: reading http://.*: 404 Not Found$' + +! stderr 'indirecttestnotfound' # Vendor prunes test dependencies. + +cmp go.mod.orig go.mod +! exists vendor + + +# 'go mod tidy' still logs the errors, but succeeds and updates go.mod. + +go mod tidy -e +stderr -count=4 'cannot find module providing package' +cmp go.mod.final go.mod + + +# 'go mod vendor -e' still logs the errors, but succeeds and updates go.mod. + +cp go.mod.orig go.mod +go mod vendor -e +stderr -count=3 'cannot find module providing package' +cmp go.mod.final go.mod +exists vendor/modules.txt +exists vendor/example.net/m/m.go + + +-- go.mod -- +module example.com/untidy +go 1.16 +replace example.net/m v0.1.0 => ./m +-- go.mod.final -- +module example.com/untidy + +go 1.16 + +replace example.net/m v0.1.0 => ./m + +require example.net/m v0.1.0 +-- untidy.go -- +package untidy + +import ( + _ "example.net/m" + _ "example.net/directnotfound" +) +-- untidy_test.go -- +package untidy_test + +import _ "example.net/directtestnotfound" +-- m/go.mod -- +module example.net/m +go 1.16 +-- m/m.go -- +package m + +import _ "example.net/indirectnotfound" +-- m/m_test.go -- +package m_test + +import _ "example.net/indirecttestnotfound" diff --git a/libgo/go/cmd/go/testdata/script/mod_edit.txt b/libgo/go/cmd/go/testdata/script/mod_edit.txt index 9da6930..5aa5ca1 100644 --- a/libgo/go/cmd/go/testdata/script/mod_edit.txt +++ b/libgo/go/cmd/go/testdata/script/mod_edit.txt @@ -46,6 +46,10 @@ cmpenv stdout $WORK/go.mod.json go mod edit -json $WORK/go.mod.retractrationale cmp stdout $WORK/go.mod.retractrationale.json +# go mod edit -json (deprecation) +go mod edit -json $WORK/go.mod.deprecation +cmp stdout $WORK/go.mod.deprecation.json + # go mod edit -json (empty mod file) go mod edit -json $WORK/go.mod.empty cmp stdout $WORK/go.mod.empty.json @@ -290,6 +294,20 @@ retract ( } ] } +-- $WORK/go.mod.deprecation -- +// Deprecated: and the new one is not ready yet +module m +-- $WORK/go.mod.deprecation.json -- +{ + "Module": { + "Path": "m", + "Deprecated": "and the new one is not ready yet" + }, + "Require": null, + "Exclude": null, + "Replace": null, + "Retract": null +} -- $WORK/go.mod.empty -- -- $WORK/go.mod.empty.json -- { diff --git a/libgo/go/cmd/go/testdata/script/mod_edit_no_modcache.txt b/libgo/go/cmd/go/testdata/script/mod_edit_no_modcache.txt new file mode 100644 index 0000000..ced15bb --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_edit_no_modcache.txt @@ -0,0 +1,15 @@ +# 'go mod edit' opportunistically locks the side-lock file in the module cache, +# for compatibility with older versions of the 'go' command. +# It does not otherwise depend on the module cache, so it should not +# fail if the module cache directory cannot be created. + +[root] skip + +mkdir $WORK/readonly +chmod 0555 $WORK/readonly +env GOPATH=$WORK/readonly/nonexist + +go mod edit -go=1.17 + +-- go.mod -- +module example.com/m diff --git a/libgo/go/cmd/go/testdata/script/mod_empty_err.txt b/libgo/go/cmd/go/testdata/script/mod_empty_err.txt index 982e6b2..c4359bc 100644 --- a/libgo/go/cmd/go/testdata/script/mod_empty_err.txt +++ b/libgo/go/cmd/go/testdata/script/mod_empty_err.txt @@ -1,4 +1,4 @@ -# This test checks error messages for non-existant packages in module mode. +# This test checks error messages for non-existent packages in module mode. # Veries golang.org/issue/35414 env GO111MODULE=on cd $WORK diff --git a/libgo/go/cmd/go/testdata/script/mod_get_ambiguous_arg.txt b/libgo/go/cmd/go/testdata/script/mod_get_ambiguous_arg.txt new file mode 100644 index 0000000..daed03b --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_ambiguous_arg.txt @@ -0,0 +1,107 @@ +go mod tidy +cp go.mod go.mod.orig + +# If there is no sensible *package* meaning for 'm/p', it should refer +# to *module* m/p. + +go get -d m/p # @latest +go list -m all +stdout '^m/p v0.3.0 ' +! stdout '^m ' + +cp go.mod.orig go.mod + +go get -d m/p@v0.1.0 +go list -m all +stdout '^m/p v0.1.0 ' +! stdout '^m ' + +# When feasible, the argument 'm/p' in 'go get m/p' refers to *package* m/p, +# which is in module m. +# +# (It only refers to *module* m/p if there is no such package at the +# requested version.) + +go get -d m/p@v0.2.0 +go list -m all +stdout '^m v0.2.0 ' +stdout '^m/p v0.1.0 ' # unchanged from the previous case + +# Repeating the above with module m/p already in the module graph does not +# change its meaning. + +go get -d m/p@v0.2.0 +go list -m all +stdout '^m v0.2.0 ' +stdout '^m/p v0.1.0 ' + +-- go.mod -- +module example.com + +go 1.16 + +replace ( + m v0.1.0 => ./m01 + m v0.2.0 => ./m02 + m v0.3.0 => ./m03 + m/p v0.1.0 => ./mp01 + m/p v0.2.0 => ./mp02 + m/p v0.3.0 => ./mp03 +) +-- m01/go.mod -- +module m + +go 1.16 +-- m01/README.txt -- +Module m at v0.1.0 does not yet contain package p. + +-- m02/go.mod -- +module m + +go 1.16 + +require m/p v0.1.0 +-- m02/p/p.go -- +// Package p is present in module m, but not module m/p. +package p + +-- m03/go.mod -- +module m + +go 1.16 + +require m/p v0.1.0 +-- m03/README.txt -- +Module m at v0.3.0 no longer contains package p. + +-- mv2/go.mod -- +module m/v2 + +go 1.16 +-- mv2/README.txt -- +This module is m/v2. It doesn't actually need to exist, +but it explains how module m could plausibly exist +and still contain package p at 'latest' even when module +m/p also exists. + +-- mp01/go.mod -- +module m/p + +go 1.16 +-- mp01/README.txt -- +This module is m/p. +Package m/p does not exist in this module. +-- mp02/go.mod -- +module m/p + +go 1.16 +-- mp02/README.txt -- +This module is m/p. +Package m/p does not exist in this module. +-- mp03/go.mod -- +module m/p + +go 1.16 +-- mp03/README.txt -- +This module is m/p. +Package m/p does not exist in this module. diff --git a/libgo/go/cmd/go/testdata/script/mod_get_ambiguous_import.txt b/libgo/go/cmd/go/testdata/script/mod_get_ambiguous_import.txt new file mode 100644 index 0000000..33605f5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_ambiguous_import.txt @@ -0,0 +1,60 @@ +go list -m all +stdout '^example.net/m v0.1.0 ' +! stdout '^example.net/m/p ' +cp go.mod go.mod.orig + +# Upgrading example.net/m/p without also upgrading example.net/m +# causes the import of package example.net/m/p to be ambiguous. +# +# TODO(#27899): Should we automatically upgrade example.net/m to v0.2.0 +# to resolve the conflict? +! go get -d example.net/m/p@v1.0.0 +stderr '^example.net/m/p: ambiguous import: found package example.net/m/p in multiple modules:\n\texample.net/m v0.1.0 \(.*[/\\]m1[/\\]p\)\n\texample.net/m/p v1.0.0 \(.*[/\\]p0\)\n\z' +cmp go.mod go.mod.orig + +# Upgrading both modules simultaneously resolves the ambiguous upgrade. +# Note that this command line mixes a module path (example.net/m) +# and a package path (example.net/m/p) in the same command. +go get -d example.net/m@v0.2.0 example.net/m/p@v1.0.0 + +go list -m all +stdout '^example.net/m v0.2.0 ' +stdout '^example.net/m/p v1.0.0 ' + +-- go.mod -- +module example.net/importer + +go 1.16 + +require ( + example.net/m v0.1.0 +) + +replace ( + example.net/m v0.1.0 => ./m1 + example.net/m v0.2.0 => ./m2 + example.net/m/p v1.0.0 => ./p0 +) +-- importer.go -- +package importer +import _ "example.net/m/p" +-- m1/go.mod -- +module example.net/m + +go 1.16 +-- m1/p/p.go -- +package p +-- m2/go.mod -- +module example.net/m + +go 1.16 +-- m2/README.txt -- +Package p has been moved to module …/m/p. +Module …/m/p does not require any version of module …/m. + +-- p0/go.mod -- +module example.net/m/p + +go 1.16 +-- p0/p.go -- +package p diff --git a/libgo/go/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt b/libgo/go/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt new file mode 100644 index 0000000..0e7f93b --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt @@ -0,0 +1,87 @@ +# Both example.net/ambiguous v0.1.0 and example.net/ambiguous/pkg v0.1.0 exist. +# 'go mod tidy' would arbitrarily choose the one with the longer path, +# but 'go mod tidy' also arbitrarily chooses the latest version. + +cp go.mod go.mod.orig + + +# From a clean slate, 'go get' currently does the same thing as 'go mod tidy': +# it resolves the package from the module with the longest matching prefix. + +go get -d example.net/ambiguous/nested/pkg@v0.1.0 +go list -m all +stdout '^example.net/ambiguous/nested v0.1.0$' +! stdout '^example.net/ambiguous ' + + +# From an initial state that already depends on the shorter path, +# the same 'go get' command should (somewhat arbitrarily) keep the +# existing path, since it is a valid interpretation of the command. + +cp go.mod.orig go.mod +go mod edit -require=example.net/ambiguous@v0.1.0 + +go get -d example.net/ambiguous/nested/pkg@v0.1.0 +go list -m all +stdout '^example.net/ambiguous v0.1.0$' +! stdout '^example.net/ambiguous/nested ' + + +# The user should be able to make the command unambiguous by explicitly +# upgrading the conflicting module... + +go get -d example.net/ambiguous@v0.2.0 example.net/ambiguous/nested/pkg@v0.1.0 +go list -m all +stdout '^example.net/ambiguous/nested v0.1.0$' +stdout '^example.net/ambiguous v0.2.0$' + + +# ...or by explicitly NOT adding the conflicting module. + +cp go.mod.orig go.mod +go mod edit -require=example.net/ambiguous@v0.1.0 + +go get -d example.net/ambiguous/nested/pkg@v0.1.0 example.net/ambiguous/nested@none +go list -m all +! stdout '^example.net/ambiguous/nested ' +stdout '^example.net/ambiguous v0.1.0$' + + +# The user should also be able to fix it by *downgrading* the conflicting module +# away. + +cp go.mod.orig go.mod +go mod edit -require=example.net/ambiguous@v0.1.0 + +go get -d example.net/ambiguous@none example.net/ambiguous/nested/pkg@v0.1.0 +go list -m all +stdout '^example.net/ambiguous/nested v0.1.0$' +! stdout '^example.net/ambiguous ' + + +# In contrast, if we do the same thing tacking a wildcard pattern ('/...') on +# the end of the package path, we get different behaviors depending on the +# initial state, and no error. (This seems to contradict the “same meaning +# regardless of the initial state” point above, but maybe that's ok?) + +cp go.mod.orig go.mod + +go get -d example.net/ambiguous/nested/pkg/...@v0.1.0 +go list -m all +stdout '^example.net/ambiguous/nested v0.1.0$' +! stdout '^example.net/ambiguous ' + + +cp go.mod.orig go.mod +go mod edit -require=example.net/ambiguous@v0.1.0 + +go get -d example.net/ambiguous/nested/pkg/...@v0.1.0 +go list -m all +! stdout '^example.net/ambiguous/nested ' +stdout '^example.net/ambiguous v0.1.0$' + + +-- go.mod -- +module test + +go 1.16 diff --git a/libgo/go/cmd/go/testdata/script/mod_get_changes.txt b/libgo/go/cmd/go/testdata/script/mod_get_changes.txt new file mode 100644 index 0000000..3287b2a --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_changes.txt @@ -0,0 +1,70 @@ +# When adding a requirement, 'go get' prints a message for the requirement +# and for changed explicit dependencies. 'go get' does not print messages +# for changed indirect dependencies. +go list -m all +! stdout golang.org/x/text +go get -d rsc.io/quote@v1.5.2 +stderr '^go get: added rsc.io/quote v1.5.2$' +stderr '^go get: upgraded rsc.io/sampler v1.0.0 => v1.3.0$' +! stderr '^go get.*golang.org/x/text' +go list -m all +stdout golang.org/x/text +cmp go.mod go.mod.upgrade + +# When removing a requirement, 'go get' prints a message for the requiremnent +# and for changed explicit dependencies. 'go get' does not print messages +# for changed indirect dependencies. +go get -d rsc.io/sampler@none +stderr '^go get: downgraded rsc.io/quote v1.5.2 => v1.3.0$' +stderr '^go get: removed rsc.io/sampler v1.3.0$' +! stderr '^go get.*golang.org/x/text' +cmp go.mod go.mod.downgrade + +# When removing or downgrading a requirement, 'go get' also prints a message +# for explicit dependencies removed as a consequence. +cp go.mod.usequote go.mod +go get -d rsc.io/quote@v1.5.1 +stderr '^go get: downgraded rsc.io/quote v1.5.2 => v1.5.1$' +stderr '^go get: removed usequote v0.0.0$' + +-- go.mod -- +module m + +go 1.16 + +require rsc.io/sampler v1.0.0 +-- go.sum -- +rsc.io/sampler v1.0.0 h1:SRJnjyQ07sAtq6G4RcfJEmz8JxqLyj3PoGXG2VhbDWo= +rsc.io/sampler v1.0.0/go.mod h1:cqxpM3ZVz9VtirqxZPmrWzkQ+UkiNiGtkrN+B+i8kx8= +-- go.mod.upgrade -- +module m + +go 1.16 + +require ( + rsc.io/quote v1.5.2 // indirect + rsc.io/sampler v1.3.0 +) +-- go.mod.downgrade -- +module m + +go 1.16 + +require ( + golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect + rsc.io/quote v1.3.0 // indirect +) +-- go.mod.usequote -- +module m + +go 1.16 + +require usequote v0.0.0 + +replace usequote => ./usequote +-- usequote/go.mod -- +module usequote + +go 1.16 + +require rsc.io/quote v1.5.2 diff --git a/libgo/go/cmd/go/testdata/script/mod_get_deprecate_install.txt b/libgo/go/cmd/go/testdata/script/mod_get_deprecate_install.txt new file mode 100644 index 0000000..63cd27a --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_deprecate_install.txt @@ -0,0 +1,39 @@ +[short] skip + +env GO111MODULE=on + +# 'go get' outside a module with an executable prints a deprecation message. +go get example.com/cmd/a +stderr '^go get: installing executables with ''go get'' in module mode is deprecated.$' +stderr 'Use ''go install pkg@version'' instead.' + +cp go.mod.orig go.mod + +# 'go get' inside a module with a non-main package does not print a message. +# This will stop building in the future, but it's the command we want to use. +go get rsc.io/quote +! stderr deprecated +cp go.mod.orig go.mod + +# 'go get' inside a module with an executable prints a different +# deprecation message. +go get example.com/cmd/a +stderr '^go get: installing executables with ''go get'' in module mode is deprecated.$' +stderr 'To adjust and download dependencies of the current module, use ''go get -d''' +cp go.mod.orig go.mod + +# 'go get' should not print a warning for a main package inside the main module. +# The intent is most likely to update the dependencies of that package. +# 'go install' would be used otherwise. +go get m +! stderr . +cp go.mod.orig go.mod + +-- go.mod.orig -- +module m + +go 1.17 +-- main.go -- +package main + +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/mod_get_deprecated.txt b/libgo/go/cmd/go/testdata/script/mod_get_deprecated.txt new file mode 100644 index 0000000..7bdd7a5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_deprecated.txt @@ -0,0 +1,66 @@ +# 'go get pkg' should not show a deprecation message for an unrelated module. +go get -d ./use/nothing +! stderr 'module.*is deprecated' + +# 'go get pkg' should show a deprecation message for the module providing pkg. +go get -d example.com/deprecated/a +stderr '^go: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$' +go get -d example.com/deprecated/a@v1.0.0 +stderr '^go: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$' + +# 'go get pkg' should show a deprecation message for a module providing +# packages directly imported by pkg. +go get -d ./use/a +stderr '^go: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$' + +# 'go get pkg' may show a deprecation message for an indirectly required module +# if it provides a package named on the command line. +go get -d ./use/b +! stderr 'module.*is deprecated' +go get -d local/use +! stderr 'module.*is deprecated' +go get -d example.com/deprecated/b +stderr '^go: module example.com/deprecated/b is deprecated: in example.com/deprecated/b@v1.9.0$' + +# 'go get pkg' does not show a deprecation message for a module providing a +# directly imported package if the module is no longer deprecated in its +# latest version, even if the module is deprecated in its current version. +go get -d ./use/undeprecated +! stderr 'module.*is deprecated' + +-- go.mod -- +module m + +go 1.17 + +require ( + example.com/deprecated/a v1.0.0 + example.com/undeprecated v1.0.0 + local v0.0.0 +) + +replace local v0.0.0 => ./local +-- use/nothing/nothing.go -- +package nothing +-- use/a/a.go -- +package a + +import _ "example.com/deprecated/a" +-- use/b/b.go -- +package b + +import _ "local/use" +-- use/undeprecated/undeprecated.go -- +package undeprecated + +import _ "example.com/undeprecated" +-- local/go.mod -- +module local + +go 1.17 + +require example.com/deprecated/b v1.0.0 +-- local/use/use.go -- +package use + +import _ "example.com/deprecated/b" diff --git a/libgo/go/cmd/go/testdata/script/mod_get_downadd_indirect.txt b/libgo/go/cmd/go/testdata/script/mod_get_downadd_indirect.txt new file mode 100644 index 0000000..efc38f7 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_downadd_indirect.txt @@ -0,0 +1,81 @@ +# This test illustrates a case where downgrading one module may upgrade another. +# Compare to the downcross2 test case in cmd/go/internal/mvs/mvs_test.go. + +# The initial package import graph used in this test looks like: +# +# a ---- b ---- d +# +# The module dependency graph originally looks like: +# +# a ---- b.2 ---- d.2 +# +# b.1 ---- c.1 +# +# If we downgrade module d to version 1, we must downgrade b as well. +# If that downgrade selects b version 1, we will add a new dependency on module c. + +cp go.mod go.mod.orig +go mod tidy +cmp go.mod.orig go.mod + +go get -d example.com/d@v0.1.0 +go list -m all +stdout '^example.com/b v0.1.0 ' +stdout '^example.com/c v0.1.0 ' +stdout '^example.com/d v0.1.0 ' + +-- go.mod -- +module example.com/a + +go 1.15 + +require example.com/b v0.2.0 + +replace ( + example.com/b v0.1.0 => ./b1 + example.com/b v0.2.0 => ./b2 + example.com/c v0.1.0 => ./c + example.com/d v0.1.0 => ./d + example.com/d v0.2.0 => ./d +) +-- a.go -- +package a + +import _ "example.com/b" + +-- b1/go.mod -- +module example.com/b + +go 1.15 + +require example.com/c v0.1.0 +-- b1/b.go -- +package b + +import _ "example.com/c" + +-- b2/go.mod -- +module example.com/b + +go 1.15 + +require example.com/d v0.2.0 +-- b2/b.go -- +package b + +import _ "example.com/d" + +-- c/go.mod -- +module example.com/c + +go 1.15 + +-- c/c.go -- +package c + +-- d/go.mod -- +module example.com/d + +go 1.15 +-- d/d.go -- +package d diff --git a/libgo/go/cmd/go/testdata/script/mod_get_downgrade.txt b/libgo/go/cmd/go/testdata/script/mod_get_downgrade.txt index a954c10..c26c5e1 100644 --- a/libgo/go/cmd/go/testdata/script/mod_get_downgrade.txt +++ b/libgo/go/cmd/go/testdata/script/mod_get_downgrade.txt @@ -20,8 +20,8 @@ stdout 'rsc.io/quote v1.5.1' stdout 'rsc.io/sampler v1.3.0' ! go get -d rsc.io/sampler@v1.0.0 rsc.io/quote@v1.5.2 golang.org/x/text@none +stderr -count=1 '^go get:' stderr '^go get: rsc.io/quote@v1.5.2 requires rsc.io/sampler@v1.3.0, not rsc.io/sampler@v1.0.0$' -stderr '^go get: rsc.io/quote@v1.5.2 requires golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c, not golang.org/x/text@none$' go list -m all stdout 'rsc.io/quote v1.5.1' diff --git a/libgo/go/cmd/go/testdata/script/mod_get_downgrade_missing.txt b/libgo/go/cmd/go/testdata/script/mod_get_downgrade_missing.txt new file mode 100644 index 0000000..5b768fa --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_downgrade_missing.txt @@ -0,0 +1,43 @@ +cp go.mod go.mod.orig + +# getting a specific version of a module along with a pattern +# not yet present in that module should report the version mismatch +# rather than a "matched no packages" warning. + +! go get -d example.net/pkgadded@v1.1.0 example.net/pkgadded/subpkg/... +stderr '^go get: example.net/pkgadded@v1.1.0 conflicts with example.net/pkgadded/subpkg/...@upgrade \(v1.2.0\)$' +! stderr 'matched no packages' +cmp go.mod.orig go.mod + + +# A wildcard pattern should match the pattern with that path. + +go get -d example.net/pkgadded/...@v1.0.0 +go list -m all +stdout '^example.net/pkgadded v1.0.0' +cp go.mod.orig go.mod + + +# If we need to resolve a transitive dependency of a package, +# and another argument constrains away the version that provides that +# package, then 'go get' should fail with a useful error message. + +! go get -d example.net/pkgadded@v1.0.0 . +stderr '^example.com/m imports\n\texample.net/pkgadded/subpkg: cannot find module providing package example.net/pkgadded/subpkg$' +! stderr 'example.net/pkgadded v1\.2\.0' +cmp go.mod.orig go.mod + +go get -d example.net/pkgadded@v1.0.0 +! go list -deps -mod=readonly . +stderr '^m.go:3:8: cannot find module providing package example\.net/pkgadded/subpkg: ' + +-- go.mod -- +module example.com/m + +go 1.16 + +require example.net/pkgadded v1.2.0 +-- m.go -- +package m + +import _ "example.net/pkgadded/subpkg" diff --git a/libgo/go/cmd/go/testdata/script/mod_get_downup_artifact.txt b/libgo/go/cmd/go/testdata/script/mod_get_downup_artifact.txt new file mode 100644 index 0000000..c20583b --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_downup_artifact.txt @@ -0,0 +1,159 @@ +# This test illustrates a case where an upgrade–downgrade–upgrade cycle can +# result in upgrades of otherwise-irrelevant dependencies. +# +# This case has no corresponding test in the mvs package, because it is an +# artifact that results from the composition of *multiple* MVS operations. + +# The initial package import graph used in the test looks like: +# +# m ---- a +# | | +# +----- b +# | | +# +----- c +# | +# +----- d +# +# b version 2 adds its own import of package d. +# +# The module dependency graph initially looks like: +# +# m ---- a.1 +# | | +# +----- b.1 +# | | +# +----- c.1 +# | +# +----- d.1 +# +# b.2 ---- c.2 +# | +# +------ d.2 +# | +# +------ e.1 +# +# If we upgrade module b to version 2, we will upgrade c and d and add a new +# dependency on e. If b version 2 is disallowed because of any of those +# dependencies, the other dependencies should not be upgraded as a side-effect. + +cp go.mod go.mod.orig +go mod tidy +cmp go.mod go.mod.orig + +go list -m all +stdout '^example.com/a v0.1.0 ' +stdout '^example.com/b v0.1.0 ' +stdout '^example.com/c v0.1.0 ' +stdout '^example.com/d v0.1.0 ' +! stdout '^example.com/e ' + +# b is imported by a, so the -u flag would normally upgrade it to v0.2.0. +# However, that would conflict with the explicit c@v0.1.0 constraint, +# so b must remain at v0.1.0. +# +# If we're not careful, we might temporarily add b@v0.2.0 and pull in its +# upgrades of module d and addition of module e, which are not relevant to +# b@v0.1.0 and should not be added to the main module's dependencies. + +go get -u -d example.com/a@latest example.com/c@v0.1.0 + +go list -m all +stdout '^example.com/a v0.1.0 ' +stdout '^example.com/b v0.1.0 ' +stdout '^example.com/c v0.1.0 ' +stdout '^example.com/d v0.1.0 ' +! stdout '^example.com/e ' + +-- go.mod -- +module example.com/m + +go 1.16 + +require ( + example.com/a v0.1.0 + example.com/b v0.1.0 + example.com/c v0.1.0 + example.com/d v0.1.0 +) + +replace ( + example.com/a v0.1.0 => ./a1 + example.com/b v0.1.0 => ./b1 + example.com/b v0.2.0 => ./b2 + example.com/c v0.1.0 => ./c + example.com/c v0.2.0 => ./c + example.com/d v0.1.0 => ./d + example.com/d v0.2.0 => ./d + example.com/e v0.1.0 => ./e +) +-- m.go -- +package m + +import ( + _ "example.com/a" + _ "example.com/b" + _ "example.com/c" + _ "example.com/d" +) + +-- a1/go.mod -- +module example.com/a + +go 1.16 + +require example.com/b v0.1.0 +-- a1/a.go -- +package a + +import _ "example.com/b" + +-- b1/go.mod -- +module example.com/b + +go 1.16 + +require example.com/c v0.1.0 +-- b1/b.go -- +package b + +import _ "example.com/c" + +-- b2/go.mod -- +module example.com/b + +go 1.16 + +require ( + example.com/c v0.2.0 + example.com/d v0.2.0 + example.com/e v0.1.0 +) +-- b2/b.go -- +package b + +import ( + "example.com/c" + "example.com/d" + "example.com/e" +) + +-- c/go.mod -- +module example.com/c + +go 1.16 +-- c/c.go -- +package c + +-- d/go.mod -- +module example.com/d + +go 1.16 +-- d/d.go -- +package d + +-- e/go.mod -- +module example.com/e + +go 1.16 +-- e/e.go -- +package e diff --git a/libgo/go/cmd/go/testdata/script/mod_get_downup_indirect.txt b/libgo/go/cmd/go/testdata/script/mod_get_downup_indirect.txt new file mode 100644 index 0000000..ced1dcd --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_downup_indirect.txt @@ -0,0 +1,101 @@ +# This test illustrates a case where downgrading one module may upgrade another. +# Compare to the downcross1 test case in cmd/go/internal/mvs/mvs_test.go. + +# The package import graph used in this test looks like: +# +# a ---- b +# \ \ +# \ \ +# ----- c ---- d +# +# The module dependency graph originally looks like: +# +# a ---- b.2 +# \ \ +# \ \ +# ----- c.1 ---- d.2 +# +# b.1 ---- c.2 +# +# If we downgrade module d to version 1, we must downgrade b as well. +# If that downgrade selects b version 1, we will upgrade module c to version 2. +# So 'go get d@1' should instead downgrade both b and c to "none". + +cp go.mod go.mod.orig +go mod tidy +cmp go.mod.orig go.mod + +go get -d example.com/d@v0.1.0 +go list -m all +! stdout '^example.com/b ' +! stdout '^example.com/c ' +stdout '^example.com/d v0.1.0 ' + +-- go.mod -- +module example.com/a + +go 1.15 + +require ( + example.com/b v0.2.0 + example.com/c v0.1.0 +) + +replace ( + example.com/b v0.1.0 => ./b1 + example.com/b v0.2.0 => ./b2 + example.com/c v0.1.0 => ./c1 + example.com/c v0.2.0 => ./c2 + example.com/d v0.1.0 => ./d + example.com/d v0.2.0 => ./d +) +-- a.go -- +package a + +import ( + _ "example.com/b" + _ "example.com/c" +) + +-- b1/go.mod -- +module example.com/b + +go 1.15 + +require example.com/c v0.2.0 +-- b1/b.go -- +package b + +import _ "example.com/c" + +-- b2/go.mod -- +module example.com/b + +go 1.15 + +require example.com/c v0.1.0 +-- b2/b.go -- +package b + +import _ "example.com/c" + +-- c1/go.mod -- +module example.com/c + +go 1.15 + +require example.com/d v0.2.0 +-- c1/c.go -- +package c + +-- c2/go.mod -- +module example.com/c + +go 1.15 +-- c2/c.go -- +package c + +-- d/go.mod -- +module example.com/d + +go 1.15 diff --git a/libgo/go/cmd/go/testdata/script/mod_get_downup_pseudo_artifact.txt b/libgo/go/cmd/go/testdata/script/mod_get_downup_pseudo_artifact.txt new file mode 100644 index 0000000..c49615ce --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_downup_pseudo_artifact.txt @@ -0,0 +1,129 @@ +# This test illustrates a case where an upgrade–downgrade–upgrade cycle could +# add extraneous dependencies due to another module depending on an +# otherwise-unlisted version (such as a pseudo-version). +# +# This case corresponds to the "downhiddenartifact" test in the mvs package. + +# The initial package import graph used in the test looks like: +# +# a --- b +# \ \ +# \ \ +# c --- d +# +# The module dependency graph initially looks like: +# +# a --- b.3 +# \ \ +# \ \ +# c.2 --- d.2 +# +# c.1 --- b.2 (pseudo) +# +# b.1 --- e.1 + +cp go.mod go.mod.orig +go mod tidy +cmp go.mod.orig go.mod + +# When we downgrade d.2 to d.1, no dependency on e should be added +# because nothing else in the module or import graph requires it. +go get -d example.net/d@v0.1.0 + +go list -m all +stdout '^example.net/b v0.2.1-0.20210219000000-000000000000 ' +stdout '^example.net/c v0.1.0 ' +stdout '^example.net/d v0.1.0 ' +! stdout '^example.net/e ' + +-- go.mod -- +module example.net/a + +go 1.16 + +require ( + example.net/b v0.3.0 + example.net/c v0.2.0 +) + +replace ( + example.net/b v0.1.0 => ./b1 + example.net/b v0.2.1-0.20210219000000-000000000000 => ./b2 + example.net/b v0.3.0 => ./b3 + example.net/c v0.1.0 => ./c1 + example.net/c v0.2.0 => ./c2 + example.net/d v0.1.0 => ./d + example.net/d v0.2.0 => ./d + example.net/e v0.1.0 => ./e +) +-- a.go -- +package a + +import ( + _ "example.net/b" + _ "example.net/c" +) + +-- b1/go.mod -- +module example.net/b + +go 1.16 + +require example.net/e v0.1.0 +-- b1/b.go -- +package b + +import _ "example.net/e" + +-- b2/go.mod -- +module example.net/b + +go 1.16 +-- b2/b.go -- +package b + +-- b3/go.mod -- +module example.net/b + +go 1.16 + +require example.net/d v0.2.0 +-- b3/b.go -- +package b + +import _ "example.net/d" +-- c1/go.mod -- +module example.net/c + +go 1.16 + +require example.net/b v0.2.1-0.20210219000000-000000000000 +-- c1/c.go -- +package c + +import _ "example.net/b" + +-- c2/go.mod -- +module example.net/c + +go 1.16 + +require example.net/d v0.2.0 +-- c2/c.go -- +package c + +import _ "example.net/d" + +-- d/go.mod -- +module example.net/d + +go 1.16 +-- d/d.go -- +package d + +-- e/go.mod -- +module example.net/e + +go 1.16 +-- e/e.go -- +package e diff --git a/libgo/go/cmd/go/testdata/script/mod_get_errors.txt b/libgo/go/cmd/go/testdata/script/mod_get_errors.txt new file mode 100644 index 0000000..5c37058 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_errors.txt @@ -0,0 +1,69 @@ +cp go.mod go.mod.orig + + +# Both 'go get' and 'go get -d' should fail, without updating go.mod, +# if the transitive dependencies of the requested package (by default, +# the package in the current directory) cannot be resolved. + +! go get +stderr '^example.com/m imports\n\texample.com/badimport imports\n\texample.net/oops: cannot find module providing package example.net/oops$' +cmp go.mod.orig go.mod + +! go get -d +stderr '^example.com/m imports\n\texample.com/badimport imports\n\texample.net/oops: cannot find module providing package example.net/oops$' +cmp go.mod.orig go.mod + +cd importsyntax + + +# If 'go get' fails due to a compile error (such as a syntax error), +# it should not update the go.mod file. + +! go get +stderr '^..[/\\]badimport[/\\]syntaxerror[/\\]syntaxerror.go:1:1: expected ''package'', found pack$' # TODO: An import stack would be nice. +cmp ../go.mod.orig ../go.mod + + +# A syntax error in a dependency prevents the compiler from needing that +# dependency's imports, so 'go get -d' should not report an error when those +# imports cannot be resolved: it has all of the dependencies that the compiler +# needs, and the user did not request to run the compiler. + +go get -d +cmp ../go.mod.syntax-d ../go.mod + + +-- go.mod -- +module example.com/m + +go 1.16 + +replace example.com/badimport v0.1.0 => ./badimport +-- go.mod.syntax-d -- +module example.com/m + +go 1.16 + +replace example.com/badimport v0.1.0 => ./badimport + +require example.com/badimport v0.1.0 +-- m.go -- +package m + +import _ "example.com/badimport" +-- importsyntax/importsyntax.go -- +package importsyntax + +import _ "example.com/badimport/syntaxerror" +-- badimport/go.mod -- +module example.com/badimport + +go 1.16 +-- badimport/badimport.go -- +package badimport + +import "example.net/oops" +-- badimport/syntaxerror/syntaxerror.go -- +pack-age syntaxerror // sic + +import "example.net/oops" diff --git a/libgo/go/cmd/go/testdata/script/mod_get_extra.txt b/libgo/go/cmd/go/testdata/script/mod_get_extra.txt new file mode 100644 index 0000000..7efa24e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_extra.txt @@ -0,0 +1,69 @@ +cp go.mod go.mod.orig + +# The -u flag should not (even temporarily) upgrade modules whose versions are +# determined by explicit queries to any version other than the explicit one. +# Otherwise, 'go get -u' could introduce spurious dependencies. + +go get -d -u example.net/a@v0.1.0 example.net/b@v0.1.0 +go list -m all +stdout '^example.net/a v0.1.0 ' +stdout '^example.net/b v0.1.0 ' +! stdout '^example.net/c ' + + +# TODO(bcmills): This property does not yet hold for modules added for +# missing packages when the newly-added module matches a wildcard. + +cp go.mod.orig go.mod + +go get -d -u example.net/a@v0.1.0 example.net/b/...@v0.1.0 +go list -m all +stdout '^example.net/a v0.1.0 ' +stdout '^example.net/b v0.1.0 ' +stdout '^example.net/c ' # BUG, but a minor and rare one + + +-- go.mod -- +module example + +go 1.15 + +replace ( + example.net/a v0.1.0 => ./a1 + example.net/b v0.1.0 => ./b1 + example.net/b v0.2.0 => ./b2 + example.net/c v0.1.0 => ./c1 + example.net/c v0.2.0 => ./c1 +) + +-- a1/go.mod -- +module example.net/a + +go 1.15 + +// example.net/a needs a dependency on example.net/b, but lacks a requirement +// on it (perhaps due to a missed file in a VCS commit). +-- a1/a.go -- +package a +import _ "example.net/b" + +-- b1/go.mod -- +module example.net/b + +go 1.15 +-- b1/b.go -- +package b + +-- b2/go.mod -- +module example.net/b + +go 1.15 + +require example.net/c v0.1.0 +-- b2/b.go -- +package b + +-- c1/go.mod -- +module example.net/c + +go 1.15 diff --git a/libgo/go/cmd/go/testdata/script/mod_get_fossil.txt b/libgo/go/cmd/go/testdata/script/mod_get_fossil.txt new file mode 100644 index 0000000..baad544 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_fossil.txt @@ -0,0 +1,29 @@ +[!net] skip +[!exec:fossil] skip + +# Regression test for 'go get' to ensure repositories +# provided by fossil v2.12 and up are able to be fetched +# and parsed correctly. +# Verifies golang.org/issue/42323. + + +env GO111MODULE=on +env GOPROXY=direct +env GOSUMDB=off + +# 'go get' for the fossil repo will fail if fossil +# is unable to determine your fossil user. Easiest +# way to set it for use by 'go get' is specifying +# a any non-empty $USER; the value doesn't otherwise matter. +env USER=fossiluser +env FOSSIL_HOME=$WORK/home + +# Attempting to get the latest version of a fossil repo. +go get vcs-test.golang.org/fossil/hello.fossil +! stderr 'unexpected response from fossil info' +grep 'vcs-test.golang.org/fossil/hello.fossil' go.mod +exists $GOPATH/bin/hello.fossil$GOEXE + +-- go.mod -- +module x +-- $WORK/home/.fossil -- diff --git a/libgo/go/cmd/go/testdata/script/mod_get_go_file.txt b/libgo/go/cmd/go/testdata/script/mod_get_go_file.txt new file mode 100644 index 0000000..0c7b5dc --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_go_file.txt @@ -0,0 +1,68 @@ +# Tests Issue #38478 +# Tests that go get in GOMOD mode returns a specific error if the argument +# ends with '.go', has no version, and either has no slash or refers to an +# existing file. + +env GO111MODULE=on + +# argument doesn't have .go suffix and has no version +! go get test +! stderr 'arguments must be package or module paths' +! stderr 'exists as a file, but ''go get'' requires package arguments' + +# argument has .go suffix and has version +! go get test.go@v1.0.0 +! stderr 'arguments must be package or module paths' +! stderr 'exists as a file, but ''go get'' requires package arguments' + +# argument has .go suffix, is a file and exists +! go get test.go +stderr 'go get test.go: arguments must be package or module paths' + +# argument has .go suffix, doesn't exist and has no slashes +! go get test_missing.go +stderr 'arguments must be package or module paths' + +# argument has .go suffix, is a file and exists in sub-directory +! go get test/test.go +stderr 'go get: test/test.go exists as a file, but ''go get'' requires package arguments' + +# argument has .go suffix, doesn't exist and has slashes +! go get test/test_missing.go +! stderr 'arguments must be package or module paths' +! stderr 'exists as a file, but ''go get'' requires package arguments' + +# argument has .go suffix, is a symlink and exists +[symlink] symlink test_sym.go -> test.go +[symlink] ! go get test_sym.go +[symlink] stderr 'go get test_sym.go: arguments must be package or module paths' +[symlink] rm test_sym.go + +# argument has .go suffix, is a symlink and exists in sub-directory +[symlink] symlink test/test_sym.go -> test.go +[symlink] ! go get test/test_sym.go +[symlink] stderr 'go get: test/test_sym.go exists as a file, but ''go get'' requires package arguments' +[symlink] rm test_sym.go + +# argument has .go suffix, is a directory and exists +mkdir test_dir.go +! go get test_dir.go +stderr 'go get test_dir.go: arguments must be package or module paths' +rm test_dir.go + +# argument has .go suffix, is a directory and exists in sub-directory +mkdir test/test_dir.go +! go get test/test_dir.go +! stderr 'arguments must be package or module paths' +! stderr 'exists as a file, but ''go get'' requires package arguments' +rm test/test_dir.go + + +-- test.go -- +package main +func main() {println("test")} + + +-- test/test.go -- +package main +func main() {println("test")} diff --git a/libgo/go/cmd/go/testdata/script/mod_get_insecure_redirect.txt b/libgo/go/cmd/go/testdata/script/mod_get_insecure_redirect.txt index 3755f17..2e12834 100644 --- a/libgo/go/cmd/go/testdata/script/mod_get_insecure_redirect.txt +++ b/libgo/go/cmd/go/testdata/script/mod_get_insecure_redirect.txt @@ -1,4 +1,4 @@ -# golang.org/issue/29591: 'go get' was following plain-HTTP redirects even without -insecure. +# golang.org/issue/29591: 'go get' was following plain-HTTP redirects even without -insecure (now replaced by GOINSECURE). [!net] skip [!exec:git] skip @@ -10,8 +10,6 @@ env GOSUMDB=off ! go get -d vcs-test.golang.org/insecure/go/insecure stderr 'redirected .* to insecure URL' -go get -d -insecure vcs-test.golang.org/insecure/go/insecure - # insecure host env GOINSECURE=vcs-test.golang.org go clean -modcache diff --git a/libgo/go/cmd/go/testdata/script/mod_get_issue37438.txt b/libgo/go/cmd/go/testdata/script/mod_get_issue37438.txt new file mode 100644 index 0000000..38b2031 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_issue37438.txt @@ -0,0 +1,37 @@ +# Regression test for https://golang.org/issue/37438. +# +# If a path exists at the requested version, but does not exist at the +# version of the module that is already required and does not exist at +# the version that would be selected by 'go mod tidy', then +# 'go get foo@requested' should resolve the requested version, +# not error out on the (unrelated) latest one. + +go get -d example.net/a/p@v0.2.0 + +-- go.mod -- +module example + +go 1.15 + +require example.net/a v0.1.0 + +replace ( + example.net/a v0.1.0 => ./a1 + example.net/a v0.2.0 => ./a2 + example.net/a v0.3.0 => ./a1 +) + +-- a1/go.mod -- +module example.net/a + +go 1.15 +-- a1/README -- +package example.net/a/p does not exist at this version. + +-- a2/go.mod -- +module example.net/a + +go 1.15 +-- a2/p/p.go -- +// Package p exists only at v0.2.0. +package p diff --git a/libgo/go/cmd/go/testdata/script/mod_get_lazy_indirect.txt b/libgo/go/cmd/go/testdata/script/mod_get_lazy_indirect.txt new file mode 100644 index 0000000..1cef9d1 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_lazy_indirect.txt @@ -0,0 +1,44 @@ +# https://golang.org/issue/45979: after 'go get' on a package, +# that package should be importable without error. + + +# We start out with an unresolved dependency. +# 'go list' suggests that we run 'go get' on that dependency. + +! go list -deps . +stderr '^m.go:3:8: no required module provides package rsc\.io/quote; to add it:\n\tgo get rsc.io/quote$' + + +# When we run the suggested 'go get' command, the new dependency can be used +# immediately. +# +# 'go get' marks the new dependency as 'indirect', because it doesn't scan +# enough source code to know whether it is direct, and it is easier and less +# invasive to remove an incorrect indirect mark (e.g. using 'go get') than to +# add one that is missing ('go mod tidy' or 'go mod vendor'). + +go get rsc.io/quote +grep 'rsc.io/quote v\d+\.\d+\.\d+ // indirect$' go.mod +! grep 'rsc.io/quote v\d+\.\d+\.\d+$' go.mod + +go list -deps . +! stderr . +[!short] go build . +[!short] ! stderr . + + +# 'go get .' (or 'go mod tidy') removes the indirect mark. + +go get . +grep 'rsc.io/quote v\d+\.\d+\.\d+$' go.mod +! grep 'rsc.io/quote v\d+\.\d+\.\d+ // indirect$' go.mod + + +-- go.mod -- +module example.com/m + +go 1.17 +-- m.go -- +package m + +import _ "rsc.io/quote" diff --git a/libgo/go/cmd/go/testdata/script/mod_get_missing_ziphash.txt b/libgo/go/cmd/go/testdata/script/mod_get_missing_ziphash.txt new file mode 100644 index 0000000..789d42d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_missing_ziphash.txt @@ -0,0 +1,55 @@ +# Test that if the module cache contains an extracted source directory but not +# a ziphash, 'go build' complains about a missing sum, and 'go get' adds +# the sum. Verifies #44749. + +# With a tidy go.sum, go build succeeds. This also populates the module cache. +cp go.sum.tidy go.sum +go build -n use +env GOPROXY=off +env GOSUMDB=off + +# Control case: if we delete the hash for rsc.io/quote v1.5.2, +# 'go build' reports an error. 'go get' adds the sum. +cp go.sum.bug go.sum +! go build -n use +stderr '^use.go:3:8: missing go.sum entry for module providing package rsc.io/quote \(imported by use\); to add:\n\tgo get use$' +go get -d use +cmp go.sum go.sum.tidy +go build -n use + +# If we delete the hash *and* the ziphash file, we should see the same behavior. +cp go.sum.bug go.sum +rm $WORK/gopath/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.ziphash +! go build -n use +stderr '^use.go:3:8: missing go.sum entry for module providing package rsc.io/quote \(imported by use\); to add:\n\tgo get use$' +go get -d use +cmp go.sum go.sum.tidy +go build -n use + +-- go.mod -- +module use + +go 1.16 + +require rsc.io/quote v1.5.2 +-- go.sum.tidy -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64= +rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY= +-- go.sum.bug -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw= +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 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64= +rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY= +-- use.go -- +package use + +import _ "rsc.io/quote" diff --git a/libgo/go/cmd/go/testdata/script/mod_get_nopkgs.txt b/libgo/go/cmd/go/testdata/script/mod_get_nopkgs.txt new file mode 100644 index 0000000..078e71a --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_nopkgs.txt @@ -0,0 +1,40 @@ +cd subdir + +# 'go get' on empty patterns that are necessarily local to the module +# should warn that the patterns are empty, exactly once. + +go get ./... +stderr -count=1 'matched no packages' + +go get -d ./... +stderr -count=1 'matched no packages' + +# 'go get' on patterns that could conceivably match nested modules +# should report a module resolution error. + +go get -d example.net/emptysubdir/... # control case + +! go get -d example.net/emptysubdir/subdir/... +! stderr 'matched no packages' +stderr '^go get example\.net/emptysubdir/subdir/\.\.\.: module example\.net/emptysubdir/subdir: reading http://.*: 404 Not Found\n\tserver response: 404 page not found\n\z' + +# It doesn't make sense to 'go get' a path in the standard library, +# since the standard library necessarily can't have unresolved imports. +# +# TODO(#30241): Maybe that won't always be the case? +# +# For that case, we emit a "malformed module path" error message, +# which isn't ideal either. + +! go get -d builtin/... # in GOROOT/src, but contains no packages +stderr '^go get builtin/...: malformed module path "builtin": missing dot in first path element$' + +-- go.mod -- +module example.net/emptysubdir + +go 1.16 +-- emptysubdir.go -- +// Package emptysubdir has a subdirectory containing no packages. +package emptysubdir +-- subdir/README.txt -- +This module intentionally does not contain any p diff --git a/libgo/go/cmd/go/testdata/script/mod_get_patch.txt b/libgo/go/cmd/go/testdata/script/mod_get_patch.txt new file mode 100644 index 0000000..053ef62 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_patch.txt @@ -0,0 +1,130 @@ +# This test examines the behavior of 'go get …@patch' +# See also mod_upgrade_patch.txt (focused on "-u=patch" specifically) +# and mod_get_patchmod.txt (focused on module/package ambiguities). + +cp go.mod go.mod.orig + +# example.net/b@patch refers to the patch for the version of b that was selected +# at the start of 'go get', not the version after applying other changes. + +! go get -d example.net/a@v0.2.0 example.net/b@patch +stderr '^go get: example.net/a@v0.2.0 requires example.net/b@v0.2.0, not example.net/b@patch \(v0.1.1\)$' +cmp go.mod go.mod.orig + + +# -u=patch changes the default version for other arguments to '@patch', +# but they continue to be resolved against the originally-selected version, +# not the updated one. +# +# TODO(#42360): Reconsider the change in defaults. + +! go get -d -u=patch example.net/a@v0.2.0 example.net/b +stderr '^go get: example.net/a@v0.2.0 requires example.net/b@v0.2.0, not example.net/b@patch \(v0.1.1\)$' +cmp go.mod go.mod.orig + + +# -u=patch refers to the patches for the selected versions of dependencies *after* +# applying other version changes, not the versions that were selected at the start. +# However, it should not patch versions determined by explicit arguments. + +go get -d -u=patch example.net/a@v0.2.0 +go list -m all +stdout '^example.net/a v0.2.0 ' +stdout '^example.net/b v0.2.1 ' + + +# "-u=patch all" should be equivalent to "all@patch", and should fail if the +# patched versions result in a higher-than-patch upgrade. + +cp go.mod.orig go.mod +! go get -u=patch all +stderr '^go get: example.net/a@v0.1.1 \(matching all@patch\) requires example.net/b@v0.2.0, not example.net/b@v0.1.1 \(matching all@patch\)$' +cmp go.mod go.mod.orig + + +# On the other hand, "-u=patch ./..." should patch-upgrade dependencies until +# they reach a fixed point, even if that results in higher-than-patch upgrades. + +go get -u=patch ./... +go list -m all +stdout '^example.net/a v0.1.1 ' +stdout '^example.net/b v0.2.1 ' + + +-- go.mod -- +module example + +go 1.16 + +require ( + example.net/a v0.1.0 + example.net/b v0.1.0 // indirect +) + +replace ( + example.net/a v0.1.0 => ./a10 + example.net/a v0.1.1 => ./a11 + example.net/a v0.2.0 => ./a20 + example.net/a v0.2.1 => ./a21 + example.net/b v0.1.0 => ./b + example.net/b v0.1.1 => ./b + example.net/b v0.2.0 => ./b + example.net/b v0.2.1 => ./b + example.net/b v0.3.0 => ./b + example.net/b v0.3.1 => ./b +) +-- example.go -- +package example + +import _ "example.net/a" + +-- a10/go.mod -- +module example.net/a + +go 1.16 + +require example.net/b v0.1.0 +-- a10/a.go -- +package a + +import _ "example.net/b" + +-- a11/go.mod -- +module example.net/a + +go 1.16 + +require example.net/b v0.2.0 // upgraded +-- a11/a.go -- +package a + +import _ "example.net/b" + +-- a20/go.mod -- +module example.net/a + +go 1.16 + +require example.net/b v0.2.0 +-- a20/a.go -- +package a + +import _ "example.net/b" + +-- a21/go.mod -- +module example.net/a + +go 1.16 + +require example.net/b v0.2.0 // not upgraded +-- a21/a.go -- +package a + +import _ "example.net/b" + +-- b/go.mod -- +module example.net/b + +go 1.16 +-- b/b.go -- +package b diff --git a/libgo/go/cmd/go/testdata/script/mod_get_patchbound.txt b/libgo/go/cmd/go/testdata/script/mod_get_patchbound.txt new file mode 100644 index 0000000..4fd1ec5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_patchbound.txt @@ -0,0 +1,84 @@ +# -u=patch will patch dependencies as far as possible, but not so far that they +# conflict with other command-line arguments. + +go list -m all +stdout '^example.net/a v0.1.0 ' +stdout '^example.net/b v0.1.0 ' + +go get -d -u=patch example.net/a@v0.2.0 +go list -m all +stdout '^example.net/a v0.2.0 ' +stdout '^example.net/b v0.1.1 ' # not v0.1.2, which requires …/a v0.3.0. + +-- go.mod -- +module example + +go 1.16 + +require ( + example.net/a v0.1.0 + example.net/b v0.1.0 // indirect +) + +replace ( + example.net/a v0.1.0 => ./a + example.net/a v0.2.0 => ./a + example.net/a v0.3.0 => ./a + example.net/b v0.1.0 => ./b10 + example.net/b v0.1.1 => ./b11 + example.net/b v0.1.2 => ./b12 +) +-- example.go -- +package example + +import _ "example.net/a" + +-- a/go.mod -- +module example.net/a + +go 1.16 + +require example.net/b v0.1.0 +-- a/a.go -- +package a + +import _ "example.net/b" + +-- b10/go.mod -- +module example.net/b + +go 1.16 + +require example.net/a v0.1.0 +-- b10/b.go -- +package b +-- b10/b_test.go -- +package b_test + +import _ "example.net/a" + +-- b11/go.mod -- +module example.net/b + +go 1.16 + +require example.net/a v0.2.0 +-- b11/b.go -- +package b +-- b11/b_test.go -- +package b_test + +import _ "example.net/a" + +-- b12/go.mod -- +module example.net/b + +go 1.16 + +require example.net/a v0.3.0 +-- b12/b.go -- +package b +-- b12/b_test.go -- +package b_test + +import _ "example.net/a" diff --git a/libgo/go/cmd/go/testdata/script/mod_get_patchcycle.txt b/libgo/go/cmd/go/testdata/script/mod_get_patchcycle.txt new file mode 100644 index 0000000..d1db56f --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_patchcycle.txt @@ -0,0 +1,64 @@ +# If a patch of a module requires a higher version of itself, +# it should be reported as its own conflict. +# +# This case is weird and unlikely to occur often at all, but it should not +# spuriously succeed. +# (It used to print v0.1.1 but then silently upgrade to v0.2.0.) + +! go get example.net/a@patch +stderr '^go get: example.net/a@patch \(v0.1.1\) requires example.net/a@v0.2.0, not example.net/a@patch \(v0.1.1\)$' # TODO: A mention of b v0.1.0 would be nice. + +-- go.mod -- +module example + +go 1.16 + +require example.net/a v0.1.0 + +replace ( + example.net/a v0.1.0 => ./a10 + example.net/a v0.1.1 => ./a11 + example.net/a v0.2.0 => ./a20 + example.net/b v0.1.0 => ./b10 +) +-- example.go -- +package example + +import _ "example.net/a" + +-- a10/go.mod -- +module example.net/a + +go 1.16 +-- a10/a.go -- +package a + +-- a11/go.mod -- +module example.net/a + +go 1.16 + +require example.net/b v0.1.0 +-- a11/a.go -- +package a + +import _ "example.net/b" + +-- a20/go.mod -- +module example.net/a + +go 1.16 +-- a20/a.go -- +package a + + +-- b10/go.mod -- +module example.net/b + +go 1.16 + +require example.net/a v0.2.0 +-- b10/b.go -- +package b + +import _ "example.net/a" diff --git a/libgo/go/cmd/go/testdata/script/mod_get_patchmod.txt b/libgo/go/cmd/go/testdata/script/mod_get_patchmod.txt new file mode 100644 index 0000000..e39d13a --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_patchmod.txt @@ -0,0 +1,82 @@ +# example.net/pkgremoved@v0.1.0 refers to a package. +go get -d example.net/pkgremoved@v0.1.0 + +go list example.net/pkgremoved +stdout '^example.net/pkgremoved' + +cp go.mod go.mod.orig + + +# When we resolve a new dependency on example.net/other, +# it will change the meaning of the path "example.net/pkgremoved" +# from a package (at v0.1.0) to only a module (at v0.2.0). +# +# If we simultaneously 'get' that module at the query "patch", the module should +# be constrained to the latest patch of its originally-selected version (v0.1.0), +# not upgraded to the latest patch of the new transitive dependency. + +! go get -d example.net/pkgremoved@patch example.net/other@v0.1.0 +stderr '^go get: example.net/other@v0.1.0 requires example.net/pkgremoved@v0.2.0, not example.net/pkgremoved@patch \(v0.1.1\)$' +cmp go.mod.orig go.mod + + +# However, we should be able to patch from a package to a module and vice-versa. + +# Package to module ... + +go get -d example.net/pkgremoved@v0.3.0 +go list example.net/pkgremoved +stdout 'example.net/pkgremoved' + +go get -d example.net/pkgremoved@patch +! go list example.net/pkgremoved + +# ... and module to package. + +go get -d example.net/pkgremoved@v0.4.0 +! go list example.net/pkgremoved + +go get -d example.net/pkgremoved@patch +go list example.net/pkgremoved +stdout 'example.net/pkgremoved' + + +-- go.mod -- +module example + +go 1.16 + +replace ( + example.net/other v0.1.0 => ./other + + example.net/pkgremoved v0.1.0 => ./prpkg + example.net/pkgremoved v0.1.1 => ./prpkg + + example.net/pkgremoved v0.2.0 => ./prmod + example.net/pkgremoved v0.2.1 => ./prmod + + example.net/pkgremoved v0.3.0 => ./prpkg + example.net/pkgremoved v0.3.1 => ./prmod + + example.net/pkgremoved v0.4.0 => ./prmod + example.net/pkgremoved v0.4.1 => ./prpkg +) +-- other/go.mod -- +module example.net/other + +go 1.16 + +require example.net/pkgremoved v0.2.0 +-- other/other.go -- +package other +-- prpkg/go.mod -- +module example.net/pkgremoved + +go 1.16 +-- prpkg/pkgremoved.go -- +package pkgremoved +-- prmod/go.mod -- +module example.net/pkgremoved +-- prmod/README.txt -- +Package pkgremoved was removed in v0.2.0 and v0.3.1, +and added in v0.1.0 and v0.4.1. diff --git a/libgo/go/cmd/go/testdata/script/mod_get_pkgtags.txt b/libgo/go/cmd/go/testdata/script/mod_get_pkgtags.txt new file mode 100644 index 0000000..0c79ec7 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_pkgtags.txt @@ -0,0 +1,130 @@ +# https://golang.org/issue/44106 +# 'go get' should fetch the transitive dependencies of packages regardless of +# tags, but shouldn't error out if the package is missing tag-guarded +# dependencies. + +# Control case: just adding the top-level module to the go.mod file does not +# fetch its dependencies. + +go mod edit -require example.net/tools@v0.1.0 +! go list -deps example.net/cmd/tool +stderr '^module example\.net/cmd provides package example\.net/cmd/tool and is replaced but not required; to add it:\n\tgo get example\.net/cmd@v0\.1\.0$' +go mod edit -droprequire example.net/tools + + +# 'go get -d' makes a best effort to fetch those dependencies, but shouldn't +# error out if dependencies of tag-guarded files are missing. + +go get -d example.net/tools@v0.1.0 +! stderr 'no Go source files' + +! go list example.net/tools +stderr '^package example.net/tools: build constraints exclude all Go files in .*[/\\]tools$' + +go list -tags=tools -e -deps example.net/tools +stdout '^example.net/cmd/tool$' +stdout '^example.net/missing$' + +go list -deps example.net/cmd/tool + +! go list example.net/missing +stderr '^no required module provides package example.net/missing; to add it:\n\tgo get example.net/missing$' + + +# https://golang.org/issue/33526: 'go get' without '-d' should succeed +# for a module whose root is a constrained-out package. +# +# Ideally it should silently succeed, but today it logs the "no Go source files" +# error and succeeds anyway. + +go get example.net/tools@v0.1.0 +! stderr . + +! go build example.net/tools +stderr '^package example.net/tools: build constraints exclude all Go files in .*[/\\]tools$' + + +# https://golang.org/issue/29268 +# 'go get' should fetch modules whose roots contain test-only packages, but +# without the -t flag shouldn't error out if the test has missing dependencies. + +go get -d example.net/testonly@v0.1.0 + +# With the -t flag, the test dependencies must resolve successfully. +! go get -d -t example.net/testonly@v0.1.0 +stderr '^example.net/testonly tested by\n\texample.net/testonly\.test imports\n\texample.net/missing: cannot find module providing package example.net/missing$' + + +# 'go get -d' should succeed for a module path that does not contain a package, +# but fail for a non-package subdirectory of a module. + +! go get -d example.net/missing/subdir@v0.1.0 +stderr '^go get: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$' + +go get -d example.net/missing@v0.1.0 + + +# Getting the subdirectory should continue to fail even if the corresponding +# module is already present in the build list. + +! go get -d example.net/missing/subdir@v0.1.0 +stderr '^go get: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$' + + +-- go.mod -- +module example.net/m + +go 1.15 + +replace ( + example.net/tools v0.1.0 => ./tools + example.net/cmd v0.1.0 => ./cmd + example.net/testonly v0.1.0 => ./testonly + example.net/missing v0.1.0 => ./missing +) + +-- tools/go.mod -- +module example.net/tools + +go 1.15 + +// Requirements intentionally omitted. + +-- tools/tools.go -- +// +build tools + +package tools + +import ( + _ "example.net/cmd/tool" + _ "example.net/missing" +) + +-- cmd/go.mod -- +module example.net/cmd + +go 1.16 +-- cmd/tool/tool.go -- +package main + +func main() {} + +-- testonly/go.mod -- +module example.net/testonly + +go 1.15 +-- testonly/testonly_test.go -- +package testonly_test + +import _ "example.net/missing" + +func Test(t *testing.T) {} + +-- missing/go.mod -- +module example.net/missing + +go 1.15 +-- missing/README.txt -- +There are no Go source files here. +-- missing/subdir/README.txt -- +There are no Go source files here either. diff --git a/libgo/go/cmd/go/testdata/script/mod_get_prefer_incompatible.txt b/libgo/go/cmd/go/testdata/script/mod_get_prefer_incompatible.txt new file mode 100644 index 0000000..be3db42 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_prefer_incompatible.txt @@ -0,0 +1,29 @@ +# Verifies golang.org/issue/37574. + +# If we are already using an +incompatible version, we shouldn't look up +# a lower compatible version when upgrading. +cp go.mod go.mod.orig +go mod tidy +cmp go.mod.orig go.mod +grep '^example.com/incompatiblewithsub v2\.0\.0\+incompatible' go.sum +! grep '^example.com/incompatiblewithsub v1.0.0' go.sum + +go get -d example.com/incompatiblewithsub/sub +cmp go.mod.orig go.mod +! grep '^example.com/incompatiblewithsub v1.0.0' go.sum + +# TODO(golang.org/issue/31580): the 'go get' command above should not change +# go.sum. However, as part of the query above, we download example.com@v1.0.0, +# an unrelated module, since it's a possible prefix. The sum for that module +# should not be written to go.sum. + +-- go.mod -- +module m + +go 1.15 + +require example.com/incompatiblewithsub v2.0.0+incompatible +-- use.go -- +package use + +import _ "example.com/incompatiblewithsub/sub" diff --git a/libgo/go/cmd/go/testdata/script/mod_get_private_vcs.txt b/libgo/go/cmd/go/testdata/script/mod_get_private_vcs.txt index 514b0a7..75c776a 100644 --- a/libgo/go/cmd/go/testdata/script/mod_get_private_vcs.txt +++ b/libgo/go/cmd/go/testdata/script/mod_get_private_vcs.txt @@ -9,3 +9,35 @@ env GOPROXY=direct stderr 'Confirm the import path was entered correctly.' stderr 'If this is a private repository, see https://golang.org/doc/faq#git_https for additional information.' ! stdout . + +# Fetching a nonexistent commit should return an "unknown revision" +# error message. +! go get github.com/golang/term@86186f3aba07ed0212cfb944f3398997d2d07c6b +stderr '^go get: github.com/golang/term@86186f3aba07ed0212cfb944f3398997d2d07c6b: invalid version: unknown revision 86186f3aba07ed0212cfb944f3398997d2d07c6b$' +! stdout . + +! go get github.com/golang/nonexist@master +stderr '^Confirm the import path was entered correctly.$' +stderr '^If this is a private repository, see https://golang.org/doc/faq#git_https for additional information.$' +! stderr 'unknown revision' +! stdout . + +[!linux] stop # Needs XDG_CONFIG_HOME. +[!exec:false] stop + +# Test that Git clone errors will be shown to the user instead of a generic +# "unknown revision" error. To do this we want to force git ls-remote to return +# an error we don't already have special handling for. See golang/go#42751. +# +# Set XDG_CONFIG_HOME to tell Git where to look for the git config file listed +# below, which turns on ssh. +env XDG_CONFIG_HOME=$TMPDIR +env GIT_SSH_COMMAND=false +! go install github.com/golang/nonexist@master +stderr 'fatal: Could not read from remote repository.' +! stderr 'unknown revision' +! stdout . + +-- $TMPDIR/git/config -- +[url "git@github.com:"] + insteadOf = https://github.com/ diff --git a/libgo/go/cmd/go/testdata/script/mod_get_promote_implicit.txt b/libgo/go/cmd/go/testdata/script/mod_get_promote_implicit.txt new file mode 100644 index 0000000..9eec201 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_promote_implicit.txt @@ -0,0 +1,92 @@ +cp go.mod.orig go.mod + +# If we list a package in an implicit dependency imported from the main module, +# we should get an error because the dependency should have an explicit +# requirement. +go list -m indirect-with-pkg +stdout '^indirect-with-pkg v1.0.0 => ./indirect-with-pkg$' +! go list ./use-indirect +stderr '^package m/use-indirect imports indirect-with-pkg from implicitly required module; to add missing requirements, run:\n\tgo get indirect-with-pkg@v1.0.0$' + +# We can promote the implicit requirement by getting the importing package. +# NOTE: the hint recommends getting the imported package (tested below) since +# it's more obvious and doesn't require -d. However, that adds an '// indirect' +# comment on the requirement. +go get -d m/use-indirect +cmp go.mod go.mod.use +cp go.mod.orig go.mod + +# We can also promote implicit requirements using 'go get' on them, or their +# packages. This gives us "// indirect" requirements, since 'go get' doesn't +# know they're needed by the main module. See #43131 for the rationale. +# The hint above recommends this because it's more obvious usage and doesn't +# require the -d flag. +go get -d indirect-with-pkg indirect-without-pkg +cmp go.mod go.mod.indirect + +-- go.mod.orig -- +module m + +go 1.16 + +require direct v1.0.0 + +replace ( + direct v1.0.0 => ./direct + indirect-with-pkg v1.0.0 => ./indirect-with-pkg + indirect-without-pkg v1.0.0 => ./indirect-without-pkg +) +-- go.mod.use -- +module m + +go 1.16 + +require ( + direct v1.0.0 + indirect-with-pkg v1.0.0 +) + +replace ( + direct v1.0.0 => ./direct + indirect-with-pkg v1.0.0 => ./indirect-with-pkg + indirect-without-pkg v1.0.0 => ./indirect-without-pkg +) +-- go.mod.indirect -- +module m + +go 1.16 + +require ( + direct v1.0.0 + indirect-with-pkg v1.0.0 // indirect + indirect-without-pkg v1.0.0 // indirect +) + +replace ( + direct v1.0.0 => ./direct + indirect-with-pkg v1.0.0 => ./indirect-with-pkg + indirect-without-pkg v1.0.0 => ./indirect-without-pkg +) +-- use-indirect/use-indirect.go -- +package use + +import _ "indirect-with-pkg" +-- direct/go.mod -- +module direct + +go 1.16 + +require ( + indirect-with-pkg v1.0.0 + indirect-without-pkg v1.0.0 +) +-- indirect-with-pkg/go.mod -- +module indirect-with-pkg + +go 1.16 +-- indirect-with-pkg/p.go -- +package p +-- indirect-without-pkg/go.mod -- +module indirect-without-pkg + +go 1.16 diff --git a/libgo/go/cmd/go/testdata/script/mod_get_replaced.txt b/libgo/go/cmd/go/testdata/script/mod_get_replaced.txt new file mode 100644 index 0000000..d97f3f1 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_replaced.txt @@ -0,0 +1,111 @@ +cp go.mod go.mod.orig + +env oldGOPROXY=$GOPROXY + +# If a wildcard replacement exists for an otherwise-nonexistent module, +# 'go get' should resolve it to the minimum valid pseudo-version. + +go mod edit -replace=example.com/x=./x +go get -d example.com/x + +go list -m example.com/x +stdout '^example.com/x v0.0.0-00010101000000-000000000000 ' + +# If specific-version replacements exist, the highest matching version should be used. +go mod edit -replace=example.com/x@v0.1.0=./x +go mod edit -replace=example.com/x@v0.2.0=./x + +go get -d example.com/x +go list -m example.com/x +stdout '^example.com/x v0.2.0 ' + +go get -d example.com/x@<v0.2.0 +go list -m example.com/x +stdout '^example.com/x v0.1.0 ' + + +# The same should work with GOPROXY=off. + +env GOPROXY=off +cp go.mod.orig go.mod + +go mod edit -replace=example.com/x=./x +go get -d example.com/x + +go list -m example.com/x +stdout '^example.com/x v0.0.0-00010101000000-000000000000 ' + +# If specific-version replacements exist, the highest matching version should be used. +go mod edit -replace=example.com/x@v0.1.0=./x +go mod edit -replace=example.com/x@v0.2.0=./x + +go get -d example.com/x +go list -m example.com/x +stdout '^example.com/x v0.2.0 ' + +go get -d example.com/x@<v0.2.0 +go list -m example.com/x +stdout '^example.com/x v0.1.0 ' + + +# Replacements should also be listed as known versions, and 'go get' should sort +# them in with ordinary versions. + +env GOPROXY=$oldGOPROXY + +cp go.mod.orig go.mod +go list -versions -m rsc.io/quote +stdout 'v1.3.0 v1.4.0' + +go get -d rsc.io/quote@v1.3 +go list -m rsc.io/quote +stdout '^rsc.io/quote v1.3.0' + +go mod edit -replace rsc.io/quote@v1.3.1=rsc.io/quote@v1.4.0 + +go list -versions -m rsc.io/quote +stdout 'v1.3.0 v1.3.1 v1.4.0' + +go get -d rsc.io/quote@v1.3 +go list -m rsc.io/quote +stdout '^rsc.io/quote v1.3.1 ' + +go get -d rsc.io/quote@>v1.3.1 +go list -m rsc.io/quote +stdout '^rsc.io/quote v1.4.0' + + +# Replacements should allow 'go get' to work even with dotless module paths. + +cp go.mod.orig go.mod + +! go list example +stderr '^package example is not in GOROOT \(.*\)$' +! go get -d example +stderr '^go get: malformed module path "example": missing dot in first path element$' + +go mod edit -replace example@v0.1.0=./example + +! go list example +stderr '^module example provides package example and is replaced but not required; to add it:\n\tgo get example@v0.1.0$' + +go get -d example +go list -m example +stdout '^example v0.1.0 ' + + +-- go.mod -- +module example.com + +go 1.16 +-- x/go.mod -- +module example.com/x + +go 1.16 +-- x/x.go -- +package x +-- example/go.mod -- +module example +go 1.16 +-- example/example.go -- +package example diff --git a/libgo/go/cmd/go/testdata/script/mod_get_retract.txt b/libgo/go/cmd/go/testdata/script/mod_get_retract.txt new file mode 100644 index 0000000..560fa7b --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_retract.txt @@ -0,0 +1,59 @@ +# 'go get pkg' should not upgrade to a retracted version. +cp go.mod.orig go.mod +go mod edit -require example.com/retract/self/prev@v1.1.0 +go get -d example.com/retract/self/prev +go list -m example.com/retract/self/prev +stdout '^example.com/retract/self/prev v1.1.0$' + +# 'go get pkg' should not downgrade from a retracted version when no higher +# version is available. +cp go.mod.orig go.mod +go mod edit -require example.com/retract/self/prev@v1.9.0 +go get -d example.com/retract/self/prev +stderr '^go: warning: example.com/retract/self/prev@v1.9.0: retracted by module author: self$' +stderr '^go: to switch to the latest unretracted version, run:\n\tgo get example.com/retract/self/prev@latest\n$' +go list -m example.com/retract/self/prev +stdout '^example.com/retract/self/prev v1.9.0$' + +# 'go get pkg@latest' should downgrade from a retracted version. +cp go.mod.orig go.mod +go mod edit -require example.com/retract/self/prev@v1.9.0 +go get -d example.com/retract/self/prev@latest +go list -m example.com/retract/self/prev +stdout '^example.com/retract/self/prev v1.1.0$' + +# 'go get pkg@version' should update to a specific version, even if that +# version is retracted. +cp go.mod.orig go.mod +go get -d example.com/retract@v1.0.0-bad +stderr '^go: warning: example.com/retract@v1.0.0-bad: retracted by module author: bad$' +go list -m example.com/retract +stdout '^example.com/retract v1.0.0-bad$' + +# 'go get -u' should not downgrade from a retracted version when no higher +# version is available. +cp go.mod.orig go.mod +go mod edit -require example.com/retract/self/prev@v1.9.0 +go get -d -u ./use +stderr '^go: warning: example.com/retract/self/prev@v1.9.0: retracted by module author: self$' +go list -m example.com/retract/self/prev +stdout '^example.com/retract/self/prev v1.9.0$' + +# 'go get' should warn if a module needed to build named packages is retracted. +# 'go get' should not warn about unrelated modules. +go get -d ./empty +! stderr retracted +go get -d ./use +stderr '^go: warning: example.com/retract/self/prev@v1.9.0: retracted by module author: self$' + +-- go.mod.orig -- +module example.com/use + +go 1.15 + +-- use/use.go -- +package use + +import _ "example.com/retract/self/prev" +-- empty/empty.go -- +package empty diff --git a/libgo/go/cmd/go/testdata/script/mod_get_retract_ambiguous.txt b/libgo/go/cmd/go/testdata/script/mod_get_retract_ambiguous.txt new file mode 100644 index 0000000..b49ba54 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_retract_ambiguous.txt @@ -0,0 +1,10 @@ +! go get -d example.com/retract/ambiguous/other +stderr 'ambiguous import: found package example.com/retract/ambiguous/nested in multiple modules:' +stderr '^go: warning: example.com/retract/ambiguous/nested@v1.9.0-bad: retracted by module author: nested modules are bad$' + +-- go.mod -- +module example.com/use + +go 1.16 + +require example.com/retract/ambiguous/nested v1.9.0-bad diff --git a/libgo/go/cmd/go/testdata/script/mod_get_split.txt b/libgo/go/cmd/go/testdata/script/mod_get_split.txt new file mode 100644 index 0000000..f4e7661 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_split.txt @@ -0,0 +1,157 @@ +cp go.mod go.mod.orig + + +# 'go get' on a package already provided by the build list should update +# the module already in the build list, not fail with an ambiguous import error. + +go get -d example.net/split/nested@patch +go list -m all +stdout '^example.net/split v0.2.1 ' +! stdout '^example.net/split/nested' + +# We should get the same behavior if we use a pattern that matches only that package. + +cp go.mod.orig go.mod + +go get -d example.net/split/nested/...@patch +go list -m all +stdout '^example.net/split v0.2.1 ' +! stdout '^example.net/split/nested' + + +# If we request a version for which the package only exists in one particular module, +# we should add that one particular module but not resolve import ambiguities. +# +# In particular, if the module that previously provided the package has a +# matching version, but does not itself match the pattern and contains no +# matching packages, we should not change its version. (We should *not* downgrade +# module example.net/split to v0.1.0, despite the fact that +# example.net/split v0.2.0 currently provides the package with the requested path.) +# +# TODO(#27899): Maybe we should resolve the ambiguities by upgrading. + +cp go.mod.orig go.mod + +! go get -d example.net/split/nested@v0.1.0 +stderr '^example.net/split/nested: ambiguous import: found package example.net/split/nested in multiple modules:\n\texample.net/split v0.2.0 \(.*split.2[/\\]nested\)\n\texample.net/split/nested v0.1.0 \(.*nested.1\)$' + +# A wildcard that matches packages in some module at its selected version +# but not at the requested version should fail. +# +# We can't set the module to the selected version, because that version doesn't +# even match the query: if we ran the same query twice, we wouldn't consider the +# module to match the wildcard during the second call, so why should we consider +# it to match during the first one? ('go get' should be idempotent, and if we +# did that then it would not be.) +# +# But we also can't leave it where it is: the user requested that we set everything +# matching the pattern to the given version, and right now we have packages +# that match the pattern but *not* the version. +# +# That only leaves two options: we can set the module to an arbitrary version +# (perhaps 'latest' or 'none'), or we can report an error and the let the user +# disambiguate. We would rather not choose arbitrarily, so we do the latter. +# +# TODO(#27899): Should we instead upgrade or downgrade to an arbirary version? + +! go get -d example.net/split/nested/...@v0.1.0 +stderr '^go get: example.net/split/nested/\.\.\.@v0.1.0 matches packages in example.net/split@v0.2.0 but not example.net/split@v0.1.0: specify a different version for module example.net/split$' + +cmp go.mod go.mod.orig + + +# If another argument resolves the ambiguity, we should be ok again. + +go get -d example.net/split@none example.net/split/nested@v0.1.0 +go list -m all +! stdout '^example.net/split ' +stdout '^example.net/split/nested v0.1.0 ' + +cp go.mod.orig go.mod + +go get -d example.net/split@v0.3.0 example.net/split/nested@v0.1.0 +go list -m all +stdout '^example.net/split v0.3.0 ' +stdout '^example.net/split/nested v0.1.0 ' + + +# If a pattern applies to modules and to packages, we should set all matching +# modules to the version indicated by the pattern, and also resolve packages +# to match the pattern if possible. + +cp go.mod.orig go.mod +go get -d example.net/split/nested@v0.0.0 + +go get -d example.net/...@v0.1.0 +go list -m all +stdout '^example.net/split v0.1.0 ' +stdout '^example.net/split/nested v0.1.0 ' + +go get -d example.net/... +go list -m all +stdout '^example.net/split v0.3.0 ' +stdout '^example.net/split/nested v0.2.0 ' + + +# @none applies to all matching module paths, +# regardless of whether they contain any packages. + +go get -d example.net/...@none +go list -m all +! stdout '^example.net' + +# Starting from no dependencies, a wildcard can resolve to an empty module with +# the same prefix even if it contains no packages. + +go get -d example.net/...@none +go get -d example.net/split/...@v0.1.0 +go list -m all +stdout '^example.net/split v0.1.0 ' + + +-- go.mod -- +module m + +go 1.16 + +require example.net/split v0.2.0 + +replace ( + example.net/split v0.1.0 => ./split.1 + example.net/split v0.2.0 => ./split.2 + example.net/split v0.2.1 => ./split.2 + example.net/split v0.3.0 => ./split.3 + example.net/split/nested v0.0.0 => ./nested.0 + example.net/split/nested v0.1.0 => ./nested.1 + example.net/split/nested v0.2.0 => ./nested.2 +) +-- split.1/go.mod -- +module example.net/split + +go 1.16 +-- split.2/go.mod -- +module example.net/split + +go 1.16 +-- split.2/nested/nested.go -- +package nested +-- split.3/go.mod -- +module example.net/split + +go 1.16 +-- nested.0/go.mod -- +module example.net/split/nested + +go 1.16 +-- nested.1/go.mod -- +module example.net/split/nested + +go 1.16 +-- nested.1/nested.go -- +package nested +-- nested.2/go.mod -- +module example.net/split/nested + +go 1.16 +-- nested.2/nested.go -- +package nested diff --git a/libgo/go/cmd/go/testdata/script/mod_get_sum_noroot.txt b/libgo/go/cmd/go/testdata/script/mod_get_sum_noroot.txt new file mode 100644 index 0000000..4f1cf03 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_sum_noroot.txt @@ -0,0 +1,11 @@ +# When 'go get' is invoked on a module without a package in the root directory, +# it should add sums for the module's go.mod file and its content to go.sum. +# Verifies golang.org/issue/41103. +go mod init m +go get -d rsc.io/QUOTE +grep '^rsc.io/QUOTE v1.5.2/go.mod ' go.sum +grep '^rsc.io/QUOTE v1.5.2 ' go.sum + +# Double-check rsc.io/QUOTE does not have a root package. +! go list -mod=readonly rsc.io/QUOTE +stderr '^cannot find module providing package rsc.io/QUOTE: import lookup disabled by -mod=readonly$' diff --git a/libgo/go/cmd/go/testdata/script/mod_get_too_many_redirects.txt b/libgo/go/cmd/go/testdata/script/mod_get_too_many_redirects.txt new file mode 100644 index 0000000..9cbe0d2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_too_many_redirects.txt @@ -0,0 +1,10 @@ +env GO111MODULE=on +env GOPROXYBASE=$GOPROXY +env GOPROXY=$GOPROXYBASE/redirect/11 +env GOSUMDB=off + +! go get -d rsc.io/quote@v1.2.0 +stderr 'stopped after 10 redirects' + +env GOPROXY=$GOPROXYBASE/redirect/9 +go get -d rsc.io/quote@v1.2.0 diff --git a/libgo/go/cmd/go/testdata/script/mod_get_update_unrelated_sum.txt b/libgo/go/cmd/go/testdata/script/mod_get_update_unrelated_sum.txt new file mode 100644 index 0000000..0093c0e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_update_unrelated_sum.txt @@ -0,0 +1,120 @@ +# Check that 'go get' adds sums for updated modules if we had sums before, +# even if we didn't load packages from them. +# Verifies #44129. + +env fmt='{{.ImportPath}}: {{if .Error}}{{.Error.Err}}{{else}}ok{{end}}' + +# Control case: before upgrading, we have the sums we need. +# go list -deps -e -f $fmt . +# stdout '^rsc.io/quote: ok$' +# ! stdout rsc.io/sampler # not imported by quote in this version +cp go.mod.orig go.mod +cp go.sum.orig go.sum +go mod tidy +cmp go.mod.orig go.mod +cmp go.sum.orig go.sum + + +# Upgrade a module. This also upgrades rsc.io/quote, and though we didn't load +# a package from it, we had the sum for its old version, so we need the +# sum for the new version, too. +go get -d example.com/upgrade@v0.0.2 +grep '^rsc.io/quote v1.5.2 ' go.sum + +# The upgrade still breaks the build because the new version of quote imports +# rsc.io/sampler, and we don't have its zip sum. +go list -deps -e -f $fmt +stdout 'rsc.io/quote: ok' +stdout 'rsc.io/sampler: missing go.sum entry for module providing package rsc.io/sampler' +cp go.mod.orig go.mod +cp go.sum.orig go.sum + + +# Replace the old version with a directory before upgrading. +# We didn't need a sum for it before (even though we had one), so we won't +# fetch a new sum. +go mod edit -replace rsc.io/quote@v1.0.0=./dummy +go get -d example.com/upgrade@v0.0.2 +! grep '^rsc.io/quote v1.5.2 ' go.sum +cp go.mod.orig go.mod +cp go.sum.orig go.sum + + +# Replace the new version with a directory before upgrading. +# We can't get a sum for a directory. +go mod edit -replace rsc.io/quote@v1.5.2=./dummy +go get -d example.com/upgrade@v0.0.2 +! grep '^rsc.io/quote v1.5.2 ' go.sum +cp go.mod.orig go.mod +cp go.sum.orig go.sum + + +# Replace the new version with a different version. +# We should get a sum for that version. +go mod edit -replace rsc.io/quote@v1.5.2=rsc.io/quote@v1.5.1 +go get -d example.com/upgrade@v0.0.2 +! grep '^rsc.io/quote v1.5.2 ' go.sum +grep '^rsc.io/quote v1.5.1 ' go.sum +cp go.mod.orig go.mod +cp go.sum.orig go.sum + + +# Delete the new version's zip (but not mod) from the cache and go offline. +# 'go get' should fail when fetching the zip. +rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip +env GOPROXY=off +! go get -d example.com/upgrade@v0.0.2 +stderr '^go: upgraded rsc.io/quote v1.0.0 => v1.5.2: error finding sum for rsc.io/quote@v1.5.2: module lookup disabled by GOPROXY=off$' + +-- go.mod.orig -- +module m + +go 1.16 + +require ( + example.com/upgrade v0.0.1 + rsc.io/quote v1.0.0 +) + +replace ( + example.com/upgrade v0.0.1 => ./upgrade1 + example.com/upgrade v0.0.2 => ./upgrade2 +) +-- go.sum.orig -- +rsc.io/quote v1.0.0 h1:kQ3IZQzPTiDJxSZI98YaWgxFEhlNdYASHvh+MplbViw= +rsc.io/quote v1.0.0/go.mod h1:v83Ri/njykPcgJltBc/gEkJTmjTsNgtO1Y7vyIK1CQA= +-- go.sum.want -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.0.0 h1:kQ3IZQzPTiDJxSZI98YaWgxFEhlNdYASHvh+MplbViw= +rsc.io/quote v1.0.0/go.mod h1:v83Ri/njykPcgJltBc/gEkJTmjTsNgtO1Y7vyIK1CQA= +rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +-- use.go -- +package use + +import ( + _ "example.com/upgrade" + _ "rsc.io/quote" +) +-- upgrade1/go.mod -- +module example.com/upgrade + +go 1.16 +-- upgrade1/upgrade.go -- +package upgrade +-- upgrade2/go.mod -- +module example.com/upgrade + +go 1.16 + +require rsc.io/quote v1.5.2 // indirect +-- upgrade2/upgrade.go -- +package upgrade +-- dummy/go.mod -- +module rsc.io/quote + +go 1.16 +-- dummy/quote.go -- +package quote + diff --git a/libgo/go/cmd/go/testdata/script/mod_get_wild.txt b/libgo/go/cmd/go/testdata/script/mod_get_wild.txt new file mode 100644 index 0000000..78c645c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_wild.txt @@ -0,0 +1,95 @@ +# This test covers a crazy edge-case involving wildcards and multiple passes of +# patch-upgrades, but if we get it right we probably get many other edge-cases +# right too. + +go list -m all +stdout '^example.net/a v0.1.0 ' +! stdout '^example.net/b ' + + +# Requesting pattern example.../b by itself fails: there is no such module +# already in the build list, and the wildcard in the first element prevents us +# from attempting to resolve a new module whose path is a prefix of the pattern. + +! go get -d -u=patch example.../b@upgrade +stderr '^go get: no modules to query for example\.\.\./b@upgrade because first path element contains a wildcard$' + + +# Patching . causes a patch to example.net/a, which introduces a new match +# for example.net/b/..., which is itself patched and causes another upgrade to +# example.net/a, which is then patched again. + +go get -d -u=patch . example.../b@upgrade +go list -m all +stdout '^example.net/a v0.2.1 ' # upgraded by dependency of b and -u=patch +stdout '^example.net/b v0.2.0 ' # introduced by patch of a and upgraded by wildcard + + +-- go.mod -- +module example + +go 1.16 + +require example.net/a v0.1.0 + +replace ( + example.net/a v0.1.0 => ./a10 + example.net/a v0.1.1 => ./a11 + example.net/a v0.2.0 => ./a20 + example.net/a v0.2.1 => ./a20 + example.net/b v0.1.0 => ./b1 + example.net/b v0.1.1 => ./b1 + example.net/b v0.2.0 => ./b2 +) +-- example.go -- +package example + +import _ "example.net/a" + +-- a10/go.mod -- +module example.net/a + +go 1.16 +-- a10/a.go -- +package a + +-- a11/go.mod -- +module example.net/a + +go 1.16 + +require example.net/b v0.1.0 +-- a11/a.go -- +package a +-- a11/unimported/unimported.go -- +package unimported + +import _ "example.net/b" + + +-- a20/go.mod -- +module example.net/a + +go 1.16 +-- a20/a.go -- +package a + +-- b1/go.mod -- +module example.net/b + +go 1.16 +-- b1/b.go -- +package b + +-- b2/go.mod -- +module example.net/b + +go 1.16 + +require example.net/a v0.2.0 +-- b2/b.go -- +package b +-- b2/b_test.go -- +package b_test + +import _ "example.net/a" diff --git a/libgo/go/cmd/go/testdata/script/mod_go_version_missing.txt b/libgo/go/cmd/go/testdata/script/mod_go_version_missing.txt new file mode 100644 index 0000000..d704816 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_go_version_missing.txt @@ -0,0 +1,122 @@ +cp go.mod go.mod.orig + +# For modules whose go.mod file does not include a 'go' directive, +# we assume the language and dependency semantics of Go 1.16, +# but do not trigger “automatic vendoring” mode (-mod=vendor), +# which was added in Go 1.14 and was not triggered +# under the same conditions in Go 1.16 (which would instead +# default to -mod=readonly when no 'go' directive is present). + +# For Go 1.16 modules, 'all' should prune out dependencies of tests, +# even if the 'go' directive is missing. + +go list -mod=readonly all +stdout '^example.com/dep$' +! stdout '^example.com/testdep$' +cp stdout list-1.txt +cmp go.mod go.mod.orig + +# We should only default to -mod=vendor if the 'go' directive is explicit in the +# go.mod file. Otherwise, we don't actually know whether the module was written +# against Go 1.11 or 1.16. We would have to update the go.mod file to clarify, +# and as of Go 1.16 we don't update the go.mod file by default. +# +# If we set -mod=vendor explicitly, we shouldn't apply the Go 1.14 +# consistency check, because — again — we don't know whether we're in a 1.11 +# module or a bad-script-edited 1.16 module. + +! go list -mod=vendor all +! stderr '^go: inconsistent vendoring' +stderr 'cannot find package "\." in:\n\t.*[/\\]vendor[/\\]example.com[/\\]badedit$' + +# When we set -mod=mod, the go version should be updated immediately, +# to the current version, converting the requirements from eager to lazy. +# +# Since we don't know which requirements are actually relevant to the main +# module, all requirements are added as roots, making the requirements untidy. + +go list -mod=mod all +! stdout '^example.com/testdep$' +cmp stdout list-1.txt +cmpenv go.mod go.mod.untidy + +go mod tidy +cmpenv go.mod go.mod.tidy + +# On the other hand, if we jump straight to 'go mod tidy', +# the requirements remain tidy from the start. + +cp go.mod.orig go.mod +go mod tidy +cmpenv go.mod go.mod.tidy + + +# The updated version should have been written back to go.mod, so now the 'go' +# directive is explicit. -mod=vendor should trigger by default, and the stronger +# Go 1.14 consistency check should apply. +! go list all +stderr '^go: inconsistent vendoring' +! stderr badedit + + +-- go.mod -- +module example.com/m + +require example.com/dep v0.1.0 + +replace ( + example.com/dep v0.1.0 => ./dep + example.com/testdep v0.1.0 => ./testdep +) +-- go.mod.untidy -- +module example.com/m + +go $goversion + +require example.com/dep v0.1.0 + +require example.com/testdep v0.1.0 // indirect + +replace ( + example.com/dep v0.1.0 => ./dep + example.com/testdep v0.1.0 => ./testdep +) +-- go.mod.tidy -- +module example.com/m + +go $goversion + +require example.com/dep v0.1.0 + +replace ( + example.com/dep v0.1.0 => ./dep + example.com/testdep v0.1.0 => ./testdep +) +-- vendor/example.com/dep/dep.go -- +package dep +import _ "example.com/badedit" +-- vendor/modules.txt -- +HAHAHA this is broken. + +-- m.go -- +package m + +import _ "example.com/dep" + +const x = 1_000 + +-- dep/go.mod -- +module example.com/dep + +require example.com/testdep v0.1.0 +-- dep/dep.go -- +package dep +-- dep/dep_test.go -- +package dep_test + +import _ "example.com/testdep" + +-- testdep/go.mod -- +module example.com/testdep +-- testdep/testdep.go -- +package testdep diff --git a/libgo/go/cmd/go/testdata/script/mod_gomodcache.txt b/libgo/go/cmd/go/testdata/script/mod_gomodcache.txt new file mode 100644 index 0000000..74a3c79 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_gomodcache.txt @@ -0,0 +1,67 @@ +# Test GOMODCACHE +env GO111MODULE=on + +# Explicitly set GOMODCACHE +env GOMODCACHE=$WORK/modcache +go env GOMODCACHE +stdout $WORK[/\\]modcache +go get -d rsc.io/quote@v1.0.0 +exists $WORK/modcache/cache/download/rsc.io/quote/@v/v1.0.0.info +grep '{"Version":"v1.0.0","Time":"2018-02-14T00:45:20Z"}' $WORK/modcache/cache/download/rsc.io/quote/@v/v1.0.0.info + +# Ensure GOMODCACHE doesn't affect location of sumdb, but $GOMODCACHE/cache/download/sumdb is still written +exists $GOPATH/pkg/sumdb +! exists $WORK/modcache/sumdb +exists $WORK/modcache/cache/download/sumdb + +# Test that the default GOMODCACHE is $GOPATH[0]/pkg/mod +env GOMODCACHE= +go env GOMODCACHE +stdout $GOPATH[/\\]pkg[/\\]mod +go get -d rsc.io/quote@v1.0.0 +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.0.0.info +grep '{"Version":"v1.0.0","Time":"2018-02-14T00:45:20Z"}' $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.0.0.info + +# If neither GOMODCACHE or GOPATH are set, GOPATH defaults to the user's $HOME/go, so GOMODCACHE becomes $HOME/go/pkg/mod +[windows] env USERPROFILE=$WORK/home # Ensure USERPROFILE is a valid path (rather than /no-home/ so we don't run into the logic that "uninfers" GOPATH in cmd/go/main.go +[plan9] env home=$WORK/home +[!windows] [!plan9] env HOME=$WORK/home +env GOMODCACHE= +env GOPATH= +go env GOMODCACHE +stdout $HOME[/\\]go[/\\]pkg[/\\]mod + +# If GOMODCACHE isn't set and GOPATH starts with the path list separator, it's an error. +env GOMODCACHE= +env GOPATH=${:}$WORK/this/is/ignored +! go env GOMODCACHE +stderr 'missing \$GOPATH' + +# If GOMODCACHE isn't set and GOPATH has multiple elements only the first is used. +env GOMODCACHE= +env GOPATH=$WORK/first/path${:}$WORK/this/is/ignored +go env GOMODCACHE +stdout $WORK[/\\]first[/\\]path[/\\]pkg[/\\]mod + +env GOMODCACHE=$WORK/modcache +go mod download rsc.io/quote@v1.0.0 +exists $WORK/modcache/cache/download/rsc.io/quote/@v/v1.0.0.info + +# Test error when cannot create GOMODCACHE directory +env GOMODCACHE=$WORK/modcachefile +! go install example.com/cmd/a@v1.0.0 +stderr 'go: could not create module cache' + +# Test that the following work even with GO111MODULE=off +env GO111MODULE=off + +# Cleaning modcache +exists $WORK/modcache +env GOMODCACHE=$WORK/modcache +go clean -modcache +! exists $WORK/modcache + +-- go.mod -- +module m + +-- $WORK/modcachefile -- diff --git a/libgo/go/cmd/go/testdata/script/mod_graph_version.txt b/libgo/go/cmd/go/testdata/script/mod_graph_version.txt new file mode 100644 index 0000000..f9a73f4 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_graph_version.txt @@ -0,0 +1,101 @@ +# For this module, Go 1.17 prunes out a (transitive and otherwise-irrelevant) +# requirement on a retracted higher version of a dependency. +# However, when Go 1.16 reads the same requirements from the go.mod file, +# it does not prune out that requirement, and selects the retracted version. +# +# The Go 1.16 module graph looks like: +# +# m ---- lazy v0.1.0 ---- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible +# | | +# + -------+------------- incompatible v1.0.0 +# +# The Go 1.17 module graph is the same except that the dependencies of +# requireincompatible are pruned out (because the module that requires +# it — lazy v0.1.0 — specifies 'go 1.17', and it is not otherwise relevant to +# the main module). + +cp go.mod go.mod.orig + +go mod graph +cp stdout graph-1.17.txt +stdout '^example\.com/m example\.com/retract/incompatible@v1\.0\.0$' +stdout '^example\.net/lazy@v0\.1\.0 example\.com/retract/incompatible@v1\.0\.0$' +! stdout 'example\.com/retract/incompatible@v2\.0\.0\+incompatible' + +go mod graph -go=1.17 +cmp stdout graph-1.17.txt + +cmp go.mod go.mod.orig + + +# Setting -go=1.16 should report the graph as viewed by Go 1.16, +# but should not edit the go.mod file. + +go mod graph -go=1.16 +cp stdout graph-1.16.txt +stdout '^example\.com/m example\.com/retract/incompatible@v1\.0\.0$' +stdout '^example\.net/lazy@v0\.1\.0 example.com/retract/incompatible@v1\.0\.0$' +stdout '^example.net/requireincompatible@v0.1.0 example.com/retract/incompatible@v2\.0\.0\+incompatible$' + +cmp go.mod go.mod.orig + + +# If we actually update the go.mod file to the requested go version, +# we should get the same selected versions, but the roots of the graph +# may be updated. +# +# TODO(#45551): The roots should not be updated. + +go mod edit -go=1.16 +go mod graph +! stdout '^example\.com/m example\.com/retract/incompatible@v1\.0\.0$' +stdout '^example\.net/lazy@v0.1.0 example.com/retract/incompatible@v1\.0\.0$' +stdout '^example.net/requireincompatible@v0.1.0 example.com/retract/incompatible@v2\.0\.0\+incompatible$' + # TODO(#45551): cmp stdout graph-1.16.txt + + +# Unsupported go versions should be rejected, since we don't know +# what versions they would report. +! go mod graph -go=1.99999999999 +stderr '^invalid value "1\.99999999999" for flag -go: maximum supported Go version is '$goversion'\nusage: go mod graph \[-go=version\]\nRun ''go help mod graph'' for details.$' + + +-- go.mod -- +// Module m indirectly imports a package from +// example.com/retract/incompatible. Its selected version of +// that module is lower under Go 1.17 semantics than under Go 1.16. +module example.com/m + +go 1.17 + +replace ( + example.net/lazy v0.1.0 => ./lazy + example.net/requireincompatible v0.1.0 => ./requireincompatible +) + +require ( + example.com/retract/incompatible v1.0.0 // indirect + example.net/lazy v0.1.0 +) +-- lazy/go.mod -- +// Module lazy requires example.com/retract/incompatible v1.0.0. +// +// When viewed from the outside it also has a transitive dependency +// on v2.0.0+incompatible, but in lazy mode that transitive dependency +// is pruned out. +module example.net/lazy + +go 1.17 + +exclude example.com/retract/incompatible v2.0.0+incompatible + +require ( + example.com/retract/incompatible v1.0.0 + example.net/requireincompatible v0.1.0 +) +-- requireincompatible/go.mod -- +module example.net/requireincompatible + +go 1.15 + +require example.com/retract/incompatible v2.0.0+incompatible diff --git a/libgo/go/cmd/go/testdata/script/mod_import_cycle.txt b/libgo/go/cmd/go/testdata/script/mod_import_cycle.txt new file mode 100644 index 0000000..7be0749 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_import_cycle.txt @@ -0,0 +1,40 @@ +env GO111MODULE=on + +# 'go list all' should fail with a reasonable error message +! go list all +stderr '^package m\n\timports m/a\n\timports m/b\n\timports m/a: import cycle not allowed' + +# 'go list -e' should not print to stderr, but should mark all three +# packages (m, m/a, and m/b) as Incomplete. +go list -e -json all +! stderr . +stdout -count=3 '"Incomplete": true,' + +-- go.mod -- +module m + +require ( + m/a v0.0.0 + m/b v0.0.0 +) + +replace ( + m/a => ./a + m/b => ./b +) +-- m.go -- +package m +import ( + _ "m/a" + _ "m/b" +) +-- a/go.mod -- +module m/a +-- a/a.go -- +package a +import _ "m/b" +-- b/go.mod -- +module m/b +-- b/b.go -- +package b +import _ "m/a" diff --git a/libgo/go/cmd/go/testdata/script/mod_import_issue41113.txt b/libgo/go/cmd/go/testdata/script/mod_import_issue41113.txt new file mode 100644 index 0000000..fed2510 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_import_issue41113.txt @@ -0,0 +1,28 @@ +# Regression test for https://golang.org/issue/41113. +# +# When resolving a missing import path, the inability to add the package from +# one module path should not interfere with adding a nested path. + +# Initially, our module depends on split-incompatible v2.1.0-pre+incompatible, +# from which an imported package has been removed (and relocated to the nested +# split-incompatible/subpkg module). modload.QueryPattern will suggest +# split-incompatible v2.0.0+incompatible, which we cannot use (because it would +# be an implicit downgrade), and split-incompatible/subpkg v0.1.0, which we +# *should* use. + +go mod tidy + +go list -m all +stdout '^example.com/split-incompatible/subpkg v0\.1\.0$' +! stdout '^example.com/split-incompatible .*' + +-- go.mod -- +module golang.org/issue/41113 + +go 1.16 + +require example.com/split-incompatible v2.1.0-pre+incompatible +-- x.go -- +package issue41113 + +import _ "example.com/split-incompatible/subpkg" diff --git a/libgo/go/cmd/go/testdata/script/mod_import_issue42891.txt b/libgo/go/cmd/go/testdata/script/mod_import_issue42891.txt new file mode 100644 index 0000000..a78cab2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_import_issue42891.txt @@ -0,0 +1,14 @@ +# If an import declaration is an absolute path, most commands should report +# an error instead of going into an infinite loop. +# Verifies golang.org/issue/42891. +go list . +stdout '^m$' + +-- go.mod -- +module m + +go 1.16 +-- m.go -- +package m + +import "/" diff --git a/libgo/go/cmd/go/testdata/script/mod_import_meta.txt b/libgo/go/cmd/go/testdata/script/mod_import_meta.txt new file mode 100644 index 0000000..0e469d0 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_import_meta.txt @@ -0,0 +1,45 @@ +# The loader should not attempt to resolve imports of the "all", "std", and "cmd" meta-packages. + +! go list -deps ./importall +! stderr 'internal error' +stderr '^importall[/\\]x.go:3:8: "all" is not an importable package; see ''go help packages''$' + +! go list -deps ./importcmd +! stderr 'internal error' +stderr '^importcmd[/\\]x.go:3:8: "cmd" is not an importable package; see ''go help packages''$' + +! go list -deps ./importstd +! stderr 'internal error' +stderr '^importstd[/\\]x.go:3:8: "std" is not an importable package; see ''go help packages''$' + + +# Not even if such a path is theoretically provided by a (necessarily replaced) module. + +go mod edit -replace std@v0.1.0=./modstd +go mod edit -require std@v0.1.0 + +! go list -deps ./importstd +stderr '^importstd[/\\]x.go:3:8: "std" is not an importable package; see ''go help packages''$' + + +-- go.mod -- +module example.com +go 1.16 +-- importall/x.go -- +package importall + +import _ "all" +-- importcmd/x.go -- +package importcmd + +import _ "cmd" +-- importstd/x.go -- +package importstd + +import _ "std" +-- modstd/go.mod -- +module std +go 1.16 +-- modstd/std.go -- +// Package std is an incredibly confusingly-named package. +package std diff --git a/libgo/go/cmd/go/testdata/script/mod_indirect_nospace.txt b/libgo/go/cmd/go/testdata/script/mod_indirect_nospace.txt new file mode 100644 index 0000000..f4fb6a8 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_indirect_nospace.txt @@ -0,0 +1,32 @@ +# https://golang.org/issue/45932: "indirect" comments missing spaces +# should not be corrupted when the comment is removed. + +go mod tidy +cmp go.mod go.mod.direct + +-- go.mod -- +module example.net/m + +go 1.16 + +require example.net/x v0.1.0 //indirect + +replace example.net/x v0.1.0 => ./x +-- go.mod.direct -- +module example.net/m + +go 1.16 + +require example.net/x v0.1.0 + +replace example.net/x v0.1.0 => ./x +-- m.go -- +package m +import _ "example.net/x" + +-- x/go.mod -- +module example.net/x + +go 1.16 +-- x/x.go -- +package x diff --git a/libgo/go/cmd/go/testdata/script/mod_init_dep.txt b/libgo/go/cmd/go/testdata/script/mod_init_dep.txt index f8cf1d5..76b4867 100644 --- a/libgo/go/cmd/go/testdata/script/mod_init_dep.txt +++ b/libgo/go/cmd/go/testdata/script/mod_init_dep.txt @@ -1,10 +1,6 @@ env GO111MODULE=on env GOFLAGS=-mod=mod -# modconv uses git directly to examine what old 'go get' would -[!net] skip -[!exec:git] skip - # go mod init should populate go.mod from Gopkg.lock go mod init x stderr 'copying requirements from Gopkg.lock' diff --git a/libgo/go/cmd/go/testdata/script/mod_init_glide.txt b/libgo/go/cmd/go/testdata/script/mod_init_glide.txt index a351a6a..373810c 100644 --- a/libgo/go/cmd/go/testdata/script/mod_init_glide.txt +++ b/libgo/go/cmd/go/testdata/script/mod_init_glide.txt @@ -3,6 +3,7 @@ env GO111MODULE=on env GOPROXY=direct +env GOSUMDB= # Regression test for golang.org/issue/32161: # 'go mod init' did not locate tags when resolving a commit to a pseudo-version. diff --git a/libgo/go/cmd/go/testdata/script/mod_init_path.txt b/libgo/go/cmd/go/testdata/script/mod_init_path.txt index ccdfc92..e5fd4dd 100644 --- a/libgo/go/cmd/go/testdata/script/mod_init_path.txt +++ b/libgo/go/cmd/go/testdata/script/mod_init_path.txt @@ -1,7 +1,7 @@ env GO111MODULE=on ! go mod init . -stderr '^go: invalid module path "\.": is a local import path$' +stderr '^go: malformed module path ".": is a local import path$' cd x go mod init example.com/x diff --git a/libgo/go/cmd/go/testdata/script/mod_init_tidy.txt b/libgo/go/cmd/go/testdata/script/mod_init_tidy.txt new file mode 100644 index 0000000..4a52590 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_init_tidy.txt @@ -0,0 +1,30 @@ +# 'go mod init' should not recommend 'go mod tidy' in an empty directory +# (one that contains no non-hidden .go files or subdirectories). +cd empty +go mod init m +! stderr tidy +cd .. + +# 'go mod init' should recommend 'go mod tidy' if the directory has a .go file. +cd pkginroot +go mod init m +stderr '^go: to add module requirements and sums:\n\tgo mod tidy$' +cd .. + +# 'go mod init' should recommend 'go mod tidy' if the directory has a +# subdirectory. We don't walk the tree to see if it has .go files. +cd subdir +go mod init m +stderr '^go: to add module requirements and sums:\n\tgo mod tidy$' +cd .. + +-- empty/empty.txt -- +Not a .go file. Still counts as an empty project. +-- empty/.hidden/empty.go -- +File in hidden directory. Still as an empty project. +-- empty/_hidden/empty.go -- +File in hidden directory. Still as an empty project. +-- pkginroot/hello.go -- +package vendorimport +-- subdir/sub/empty.txt -- +Subdirectory doesn't need to contain a package. diff --git a/libgo/go/cmd/go/testdata/script/mod_install_hint.txt b/libgo/go/cmd/go/testdata/script/mod_install_hint.txt new file mode 100644 index 0000000..f2a5287 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_install_hint.txt @@ -0,0 +1,5 @@ +# Module is replaced but not required. No hint appears as no module is suggested. +go mod init m +go mod edit -replace=github.com/notrequired@v0.5.0=github.com/doesnotexist@v0.5.0 +! go install github.com/notrequired +! stderr 'to add it:'
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/mod_install_pkg_version.txt b/libgo/go/cmd/go/testdata/script/mod_install_pkg_version.txt new file mode 100644 index 0000000..367d34b --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_install_pkg_version.txt @@ -0,0 +1,203 @@ +# 'go install pkg@version' works outside a module. +env GO111MODULE=auto +go install example.com/cmd/a@v1.0.0 +exists $GOPATH/bin/a$GOEXE +rm $GOPATH/bin + + +# 'go install pkg@version' reports an error if modules are disabled. +env GO111MODULE=off +! go install example.com/cmd/a@v1.0.0 +stderr '^go: modules disabled by GO111MODULE=off; see ''go help modules''$' +env GO111MODULE=auto + + +# 'go install pkg@version' ignores go.mod in current directory. +cd m +cp go.mod go.mod.orig +! go list -m all +stderr '^go list -m: example.com/cmd@v1.1.0-doesnotexist: missing go.sum entry; to add it:\n\tgo mod download example.com/cmd$' +go install example.com/cmd/a@latest +cmp go.mod go.mod.orig +exists $GOPATH/bin/a$GOEXE +[!gccgo] go version -m $GOPATH/bin/a$GOEXE +[!gccgo] stdout '^\tmod\texample.com/cmd\tv1.0.0\t' # "latest", not from go.mod +rm $GOPATH/bin/a +cd .. + + +# 'go install -modfile=x.mod pkg@version' reports an error, but only if +# -modfile is specified explicitly on the command line. +cd m +env GOFLAGS=-modfile=go.mod +go install example.com/cmd/a@latest # same as above +env GOFLAGS= +! go install -modfile=go.mod example.com/cmd/a@latest +stderr '^go: -modfile cannot be used with commands that ignore the current module$' +cd .. + + +# Every test case requires linking, so we only cover the most important cases +# when -short is set. +[short] stop + + +# 'go install pkg@version' works on a module that doesn't have a go.mod file +# and with a module whose go.mod file has missing requirements. +# With a proxy, the two cases are indistinguishable. +go install rsc.io/fortune@v1.0.0 +stderr '^go: found rsc.io/quote in rsc.io/quote v1.5.2$' +exists $GOPATH/bin/fortune$GOEXE +! exists $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0/go.mod # no go.mod file +[!gccgo] go version -m $GOPATH/bin/fortune$GOEXE +[!gccgo] stdout '^\tdep\trsc.io/quote\tv1.5.2\t' # latest version of fortune's dependency +rm $GOPATH/bin + + +# 'go install dir@version' works like a normal 'go install' command if +# dir is a relative or absolute path. +env GO111MODULE=on +go mod download rsc.io/fortune@v1.0.0 +! go install $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0 +stderr '^go: go\.mod file not found in current directory or any parent directory; see ''go help modules''$' +! go install ../pkg/mod/rsc.io/fortune@v1.0.0 +stderr '^go: go\.mod file not found in current directory or any parent directory; see ''go help modules''$' +mkdir tmp +cd tmp +go mod init tmp +go mod edit -require=rsc.io/fortune@v1.0.0 +! go install -mod=readonly $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0 +stderr '^missing go\.sum entry for module providing package rsc\.io/fortune; to add:\n\tgo mod download rsc\.io/fortune$' +! go install -mod=readonly ../../pkg/mod/rsc.io/fortune@v1.0.0 +stderr '^missing go\.sum entry for module providing package rsc\.io/fortune; to add:\n\tgo mod download rsc\.io/fortune$' +go get -d rsc.io/fortune@v1.0.0 +go install -mod=readonly $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0 +exists $GOPATH/bin/fortune$GOEXE +cd .. +rm tmp +rm $GOPATH/bin +env GO111MODULE=auto + +# 'go install pkg@version' reports errors for meta packages, std packages, +# and directories. +! go install std@v1.0.0 +stderr '^go install: std@v1.0.0: argument must be a package path, not a meta-package$' +! go install fmt@v1.0.0 +stderr '^go install: fmt@v1.0.0: argument must not be a package in the standard library$' +! go install example.com//cmd/a@v1.0.0 +stderr '^go install: example.com//cmd/a@v1.0.0: argument must be a clean package path$' +! go install example.com/cmd/a@v1.0.0 ./x@v1.0.0 +stderr '^go install: ./x@v1.0.0: argument must be a package path, not a relative path$' +! go install example.com/cmd/a@v1.0.0 $GOPATH/src/x@v1.0.0 +stderr '^go install: '$WORK'[/\\]gopath/src/x@v1.0.0: argument must be a package path, not an absolute path$' +! go install example.com/cmd/a@v1.0.0 cmd/...@v1.0.0 +stderr '^package cmd/go not provided by module example.com/cmd@v1.0.0$' + +# 'go install pkg@version' should accept multiple arguments but report an error +# if the version suffixes are different, even if they refer to the same version. +go install example.com/cmd/a@v1.0.0 example.com/cmd/b@v1.0.0 +exists $GOPATH/bin/a$GOEXE +exists $GOPATH/bin/b$GOEXE +rm $GOPATH/bin + +env GO111MODULE=on +go list -m example.com/cmd@latest +stdout '^example.com/cmd v1.0.0$' +env GO111MODULE=auto + +! go install example.com/cmd/a@v1.0.0 example.com/cmd/b@latest +stderr '^go install: example.com/cmd/b@latest: all arguments must have the same version \(@v1.0.0\)$' + + +# 'go install pkg@version' should report an error if the arguments are in +# different modules. +! go install example.com/cmd/a@v1.0.0 rsc.io/fortune@v1.0.0 +stderr '^package rsc.io/fortune provided by module rsc.io/fortune@v1.0.0\n\tAll packages must be provided by the same module \(example.com/cmd@v1.0.0\).$' + + +# 'go install pkg@version' should report an error if an argument is not +# a main package. +! go install example.com/cmd/a@v1.0.0 example.com/cmd/err@v1.0.0 +stderr '^package example.com/cmd/err is not a main package$' + +# Wildcards should match only main packages. This module has a non-main package +# with an error, so we'll know if that gets built. +mkdir tmp +cd tmp +go mod init m +go get -d example.com/cmd@v1.0.0 +! go build example.com/cmd/... +stderr 'err[/\\]err.go:3:9: undefined: DoesNotCompile$' +cd .. + +go install example.com/cmd/...@v1.0.0 +exists $GOPATH/bin/a$GOEXE +exists $GOPATH/bin/b$GOEXE +rm $GOPATH/bin + +# If a wildcard matches no packages, we should see a warning. +! go install example.com/cmd/nomatch...@v1.0.0 +stderr '^go install: example.com/cmd/nomatch\.\.\.@v1.0.0: module example.com/cmd@v1.0.0 found, but does not contain packages matching example.com/cmd/nomatch\.\.\.$' +go install example.com/cmd/a@v1.0.0 example.com/cmd/nomatch...@v1.0.0 +stderr '^go: warning: "example.com/cmd/nomatch\.\.\." matched no packages$' + +# If a wildcard matches only non-main packges, we should see a different warning. +go install example.com/cmd/err...@v1.0.0 +stderr '^go: warning: "example.com/cmd/err\.\.\." matched only non-main packages$' + + +# 'go install pkg@version' should report errors if the module contains +# replace or exclude directives. +go mod download example.com/cmd@v1.0.0-replace +! go install example.com/cmd/a@v1.0.0-replace +cmp stderr replace-err + +go mod download example.com/cmd@v1.0.0-exclude +! go install example.com/cmd/a@v1.0.0-exclude +cmp stderr exclude-err + +# 'go install pkg@version' should report an error if the module requires a +# higher version of itself. +! go install example.com/cmd/a@v1.0.0-newerself +stderr '^go install: example.com/cmd/a@v1.0.0-newerself: version constraints conflict:\n\texample.com/cmd@v1.0.0-newerself requires example.com/cmd@v1.0.0, but example.com/cmd@v1.0.0-newerself is requested$' + + +# 'go install pkg@version' will only match a retracted version if it's +# explicitly requested. +env GO111MODULE=on +go list -m -versions example.com/cmd +! stdout v1.9.0 +go list -m -versions -retracted example.com/cmd +stdout v1.9.0 +go install example.com/cmd/a@latest +[!gccgo] go version -m $GOPATH/bin/a$GOEXE +[!gccgo] stdout '^\tmod\texample.com/cmd\tv1.0.0\t' +go install example.com/cmd/a@v1.9.0 +[!gccgo] go version -m $GOPATH/bin/a$GOEXE +[!gccgo] stdout '^\tmod\texample.com/cmd\tv1.9.0\t' +env GO111MODULE= + +# 'go install pkg@version' succeeds when -mod=readonly is set explicitly. +# Verifies #43278. +go install -mod=readonly example.com/cmd/a@v1.0.0 + +-- m/go.mod -- +module m + +go 1.16 + +require example.com/cmd v1.1.0-doesnotexist +-- x/x.go -- +package main + +func main() {} +-- replace-err -- +go install: example.com/cmd/a@v1.0.0-replace (in example.com/cmd@v1.0.0-replace): + The go.mod file for the module providing named packages contains one or + more replace directives. It must not contain directives that would cause + it to be interpreted differently than if it were the main module. +-- exclude-err -- +go install: example.com/cmd/a@v1.0.0-exclude (in example.com/cmd@v1.0.0-exclude): + The go.mod file for the module providing named packages contains one or + more exclude directives. It must not contain directives that would cause + it to be interpreted differently than if it were the main module. diff --git a/libgo/go/cmd/go/testdata/script/mod_invalid_path.txt b/libgo/go/cmd/go/testdata/script/mod_invalid_path.txt new file mode 100644 index 0000000..333a3ff --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_invalid_path.txt @@ -0,0 +1,61 @@ +# Test that mod files with invalid or missing paths produce an error. + +# Test that go list fails on a go.mod with no module declaration. +cd $WORK/gopath/src/mod +! go list . +stderr '^go: no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod$' + +# Test that go mod init in GOPATH doesn't add a module declaration +# with a path that can't possibly be a module path, because +# it isn't even a valid import path. +# The single quote and backtick are the only characters which are not allowed +# but are a valid Windows file name. +cd $WORK/'gopath/src/m''d' +! go mod init +stderr 'cannot determine module path' + +# Test that a go.mod file is rejected when its module declaration has a path that can't +# possibly be a module path, because it isn't even a valid import path +cd $WORK/gopath/src/badname +! go list . +stderr 'malformed module path' + +# Test that an import path containing an element with a leading dot is valid, +# but such a module path is not. +# Verifies #43985. +cd $WORK/gopath/src/dotname +go list ./.dot +stdout '^example.com/dotname/.dot$' +go list ./use +stdout '^example.com/dotname/use$' +! go list -m example.com/dotname/.dot@latest +stderr '^go list -m: example.com/dotname/.dot@latest: malformed module path "example.com/dotname/.dot": leading dot in path element$' +go get -d example.com/dotname/.dot +go get -d example.com/dotname/use +go mod tidy + +-- mod/go.mod -- + +-- mod/foo.go -- +package foo + +-- m'd/foo.go -- +package mad + +-- badname/go.mod -- + +module .\. + +-- badname/foo.go -- +package badname + +-- dotname/go.mod -- +module example.com/dotname + +go 1.16 +-- dotname/.dot/dot.go -- +package dot +-- dotname/use/use.go -- +package use + +import _ "example.com/dotname/.dot" diff --git a/libgo/go/cmd/go/testdata/script/mod_invalid_path_dotname.txt b/libgo/go/cmd/go/testdata/script/mod_invalid_path_dotname.txt new file mode 100644 index 0000000..8593433 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_invalid_path_dotname.txt @@ -0,0 +1,46 @@ +# Test that an import path containing an element with a leading dot +# in another module is valid. + +# 'go get' works with no version query. +cp go.mod.empty go.mod +go get -d example.com/dotname/.dot +go list -m example.com/dotname +stdout '^example.com/dotname v1.0.0$' + +# 'go get' works with a version query. +cp go.mod.empty go.mod +go get -d example.com/dotname/.dot@latest +go list -m example.com/dotname +stdout '^example.com/dotname v1.0.0$' + +# 'go get' works on an importing package. +cp go.mod.empty go.mod +go get -d . +go list -m example.com/dotname +stdout '^example.com/dotname v1.0.0$' + +# 'go list' works on the dotted package. +go list example.com/dotname/.dot +stdout '^example.com/dotname/.dot$' + +# 'go list' works on an importing package. +go list . +stdout '^m$' + +# 'go mod tidy' works. +cp go.mod.empty go.mod +go mod tidy +go list -m example.com/dotname +stdout '^example.com/dotname v1.0.0$' + +-- go.mod.empty -- +module m + +go 1.16 +-- go.sum -- +example.com/dotname v1.0.0 h1:Q0JMAn464CnwFVCshs1n4+f5EFiW/eRhnx/fTWjw2Ag= +example.com/dotname v1.0.0/go.mod h1:7K4VLT7QylRI8H7yZwUkeDH2s19wQnyfp/3oBlItWJ0= +-- use.go -- +package use + +import _ "example.com/dotname/.dot" diff --git a/libgo/go/cmd/go/testdata/script/mod_invalid_path_plus.txt b/libgo/go/cmd/go/testdata/script/mod_invalid_path_plus.txt new file mode 100644 index 0000000..51dbf93 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_invalid_path_plus.txt @@ -0,0 +1,36 @@ +# https://golang.org/issue/44776 +# The '+' character should be disallowed in module paths, but allowed in package +# paths within valid modules. + +# 'go list' accepts package paths with pluses. +cp go.mod.orig go.mod +go get -d example.net/cmd +go list example.net/cmd/x++ + +# 'go list -m' rejects module paths with pluses. +! go list -versions -m 'example.net/bad++' +stderr '^go list -m: malformed module path "example.net/bad\+\+": invalid char ''\+''$' + +# 'go get' accepts package paths with pluses. +cp go.mod.orig go.mod +go get -d example.net/cmd/x++ +go list -m example.net/cmd +stdout '^example.net/cmd v0.0.0-00010101000000-000000000000 => ./cmd$' + +-- go.mod.orig -- +module example.com/m + +go 1.16 + +replace ( + example.net/cmd => ./cmd +) + +-- cmd/go.mod -- +module example.net/cmd + +go 1.16 +-- cmd/x++/main.go -- +package main + +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/mod_invalid_version.txt b/libgo/go/cmd/go/testdata/script/mod_invalid_version.txt index 43b9564..6846a79 100644 --- a/libgo/go/cmd/go/testdata/script/mod_invalid_version.txt +++ b/libgo/go/cmd/go/testdata/script/mod_invalid_version.txt @@ -19,7 +19,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 \(replaced by \./\..\): parsing ../go.mod: '$WORK'/gopath/src/go.mod:5: require golang.org/x/text: version "14c0d48ead0c" invalid: must be of the form v1.2.3' +stderr 'go list -m: example.com@v0.0.0 \(replaced by \./\.\.\): parsing ..[/\\]go.mod: '$WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "14c0d48ead0c" invalid: must be of the form v1.2.3' cd .. go list -m golang.org/x/text stdout 'golang.org/x/text v0.1.1-0.20170915032832-14c0d48ead0c' @@ -30,7 +30,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c: invalid version: missing golang.org/x/text/unicode/go.mod at revision 14c0d48ead0c' +stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c: invalid version: missing golang.org/x/text/unicode/go.mod at revision 14c0d48ead0c' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text/unicode@v0.0.0-20170915032832-14c0d48ead0c: invalid version: missing golang.org/x/text/unicode/go.mod at revision 14c0d48ead0c' @@ -47,17 +47,17 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v2.1.1-0.20170915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 \(replaced by \./\.\.\): parsing ../go.mod: '$WORK'/gopath/src/go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2' +stderr 'go list -m: example.com@v0.0.0 \(replaced by \./\.\.\): parsing ..[/\\]go.mod: '$WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2' cd .. ! go list -m golang.org/x/text -stderr $WORK'/gopath/src/go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2' +stderr $WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2' # A pseudo-version with fewer than 12 digits of SHA-1 prefix is invalid. cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0 cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(14c0d48ead0c\)' +stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(14c0d48ead0c\)' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0: invalid pseudo-version: revision is shorter than canonical \(14c0d48ead0c\)' @@ -67,7 +67,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(14c0d48ead0c\)' +stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(14c0d48ead0c\)' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0cd47e3104ada247d91be04afc7a5a: invalid pseudo-version: revision is longer than canonical \(14c0d48ead0c\)' @@ -77,7 +77,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)' +stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)' @@ -87,7 +87,7 @@ stderr 'golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-v go mod edit -replace golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c=golang.org/x/text@14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)' +stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)' cd .. go list -m golang.org/x/text stdout 'golang.org/x/text v0.1.1-0.20190915032832-14c0d48ead0c => golang.org/x/text v0.1.1-0.20170915032832-14c0d48ead0c' @@ -97,7 +97,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v1.999.999-0.20170915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.999.999-0.20170915032832-14c0d48ead0c: invalid pseudo-version: preceding tag \(v1.999.998\) not found' +stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.999.999-0.20170915032832-14c0d48ead0c: invalid pseudo-version: preceding tag \(v1.999.998\) not found' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v1.999.999-0.20170915032832-14c0d48ead0c: invalid pseudo-version: preceding tag \(v1.999.998\) not found' @@ -109,7 +109,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v1.0.0-20170915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.0.0-20170915032832-14c0d48ead0c: invalid pseudo-version: major version without preceding tag must be v0, not v1' +stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.0.0-20170915032832-14c0d48ead0c: invalid pseudo-version: major version without preceding tag must be v0, not v1' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v1.0.0-20170915032832-14c0d48ead0c: invalid pseudo-version: major version without preceding tag must be v0, not v1' @@ -120,7 +120,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number' +stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number' @@ -130,7 +130,7 @@ stderr 'golang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-v go mod edit -replace golang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c=golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number' +stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.0.0-0.20170915032832-14c0d48ead0c: invalid pseudo-version: version before v0.0.0 would have negative patch number' cd .. go list -m golang.org/x/text stdout 'golang.org/x/text v0.0.0-0.20170915032832-14c0d48ead0c => golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c' @@ -153,7 +153,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c: invalid pseudo-version: revision 14c0d48ead0c is not a descendent of preceding tag \(v0.2.0\)' +stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c: invalid pseudo-version: revision 14c0d48ead0c is not a descendent of preceding tag \(v0.2.0\)' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c: invalid pseudo-version: revision 14c0d48ead0c is not a descendent of preceding tag \(v0.2.0\)' @@ -163,7 +163,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac: invalid pseudo-version: tag \(v0.2.0\) found on revision c4d099d611ac is already canonical, so should not be replaced with a pseudo-version derived from that tag' +stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac: invalid pseudo-version: tag \(v0.2.0\) found on revision c4d099d611ac is already canonical, so should not be replaced with a pseudo-version derived from that tag' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac: invalid pseudo-version: tag \(v0.2.0\) found on revision c4d099d611ac is already canonical, so should not be replaced with a pseudo-version derived from that tag' @@ -173,7 +173,7 @@ cp go.mod.orig go.mod go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c+incompatible cd outside ! go list -m golang.org/x/text -stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c\+incompatible: invalid version: \+incompatible suffix not allowed: major version v0 is compatible' +stderr 'go list -m: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c\+incompatible: invalid version: \+incompatible suffix not allowed: major version v0 is compatible' cd .. ! go list -m golang.org/x/text stderr 'golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c\+incompatible: invalid version: \+incompatible suffix not allowed: major version v0 is compatible' @@ -194,7 +194,7 @@ cp go.mod.orig go.mod go mod edit -require github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d+incompatible cd outside ! go list -m github.com/pierrec/lz4 -stderr 'go: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required' +stderr 'go list -m: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required' cd .. ! go list -m github.com/pierrec/lz4 stderr 'github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required' diff --git a/libgo/go/cmd/go/testdata/script/mod_lazy_consistency.txt b/libgo/go/cmd/go/testdata/script/mod_lazy_consistency.txt new file mode 100644 index 0000000..1bf3e31 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_lazy_consistency.txt @@ -0,0 +1,95 @@ +# If the root requirements in a lazy module are inconsistent +# (for example, due to a bad hand-edit or git merge), +# they can go unnoticed as long as the module with the violated +# requirement is not used. +# When we load a package from that module, we should spot-check its +# requirements and either emit an error or update the go.mod file. + +cp go.mod go.mod.orig + + +# If we load package x from x.1, we only check the requirements of x, +# which are fine: loading succeeds. + +go list -deps ./usex +stdout '^example.net/x$' +cmp go.mod go.mod.orig + + +# However, if we load needx2, we should load the requirements of needx2. +# Those requirements indicate x.2, not x.1, so the module graph is +# inconsistent and needs to be fixed. + +! go list -deps ./useneedx2 +stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy$' + +! go list -deps example.net/needx2 +stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy$' + + +# The command printed in the error message should fix the problem. + +go mod tidy +go list -deps ./useneedx2 +stdout '^example.net/m/useneedx2$' +stdout '^example.net/needx2$' +stdout '^example.net/x$' + +go list -m all +stdout '^example.net/needx2 v0\.1\.0 ' +stdout '^example.net/x v0\.2\.0 ' + + +-- go.mod -- +module example.net/m + +go 1.17 + +require ( + example.net/needx2 v0.1.0 + example.net/x v0.1.0 +) + +replace ( + example.net/needx2 v0.1.0 => ./needx2.1 + example.net/x v0.1.0 => ./x.1 + example.net/x v0.2.0 => ./x.2 +) +-- useneedx2/useneedx2.go -- +package useneedx2 + +import _ "example.net/needx2" +-- usex/usex.go -- +package usex + +import _ "example.net/x" + +-- x.1/go.mod -- +module example.com/x + +go 1.17 +-- x.1/x.go -- +package x + +-- x.2/go.mod -- +module example.com/x + +go 1.17 +-- x.2/x.go -- +package x + +const AddedInV2 = true + +-- needx2.1/go.mod -- +module example.com/x + +go 1.17 + +require example.net/x v0.2.0 +-- needx2.1/needx2.go -- +// Package needx2 needs x v0.2.0 or higher. +package needx2 + +import "example.net/x" + +var _ = x.AddedInV2 diff --git a/libgo/go/cmd/go/testdata/script/mod_lazy_downgrade.txt b/libgo/go/cmd/go/testdata/script/mod_lazy_downgrade.txt new file mode 100644 index 0000000..2f815fe --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_lazy_downgrade.txt @@ -0,0 +1,183 @@ +# This test illustrates the interaction between lazy loading and downgrading in +# 'go get'. + +# The package import graph used in this test looks like: +# +# lazy ---- a +# | +# a_test ---- b +# b_test ---- c +# +# The module dependency graph initially looks like: +# +# lazy ---- a.1 ---- b.1 ---- c.1 +# \ / +# b.3 ---- c.2 b.2 +# +# (Note that lazy loading will prune out the dependency from b.1 on c.1.) + +cp go.mod go.mod.orig +go mod tidy +cmp go.mod.orig go.mod + +go list -m all +stdout '^example.com/a v0.1.0 ' +stdout '^example.com/b v0.3.0 ' +stdout '^example.com/c v0.2.0 ' + +# Downgrading c should also downgrade the b that requires it. + +go get -d example.com/c@v0.1.0 +go list -m all +stdout '^example.com/a v0.1.0 ' +stdout '^example.com/b v0.2.0 ' +stdout '^example.com/c v0.1.0 ' + +# Removing c entirely should also remove the a and b that require it. + +go get -d example.com/c@none +go list -m all +! stdout '^example.com/a ' +! stdout '^example.com/b ' +! stdout '^example.com/c ' + + +# With lazy loading, downgrading c should work the same way, but dependencies +# outside of the deepening scan should not affect the downgrade. + +cp go.mod.orig go.mod +go mod edit -go=1.17 + +go list -m all +stdout '^example.com/a v0.1.0 ' +stdout '^example.com/b v0.3.0 ' +stdout '^example.com/c v0.2.0 ' + +go get -d example.com/c@v0.1.0 +go list -m all +stdout '^example.com/a v0.1.0 ' +stdout '^example.com/b v0.2.0 ' +stdout '^example.com/c v0.1.0 ' + +# At this point, b.2 is still an explicit root, so its dependency on c +# is still tracked, and it will still be downgraded away if we remove c. +# ('go get' never makes a root into a non-root. Only 'go mod tidy' does that.) + +go get -d example.com/c@none +go list -m all +! stdout '^example.com/a ' +! stdout '^example.com/b ' +! stdout '^example.com/c ' + + +# This time, we drop the explicit 'b' root by downgrading it to v0.1.0 +# (the version required by a.1) and running 'go mod tidy'. +# It is still selected at v0.1.0 (as a dependency of a), +# but its dependency on c is now pruned from the module graph, so it doesn't +# result in any downgrades to b or a if we run 'go get c@none'. + +cp go.mod.orig go.mod +go mod edit -go=1.17 + +go list -m all +stdout '^example.com/a v0.1.0 ' +stdout '^example.com/b v0.3.0 ' +stdout '^example.com/c v0.2.0 ' + +go get -d example.com/c@v0.1.0 example.com/b@v0.1.0 +go list -m all +stdout '^example.com/a v0.1.0 ' +stdout '^example.com/b v0.1.0 ' +stdout '^example.com/c v0.1.0 ' + +go mod tidy +go list -m all +stdout '^example.com/a v0.1.0 ' +stdout '^example.com/b v0.1.0 ' +! stdout '^example.com/c ' + +go get -d example.com/c@none +go list -m all +stdout '^example.com/a v0.1.0' +stdout '^example.com/b v0.1.0' +! stdout '^example.com/c ' + + +-- go.mod -- +module example.com/lazy + +go 1.15 + +require ( + example.com/a v0.1.0 + example.com/b v0.3.0 // indirect +) + +replace ( + example.com/a v0.1.0 => ./a + example.com/b v0.1.0 => ./b1 + example.com/b v0.2.0 => ./b2 + example.com/b v0.3.0 => ./b3 + example.com/c v0.1.0 => ./c + example.com/c v0.2.0 => ./c +) +-- lazy.go -- +package lazy + +import _ "example.com/a" + +-- a/go.mod -- +module example.com/a + +go 1.17 + +require example.com/b v0.1.0 +-- a/a.go -- +package a +-- a/a_test.go -- +package a_test + +import _ "example.com/b" + +-- b1/go.mod -- +module example.com/b + +go 1.17 + +require example.com/c v0.1.0 +-- b1/b.go -- +package b +-- b1/b_test.go -- +package b_test +import _ "example.com/c" + +-- b2/go.mod -- +module example.com/b + +go 1.17 + +require example.com/c v0.1.0 +-- b2/b.go -- +package b +-- b2/b_test.go -- +package b_test +import _ "example.com/c" + +-- b3/go.mod -- +module example.com/b + +go 1.17 + +require example.com/c v0.2.0 +-- b3/b.go -- +package b +-- b3/b_test.go -- +package b_test +import _ "example.com/c" + +-- c/go.mod -- +module example.com/c + +go 1.17 +-- c/c.go -- +package c diff --git a/libgo/go/cmd/go/testdata/script/mod_lazy_import_allmod.txt b/libgo/go/cmd/go/testdata/script/mod_lazy_import_allmod.txt new file mode 100644 index 0000000..97718c4 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_lazy_import_allmod.txt @@ -0,0 +1,191 @@ +# This test demonstrates dependency resolution when the main module imports a +# new package from a previously-test-only dependency. +# +# When lazy loading is active, the loader will not load dependencies of any +# module whose packages are *only* imported by tests outside the main module. If +# the main module is changed to import a package from such a module, the +# dependencies of that module will need to be reloaded. + +# The import graph used in this test looks like: +# +# m ---- a +# \ | +# \ a_test ---- b/x +# \ +# --------------b/y (new) ---- c +# +# Where b/x and b/y are disjoint packages, but both contained in module b. +# +# The module dependency graph initially looks like: +# +# m ---- a.1 ---- b.1 ---- c.1 +# +# This configuration is similar to that used in mod_lazy_new_import, +# but the new import is from what is initially a test-only dependency. + +# Control case: in Go 1.14, the original go.mod is tidy, +# and the dependency on c is eagerly loaded. + +cp go.mod go.mod.orig +go mod tidy +cmp go.mod.orig go.mod + +go list -m all +stdout '^a v0.1.0 ' +stdout '^b v0.1.0 ' +stdout '^c v0.1.0 ' + +# After adding a new import of b/y, +# the import of c from b/y should resolve to the version required by b. + +cp m.go m.go.orig +cp m.go.new m.go +go mod tidy +cmp go.mod.new go.mod + +go list -m all +stdout '^a v0.1.0 ' +stdout '^b v0.1.0 ' +stdout '^c v0.1.0 ' + +# With lazy loading, the go.mod requirements are the same, +# but the dependency on c is initially pruned out. + +cp m.go.orig m.go +cp go.mod.orig go.mod +go mod edit -go=1.17 +go mod edit -go=1.17 go.mod.new + +cp go.mod go.mod.orig +go mod tidy +cmp go.mod.orig go.mod + +go list -m all +stdout '^a v0.1.0 ' +stdout '^b v0.1.0 ' +! stdout '^c ' + +# After adding a new direct import of b/y, +# the existing verison of b should be promoted to a root, +# bringing the version of c required by b into the build list. + +cp m.go.new m.go +go mod tidy +cmp go.mod.lazy go.mod + +go list -m all +stdout '^a v0.1.0 ' +stdout '^b v0.1.0 ' +stdout '^c v0.1.0 ' + +-- m.go -- +package main + +import ( + "fmt" + + _ "a" // a_test imports b/x. +) + +func main() { +} +-- m.go.new -- +package main + +import ( + "fmt" + + _ "a" // a_test imports b/x. + "b/y" // This is a new import, not yet reflected in the go.mod file. +) + +func main() { + fmt.Println(b.CVersion()) +} +-- go.mod -- +module m + +go 1.14 + +require a v0.1.0 + +replace ( + a v0.1.0 => ./a1 + b v0.1.0 => ./b1 + c v0.1.0 => ./c1 + c v0.2.0 => ./c2 +) +-- go.mod.new -- +module m + +go 1.14 + +require ( + a v0.1.0 + b v0.1.0 +) + +replace ( + a v0.1.0 => ./a1 + b v0.1.0 => ./b1 + c v0.1.0 => ./c1 + c v0.2.0 => ./c2 +) +-- go.mod.lazy -- +module m + +go 1.17 + +require ( + a v0.1.0 + b v0.1.0 +) + +require c v0.1.0 // indirect + +replace ( + a v0.1.0 => ./a1 + b v0.1.0 => ./b1 + c v0.1.0 => ./c1 + c v0.2.0 => ./c2 +) +-- a1/go.mod -- +module a + +go 1.17 + +require b v0.1.0 +-- a1/a.go -- +package a +-- a1/a_test.go -- +package a_test + +import _ "b/x" +-- b1/go.mod -- +module b + +go 1.17 + +require c v0.1.0 +-- b1/x/x.go -- +package x +-- b1/y/y.go -- +package y + +import "c" + +func CVersion() string { + return c.Version +} +-- c1/go.mod -- +module c + +go 1.17 +-- c1/c.go -- +package c + +const Version = "v0.1.0" +-- c2/go.mod -- +This file should be unused. +-- c2/c.go -- +This file should be unused. diff --git a/libgo/go/cmd/go/testdata/script/mod_lazy_new_import.txt b/libgo/go/cmd/go/testdata/script/mod_lazy_new_import.txt new file mode 100644 index 0000000..4272a52 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_lazy_new_import.txt @@ -0,0 +1,155 @@ +# This test illustrates the use of a deepening scan to resolve transitive +# imports of imports of new packages from within existing dependencies. + +# The package import graph used in this test looks like: +# +# lazy ---- a/x ---- b +# \ +# ---- a/y (new) ---- c +# +# Where a/x and x/y are disjoint packages, but both contained in module a. +# +# The module dependency graph initially looks like: +# +# lazy ---- a.1 ---- b.1 +# \ +# c.1 + + +cp go.mod go.mod.old +cp lazy.go lazy.go.old +go mod tidy +cmp go.mod go.mod.old + +# Before adding a new import, the go.mod file should +# enumerate modules for all packages already imported. +go list all +cmp go.mod go.mod.old + +# When we add a new import of a package in an existing dependency, +# and that dependency is already tidy, its transitive dependencies +# should already be present. +cp lazy.go.new lazy.go +go list all +go list -m all +stdout '^example.com/c v0.1.0' # not v0.2.0 as would be resolved by 'latest' +cmp go.mod go.mod.old + +# Now, we repeat the test with a lazy main module. +cp lazy.go.old lazy.go +cp go.mod.117 go.mod + +# Before adding a new import, the go.mod file should +# enumerate modules for all packages already imported. +go list all +cmp go.mod go.mod.117 + +# When a new import is found, we should perform a deepening scan of the existing +# dependencies and add a requirement on the version required by those +# dependencies — not re-resolve 'latest'. +cp lazy.go.new lazy.go + +! go list all +stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy$' + +go mod tidy +go list all +go list -m all +stdout '^example.com/c v0.1.0' # not v0.2.0 as would be resolved by 'latest' + +cmp go.mod go.mod.new + + +-- go.mod -- +module example.com/lazy + +go 1.15 + +require example.com/a v0.1.0 + +replace ( + example.com/a v0.1.0 => ./a + example.com/b v0.1.0 => ./b + example.com/c v0.1.0 => ./c1 + example.com/c v0.2.0 => ./c2 +) +-- go.mod.117 -- +module example.com/lazy + +go 1.17 + +require example.com/a v0.1.0 + +require example.com/b v0.1.0 // indirect + +replace ( + example.com/a v0.1.0 => ./a + example.com/b v0.1.0 => ./b + example.com/c v0.1.0 => ./c1 + example.com/c v0.2.0 => ./c2 +) +-- go.mod.new -- +module example.com/lazy + +go 1.17 + +require example.com/a v0.1.0 + +require ( + example.com/b v0.1.0 // indirect + example.com/c v0.1.0 // indirect +) + +replace ( + example.com/a v0.1.0 => ./a + example.com/b v0.1.0 => ./b + example.com/c v0.1.0 => ./c1 + example.com/c v0.2.0 => ./c2 +) +-- lazy.go -- +package lazy + +import ( + _ "example.com/a/x" +) +-- lazy.go.new -- +package lazy + +import ( + _ "example.com/a/x" + _ "example.com/a/y" +) +-- a/go.mod -- +module example.com/a + +go 1.15 + +require ( + example.com/b v0.1.0 + example.com/c v0.1.0 +) +-- a/x/x.go -- +package x +import _ "example.com/b" +-- a/y/y.go -- +package y +import _ "example.com/c" +-- b/go.mod -- +module example.com/b + +go 1.15 +-- b/b.go -- +package b +-- c1/go.mod -- +module example.com/c + +go 1.15 +-- c1/c.go -- +package c +-- c2/go.mod -- +module example.com/c + +go 1.15 +-- c2/c.go -- +package c +This file should not be used, so this syntax error should be ignored. diff --git a/libgo/go/cmd/go/testdata/script/mod_lazy_test_horizon.txt b/libgo/go/cmd/go/testdata/script/mod_lazy_test_horizon.txt new file mode 100644 index 0000000..7d07eb6 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_lazy_test_horizon.txt @@ -0,0 +1,131 @@ +# This file demonstrates the effect of lazy loading on the selected +# versions of test dependencies. + +# The package import graph used in this test looks like: +# +# m ---- a +# \ | +# \ a_test ---- b +# \ | +# x b_test +# | \ +# x_test -------------- c +# +# And the module dependency graph looks like: +# +# m -- a.1 -- b.1 -- c.2 +# \ +# x.1 ------------ c.1 + +# Control case: in Go 1.15, the version of c imported by 'go test x' is the +# version required by module b, even though b_test is not relevant to the main +# module. (The main module imports a, and a_test imports b, but all of the +# packages and tests in the main module can be built without b.) + +go list -m c +stdout '^c v0.2.0 ' + +[!short] go test -v x +[!short] stdout ' c v0.2.0$' + +# With lazy loading, the go.mod requirements are the same, +# but the irrelevant dependency on c v0.2.0 should be pruned out, +# leaving only the relevant dependency on c v0.1.0. + +go mod edit -go=1.17 +go list -m c +stdout '^c v0.1.0' + +[!short] go test -v x +[!short] stdout ' c v0.1.0$' + +-- m.go -- +package m + +import ( + _ "a" + _ "x" +) +-- go.mod -- +module m + +go 1.15 + +require ( + a v0.1.0 + x v0.1.0 +) + +replace ( + a v0.1.0 => ./a1 + b v0.1.0 => ./b1 + c v0.1.0 => ./c1 + c v0.2.0 => ./c2 + x v0.1.0 => ./x1 +) +-- a1/go.mod -- +module a + +go 1.17 + +require b v0.1.0 +-- a1/a.go -- +package a +-- a1/a_test.go -- +package a_test + +import _ "b" +-- b1/go.mod -- +module b + +go 1.17 + +require c v0.2.0 +-- b1/b.go -- +package b +-- b1/b_test.go -- +package b_test + +import ( + "c" + "testing" +) + +func TestCVersion(t *testing.T) { + t.Log(c.Version) +} +-- c1/go.mod -- +module c + +go 1.17 +-- c1/c.go -- +package c + +const Version = "v0.1.0" +-- c2/go.mod -- +module c + +go 1.17 +-- c2/c.go -- +package c + +const Version = "v0.2.0" +-- x1/go.mod -- +module x + +go 1.17 + +require c v0.1.0 +-- x1/x.go -- +package x +-- x1/x_test.go -- +package x_test + +import ( + "c" + "testing" +) + +func TestCVersion(t *testing.T) { + t.Log("c", c.Version) +} diff --git a/libgo/go/cmd/go/testdata/script/mod_lazy_test_of_test_dep.txt b/libgo/go/cmd/go/testdata/script/mod_lazy_test_of_test_dep.txt new file mode 100644 index 0000000..68a5b6d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_lazy_test_of_test_dep.txt @@ -0,0 +1,224 @@ +# This file demonstrates the effect of lazy loading on the reproducibility of +# tests (and tests of test dependencies) outside the main module. +# +# It is similar to the cases in mod_all.txt and mod_lazy_test_horizon.txt, but +# focuses on the effect of "go test" on specific packages instead of the "all" +# pattern. + +# The package import graph used in this test looks like: +# +# lazy ---- a +# | +# a_test ---- b +# | +# b_test ---- c +# +# And the non-lazy module dependency graph looks like: +# +# lazy ---- a.1 ---- b.1 ---- c.1 + +cp go.mod go.mod.old +go mod tidy +cmp go.mod go.mod.old + + +# In Go 1.15 mode, 'go list -m all' includes modules needed by the +# transitive closure of tests of dependencies of tests of dependencies of …. + +go list -m all +stdout '^example.com/b v0.1.0 ' +stdout '^example.com/c v0.1.0 ' +cmp go.mod go.mod.old + +# 'go test' (or equivalent) of any such dependency, no matter how remote, does +# not update the go.mod file. + +go list -test -deps example.com/a +stdout example.com/b +! stdout example.com/c + +[!short] go test -c -o $devnull example.com/a +[!short] cmp go.mod go.mod.old + +go list -test -deps example.com/b +stdout example.com/c + +[!short] go test -c -o $devnull example.com/b +[!short] cmp go.mod go.mod.old + +go mod edit -go=1.17 a/go.mod +go mod edit -go=1.17 b1/go.mod +go mod edit -go=1.17 b2/go.mod +go mod edit -go=1.17 c1/go.mod +go mod edit -go=1.17 c2/go.mod +go mod edit -go=1.17 + + +# After changing to 'go 1.17` uniformly, 'go list -m all' should prune out +# example.com/c, because it is not imported by any package (or test of a package) +# transitively imported by the main module. +# +# example.com/a is imported, +# and example.com/b is needed in order to run 'go test example.com/a', +# but example.com/c is not needed because we don't expect the user to need to run +# 'go test example.com/b'. + +# If we skip directly to adding a new import of c, the dependency is too far +# away for a deepening scan to find, which is fine because the package whose +# test imported it wasn't even it "all". It should resolve from the latest +# version of its module. + +# However, if we reach c by running successive tests starting from the main +# module, we should end up with exactly the version required by b, with an update +# to the go.mod file as soon as we test a test dependency that is not itself in +# "all". + +cp go.mod go.mod.117 +go mod tidy +cmp go.mod go.mod.117 + +go list -m all +stdout '^example.com/b v0.1.0 ' +! stdout '^example.com/c ' + +# 'go test' of a package (transitively) imported by the main module +# should work without changes to the go.mod file. + +go list -test -deps example.com/a +stdout example.com/b +! stdout example.com/c + +[!short] go test -c -o $devnull example.com/a + +# However, 'go test' of a package that is itself a dependency should require an +# update to the go.mod file. +! go list -test -deps example.com/b + + # TODO(#36460): The hint here is wrong. We should suggest + # 'go get -t example.com/b@v0.1.0' instead of 'go mod tidy'. +stderr '^go: updates to go\.mod needed; to update it:\n\tgo mod tidy$' + +[!short] ! go test -c -o $devnull example.com/b +[!short] stderr '^go: updates to go\.mod needed; to update it:\n\tgo mod tidy$' + +go get -t example.com/b@v0.1.0 +go list -test -deps example.com/b +stdout example.com/c + +[!short] go test -c -o $devnull example.com/b + +# The update should bring the version required by b, not the latest version of c. + +go list -m example.com/c +stdout '^example.com/c v0.1.0 ' + +cmp go.mod go.mod.b + + +# We should reach the same state if we arrive at it via `go test -mod=mod`. + +cp go.mod.117 go.mod + +[short] go list -mod=mod -test -deps example.com/a +[!short] go test -mod=mod -c -o $devnull example.com/a + +[short] go list -mod=mod -test -deps example.com/b +[!short] go test -mod=mod -c -o $devnull example.com/b + +cmp go.mod go.mod.b + + + +-- go.mod -- +module example.com/lazy + +go 1.15 + +require example.com/a v0.1.0 + +replace ( + example.com/a v0.1.0 => ./a + example.com/b v0.1.0 => ./b1 + example.com/b v0.2.0 => ./b2 + example.com/c v0.1.0 => ./c1 + example.com/c v0.2.0 => ./c2 +) +-- go.mod.b -- +module example.com/lazy + +go 1.17 + +require example.com/a v0.1.0 + +require example.com/b v0.1.0 // indirect + +replace ( + example.com/a v0.1.0 => ./a + example.com/b v0.1.0 => ./b1 + example.com/b v0.2.0 => ./b2 + example.com/c v0.1.0 => ./c1 + example.com/c v0.2.0 => ./c2 +) +-- lazy.go -- +package lazy + +import ( + _ "example.com/a" +) +-- a/go.mod -- +module example.com/a + +go 1.15 + +require example.com/b v0.1.0 +-- a/a.go -- +package a +-- a/a_test.go -- +package a + +import ( + "testing" + + _ "example.com/b" +) + +func TestUsingB(t *testing.T) { + // … +} +-- b1/go.mod -- +module example.com/b + +go 1.15 + +require example.com/c v0.1.0 +-- b1/b.go -- +package b +-- b1/b_test.go -- +package b + +import _ "example.com/c" +-- b2/go.mod -- +module example.com/b + +go 1.15 + +require example.com/c v0.1.0 +-- b2/b.go -- +package b +This file should not be used, so this syntax error should be ignored. +-- b2/b_test.go -- +package b +This file should not be used, so this syntax error should be ignored. +-- c1/go.mod -- +module example.com/c + +go 1.15 +-- c1/c.go -- +package c +-- c2/go.mod -- +module example.com/c + +go 1.15 +-- c2/c.go -- +package c +This file should not be used, so this syntax error should be ignored. diff --git a/libgo/go/cmd/go/testdata/script/mod_list.txt b/libgo/go/cmd/go/testdata/script/mod_list.txt index 1ba6d7c..239c7ca 100644 --- a/libgo/go/cmd/go/testdata/script/mod_list.txt +++ b/libgo/go/cmd/go/testdata/script/mod_list.txt @@ -29,7 +29,8 @@ stdout 'v1.3.0.*mod[\\/]rsc.io[\\/]sampler@v1.3.1 .*[\\/]v1.3.1.mod => v1.3.1.*s go list std stdout ^math/big -# rsc.io/quote/buggy should be listable as a package +# rsc.io/quote/buggy should be listable as a package, +# even though it is only a test. go list -mod=mod rsc.io/quote/buggy # rsc.io/quote/buggy should not be listable as a module diff --git a/libgo/go/cmd/go/testdata/script/mod_list_deprecated.txt b/libgo/go/cmd/go/testdata/script/mod_list_deprecated.txt new file mode 100644 index 0000000..f0ecbba --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_list_deprecated.txt @@ -0,0 +1,52 @@ +# 'go list pkg' does not show deprecation. +go list example.com/deprecated/a +stdout '^example.com/deprecated/a$' + +# 'go list -m' does not show deprecation. +go list -m example.com/deprecated/a +stdout '^example.com/deprecated/a v1.9.0$' + +# 'go list -m -versions' does not show deprecation. +go list -m -versions example.com/deprecated/a +stdout '^example.com/deprecated/a v1.0.0 v1.9.0$' + +# 'go list -m -u' shows deprecation. +go list -m -u example.com/deprecated/a +stdout '^example.com/deprecated/a v1.9.0 \(deprecated\)$' + +# 'go list -m -u -f' exposes the deprecation message. +go list -m -u -f {{.Deprecated}} example.com/deprecated/a +stdout '^in example.com/deprecated/a@v1.9.0$' + +# This works even if we use an old version that does not have the deprecation +# message in its go.mod file. +go get -d example.com/deprecated/a@v1.0.0 +! grep Deprecated: $WORK/gopath/pkg/mod/cache/download/example.com/deprecated/a/@v/v1.0.0.mod +go list -m -u -f {{.Deprecated}} example.com/deprecated/a +stdout '^in example.com/deprecated/a@v1.9.0$' + +# 'go list -m -u' does not show deprecation for the main module. +go list -m -u +! stdout deprecated +go list -m -u -f '{{if not .Deprecated}}ok{{end}}' +stdout ok + +# 'go list -m -u' does not show a deprecation message for a module that is not +# deprecated at the latest version, even if it is deprecated at the current +# version. +go list -m -u example.com/undeprecated +stdout '^example.com/undeprecated v1.0.0 \[v1.0.1\]$' +-- go.mod -- +// Deprecated: main module is deprecated, too! +module example.com/use + +go 1.17 + +require ( + example.com/deprecated/a v1.9.0 + example.com/undeprecated v1.0.0 +) +-- go.sum -- +example.com/deprecated/a v1.9.0 h1:pRyvBIZheJpQVVnNW4Fdg8QuoqDgtkCreqZZbASV3BE= +example.com/deprecated/a v1.9.0/go.mod h1:Z1uUVshSY9kh6l/2hZ8oA9SBviX2yfaeEpcLDz6AZwY= +example.com/undeprecated v1.0.0/go.mod h1:1qiRbdA9VzJXDqlG26Y41O5Z7YyO+jAD9do8XCZQ+Gg= diff --git a/libgo/go/cmd/go/testdata/script/mod_list_deprecated_replace.txt b/libgo/go/cmd/go/testdata/script/mod_list_deprecated_replace.txt new file mode 100644 index 0000000..48b991f --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_list_deprecated_replace.txt @@ -0,0 +1,68 @@ +# When all versions are replaced, we should not look up a deprecation message. +# We will still look up a deprecation message for the replacement. +cp go.mod.allreplaced go.mod +go list -m -u -f '{{.Path}}@{{.Version}} <{{.Deprecated}}>{{with .Replace}} => {{.Path}}@{{.Version}} <{{.Deprecated}}>{{end}}' all +stdout '^example.com/deprecated/a@v1.0.0 <> => example.com/deprecated/b@v1.0.0 <in example.com/deprecated/b@v1.9.0>$' + +# When one version is replaced, we should see a deprecation message. +cp go.mod.onereplaced go.mod +go list -m -u -f '{{.Path}}@{{.Version}} <{{.Deprecated}}>{{with .Replace}} => {{.Path}}@{{.Version}} <{{.Deprecated}}>{{end}}' all +stdout '^example.com/deprecated/a@v1.0.0 <in example.com/deprecated/a@v1.9.0> => example.com/deprecated/b@v1.0.0 <in example.com/deprecated/b@v1.9.0>$' + +# If the replacement is a directory, we won't look that up. +cp go.mod.dirreplacement go.mod +go list -m -u -f '{{.Path}}@{{.Version}} <{{.Deprecated}}>{{with .Replace}} => {{.Path}}@{{.Version}} <{{.Deprecated}}>{{end}}' all +stdout '^example.com/deprecated/a@v1.0.0 <> => ./a@ <>$' + +# If the latest version of the replacement is replaced, we'll use the content +# from that replacement. +cp go.mod.latestreplaced go.mod +go list -m -u -f '{{.Path}}@{{.Version}} <{{.Deprecated}}>{{with .Replace}} => {{.Path}}@{{.Version}} <{{.Deprecated}}>{{end}}' all +stdout '^example.com/deprecated/a@v1.0.0 <> => example.com/deprecated/b@v1.0.0 <in ./b>$' + +-- go.mod.allreplaced -- +module m + +go 1.17 + +require example.com/deprecated/a v1.0.0 + +replace example.com/deprecated/a => example.com/deprecated/b v1.0.0 +-- go.mod.onereplaced -- +module m + +go 1.17 + +require example.com/deprecated/a v1.0.0 + +replace example.com/deprecated/a v1.0.0 => example.com/deprecated/b v1.0.0 +-- go.mod.dirreplacement -- +module m + +go 1.17 + +require example.com/deprecated/a v1.0.0 + +replace example.com/deprecated/a => ./a +-- go.mod.latestreplaced -- +module m + +go 1.17 + +require example.com/deprecated/a v1.0.0 + +replace ( + example.com/deprecated/a => example.com/deprecated/b v1.0.0 + example.com/deprecated/b v1.9.0 => ./b +) +-- go.sum -- +example.com/deprecated/b v1.0.0/go.mod h1:b19J9ywRGviY7Nq4aJ1WBJ+A7qUlEY9ihp22yI4/F6M= +-- a/go.mod -- +module example.com/deprecated/a + +go 1.17 +-- b/go.mod -- +// Deprecated: in ./b +module example.com/deprecated/b + +go 1.17 diff --git a/libgo/go/cmd/go/testdata/script/mod_list_retract.txt b/libgo/go/cmd/go/testdata/script/mod_list_retract.txt new file mode 100644 index 0000000..4b13348 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_list_retract.txt @@ -0,0 +1,108 @@ +# 'go list -mod=vendor -retracted' reports an error. +go mod vendor +! go list -m -retracted -mod=vendor +stderr '^go list -retracted cannot be used when vendoring is enabled$' +rm vendor + +# 'go list -retracted' reports an error in GOPATH mode. +env GO111MODULE=off +! go list -retracted +stderr '^go list -retracted can only be used in module-aware mode$' +env GO111MODULE= + +# 'go list pkg' does not show retraction. +go list -f '{{with .Module}}{{with .Retracted}}retracted{{end}}{{end}}' example.com/retract +! stdout . + +# 'go list -retracted pkg' shows retraction. +go list -retracted -f '{{with .Module}}{{with .Retracted}}retracted{{end}}{{end}}' example.com/retract +stdout retracted + +# 'go list -m' does not show retraction. +go list -m -f '{{with .Retracted}}retracted{{end}}' example.com/retract +! stdout . + +# 'go list -m -retracted' shows retraction. +go list -m -retracted -f '{{with .Retracted}}retracted{{end}}' example.com/retract + +# 'go list -m mod@version' does not show retraction. +go list -m -f '{{with .Retracted}}retracted{{end}}' example.com/retract@v1.0.0-unused +! stdout . + +# 'go list -m -retracted mod@version' does not show an error if the module +# that would contain the retraction is unavailable. See #45305. +go list -m -retracted -f '{{.Path}} {{.Version}} {{.Error}}' example.com/retract/missingmod@v1.0.0 +stdout '^example.com/retract/missingmod v1.0.0 <nil>$' +exists $GOPATH/pkg/mod/cache/download/example.com/retract/missingmod/@v/v1.9.0.info +! exists $GOPATH/pkg/mod/cache/download/example.com/retract/missingmod/@v/v1.9.0.mod + +# 'go list -m -retracted mod@version' shows retractions. +go list -m -retracted example.com/retract@v1.0.0-unused +stdout '^example.com/retract v1.0.0-unused \(retracted\)$' +go list -m -retracted -f '{{with .Retracted}}retracted{{end}}' example.com/retract@v1.0.0-unused +stdout retracted + +# 'go list -m mod@latest' selects a previous release version, not self-retracted latest. +go list -m -f '{{.Version}}{{with .Retracted}} retracted{{end}}' example.com/retract/self/prev@latest +stdout '^v1.1.0$' + +# 'go list -m -retracted mod@latest' selects the self-retracted latest version. +go list -m -retracted -f '{{.Version}}{{with .Retracted}} retracted{{end}}' example.com/retract/self/prev@latest +stdout '^v1.9.0 retracted$' + +# 'go list -m mod@latest' selects a pre-release version if all release versions are retracted. +go list -m -f '{{.Version}}{{with .Retracted}} retracted{{end}}' example.com/retract/self/prerelease@latest +stdout '^v1.9.1-pre$' + +# 'go list -m -retracted mod@latest' selects the self-retracted latest version. +go list -m -retracted -f '{{.Version}}{{with .Retracted}} retracted{{end}}' example.com/retract/self/prerelease@latest +stdout '^v1.9.0 retracted$' + +# 'go list -m mod@latest' selects a pseudo-version if all versions are retracted. +# TODO(golang.org/issue/24031): the proxy does not expose the pseudo-version, +# even if all release versions are retracted. +go list -m -e -f '{{.Error.Err}}' example.com/retract/self/pseudo@latest +stdout '^module example.com/retract/self/pseudo: no matching versions for query "latest"$' + +# 'go list -m mod@latest' reports an error if all versions are retracted. +go list -m -e -f '{{.Error.Err}}' example.com/retract/self/all@latest +stdout '^module example.com/retract/self/all: no matching versions for query "latest"$' + +# 'go list -m mod@<v1.10' selects a previous release version, not self-retracted latest. +# The @latest query is not special with respect to retractions. +go list -m -f '{{.Version}}{{with .Retracted}} retracted{{end}}' example.com/retract/self/prev@<v1.10 +stdout '^v1.1.0$' + +# 'go list -m -versions' hides retracted versions. +go list -m -versions example.com/retract +stdout '^example.com/retract v1.0.0-good v1.1.0$' + +# 'go list -m -retracted -versions' shows retracted versions. +go list -m -retracted -versions example.com/retract +stdout '^example.com/retract v1.0.0-bad v1.0.0-good v1.0.0-unused v1.1.0$' + +# 'go list -m -u -versions' loads retractions and does not show retracted versions. +go list -m -u -versions example.com/retract +stdout '^example.com/retract v1.0.0-good v1.1.0$' +go list -m -u -versions -f '{{with .Retracted}}retracted{{end}}' example.com/retract +stdout retracted + +# 'go list -m -u' shows retraction. +go list -m -u -f '{{with .Retracted}}retracted{{end}}' example.com/retract +stdout retracted + +# 'go list -m -u' does not suggest an update to a self-retracted latest version. +go list -m -u -f '{{with .Update}}{{.Version}}{{with .Retracted}} retracted{{end}}{{end}}' example.com/retract/self/prev@v1.0.0-bad +stdout '^v1.1.0$' + +-- go.mod -- +module example.com/use + +go 1.15 + +require example.com/retract v1.0.0-bad + +-- use.go -- +package use + +import _ "example.com/retract" diff --git a/libgo/go/cmd/go/testdata/script/mod_list_std.txt b/libgo/go/cmd/go/testdata/script/mod_list_std.txt index baf7908..f4e0433 100644 --- a/libgo/go/cmd/go/testdata/script/mod_list_std.txt +++ b/libgo/go/cmd/go/testdata/script/mod_list_std.txt @@ -48,18 +48,20 @@ stdout ^vendor/golang.org/x/crypto/internal/subtle ! stdout ^golang\.org/x # Within the std module, the dependencies of the non-vendored packages within -# std should appear to come from modules, but they should be loaded from the -# vendor directory (just like ordinary vendored module dependencies). +# std should appear to be packages beginning with 'vendor/', not 'golang.org/…' +# module dependencies. go list all -stdout ^golang.org/x/ +! stdout ^golang.org/x/ ! stdout ^std/ ! stdout ^cmd/ -! stdout ^vendor/ +stdout ^vendor/ go list -deps -f '{{if not .Standard}}{{.ImportPath}}{{end}}' std -! stdout ^vendor/golang.org/x/net/http2/hpack -stdout ^golang.org/x/net/http2/hpack +! stdout . + +# However, the 'golang.org/…' module dependencies should resolve to those same +# directories. go list -f '{{.Dir}}' golang.org/x/net/http2/hpack stdout $GOROOT[/\\]src[/\\]vendor diff --git a/libgo/go/cmd/go/testdata/script/mod_list_sums.txt b/libgo/go/cmd/go/testdata/script/mod_list_sums.txt new file mode 100644 index 0000000..86c528f --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_list_sums.txt @@ -0,0 +1,32 @@ +# https://golang.org/issue/41297: 'go list -m' should not require go.sum with +# -versions or when all args are version queries. + +go mod init m +go mod edit -require=rsc.io/quote@v1.5.1 + +go list -m -mod=readonly rsc.io/quote@latest +stdout '^rsc\.io/quote v1\.5\.2$' +! stderr . + +go list -m -mod=readonly -versions rsc.io/quote +stdout 'rsc\.io/quote v1\.0\.0 .* v1\.5\.3-pre1$' +! stderr . + +# Incidentally fetching the required version of a module records its checksum, +# just because it happens to be in the build list, and recording the checksum +# triggers an error under -mod=readonly. +# +# TODO(#41297): This should not be an error. +! go list -m -mod=readonly rsc.io/quote@<v1.5.2 +stderr '^go: updates to go.sum needed, disabled by -mod=readonly$' +! stderr 'missing go.sum entry' + +# Attempting to list the versions of a module that is not a root dependency +# causes the build list to be resolved (so that the selected version can *also* +# be identified, even though it is not relevant to this particular output). +# That, in turn, causes us to need checksums for the go.sum files for the +# modules in the module graph. +# +# TODO(#41297): This should not be an error either. +! go list -m -mod=readonly -versions rsc.io/sampler +stderr '^go list -m: rsc\.io/quote@v1\.5\.1: missing go\.sum entry; to add it:\n\tgo mod download rsc\.io/quote$' diff --git a/libgo/go/cmd/go/testdata/script/mod_list_test_cycle.txt b/libgo/go/cmd/go/testdata/script/mod_list_test_cycle.txt new file mode 100644 index 0000000..755e50b --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_list_test_cycle.txt @@ -0,0 +1,23 @@ +# https://golang.org/issue/45863: a typo in a test package leading to an +# import cycle should be diagnosed, instead of causing an infinite loop. +# The failure mode of this test prior to the fix was a timeout or OOM crash. + +go list -e -test -deps ./datastore/sql + +-- go.mod -- +module golang.org/issue45863 + +go 1.17 +-- datastore/datastore_health.go -- +package datastore + +import ( + "golang.org/issue45863/datastore" + "golang.org/issue45863/datastore/sql" +) +-- datastore/sql/sql.go -- +package sql +-- datastore/sql/sql_test.go -- +package sql + +import _ "golang.org/issue45863/datastore" diff --git a/libgo/go/cmd/go/testdata/script/mod_list_update_nolatest.txt b/libgo/go/cmd/go/testdata/script/mod_list_update_nolatest.txt new file mode 100644 index 0000000..c6bbbb0 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_list_update_nolatest.txt @@ -0,0 +1,55 @@ +# Check that if a proxy does not have a version of a module that could be +# an upgrade, 'go list -m -u' still succeeds. +# We use a local file proxy, since our test proxy doesn't have the behavior +# we want to test, and we don't want it to be too clever. +# Verifies #45305, where proxy.golang.org serves an empty /@v/list (200) +# but has no /@latest (410) because the go.mod at the tip of the default +# branch has a different major version suffix. +env testproxy=$GOPROXY +env GOPROXY=file:///$WORK/proxy +env GOSUMDB=off + +# If the proxy does not return a list of versions (404/410) +# or a latest version (404/410), we should see no error. +go list -m example.com/noversion +stdout '^example.com/noversion v0.0.0$' +go list -m -u example.com/noversion +stdout '^example.com/noversion v0.0.0$' + +# If the proxy returns an empty list of versions (200, not 404/410) +# but does not have a latest version (404/410), we should see no error. +go list -m example.com/nolatest +stdout '^example.com/nolatest v0.0.0$' +go list -m -u example.com/nolatest +stdout '^example.com/nolatest v0.0.0$' + +# If proxy returns an invalid response, we should see an error. +env GOPROXY=$testproxy/invalid +! go list -m -u example.com/nolatest +stderr '^go list -m: loading module retractions for example.com/nolatest@v0.0.0: invalid response from proxy "[^"]*": invalid character ''i'' looking for beginning of value$' + +-- go.mod -- +module m + +go 1.17 + +require ( + example.com/nolatest v0.0.0 + example.com/noversion v0.0.0 +) +-- go.sum -- +example.com/nolatest v0.0.0/go.mod h1:HnLrCt6SJga5tCtJ7IzG9dOOCniY3G5C0VT7jfMdS0M= +example.com/noversion v0.0.0/go.mod h1:2RUfWiCYsygSXPM2Igxx0FD3Kq33OnVdxm34eDDhXbQ= +-- $WORK/proxy/example.com/nolatest/@v/list -- +-- $WORK/proxy/example.com/nolatest/@v/v0.0.0.info -- +{"Version":"v0.0.0"} +-- $WORK/proxy/example.com/nolatest/@v/v0.0.0.mod -- +module example.com/nolatest + +go 1.17 +-- $WORK/proxy/example.com/noversion/@v/v0.0.0.info -- +{"Version":"v0.0.0"} +-- $WORK/proxy/example.com/noversion/@v/v0.0.0.mod -- +module example.com/noversion + +go 1.17 diff --git a/libgo/go/cmd/go/testdata/script/mod_load_badchain.txt b/libgo/go/cmd/go/testdata/script/mod_load_badchain.txt index c0c382b..eb464ab 100644 --- a/libgo/go/cmd/go/testdata/script/mod_load_badchain.txt +++ b/libgo/go/cmd/go/testdata/script/mod_load_badchain.txt @@ -22,7 +22,7 @@ cmp go.mod go.mod.orig # Update manually. Listing modules should produce an error. go mod edit -require=example.com/badchain/a@v1.1.0 -! go list -m +! go list -m all cmp stderr list-expected # Try listing a package that imports a package @@ -69,19 +69,17 @@ import ( func Test(t *testing.T) {} -- update-main-expected -- -go get: example.com/badchain/c@v1.0.0 updating to - example.com/badchain/c@v1.1.0: parsing go.mod: +go get: example.com/badchain/c@v1.1.0: parsing go.mod: module declares its path as: badchain.example.com/c but was required as: example.com/badchain/c -- update-a-expected -- -go get: example.com/badchain/a@v1.0.0 updating to - example.com/badchain/a@v1.1.0 requires +go get: example.com/badchain/a@v1.1.0 requires example.com/badchain/b@v1.1.0 requires example.com/badchain/c@v1.1.0: parsing go.mod: module declares its path as: badchain.example.com/c but was required as: example.com/badchain/c -- list-expected -- -go: example.com/badchain/a@v1.1.0 requires +go list -m: example.com/badchain/a@v1.1.0 requires example.com/badchain/b@v1.1.0 requires example.com/badchain/c@v1.1.0: parsing go.mod: module declares its path as: badchain.example.com/c diff --git a/libgo/go/cmd/go/testdata/script/mod_load_replace_mismatch.txt b/libgo/go/cmd/go/testdata/script/mod_load_replace_mismatch.txt new file mode 100644 index 0000000..2ca8b3c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_load_replace_mismatch.txt @@ -0,0 +1,23 @@ +# If a replacement module declares a module path different from both +# the original module and its location, report an error with all three paths. +# In particular, the "required as" path should be the original. +# Verifies golang.org/issue/38220. +! go mod download +cmp stderr want + +-- go.mod -- +module m + +require rsc.io/quote v1.5.2 + +replace rsc.io/quote v1.5.2 => example.com/quote v1.5.2 + +-- use.go -- +package use + +import _ "rsc.io/quote" + +-- want -- +go: rsc.io/quote@v1.5.2 (replaced by example.com/quote@v1.5.2): parsing go.mod: + module declares its path as: rsc.io/Quote + but was required as: rsc.io/quote diff --git a/libgo/go/cmd/go/testdata/script/mod_notall.txt b/libgo/go/cmd/go/testdata/script/mod_notall.txt new file mode 100644 index 0000000..1657c8d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_notall.txt @@ -0,0 +1,99 @@ +# This test demonstrates go commands that combine the 'all' pattern +# with packages outside of 'all'. + +# With -deps, 'all' should include test dependencies of packages in the main +# module, but not should not include test dependencies of packages imported only +# by other root patterns. + +env GOFLAGS=-mod=mod +cp go.mod go.mod.orig + +go list -deps all x/otherroot + +stdout '^x/inall$' +stdout '^x/inall/fromtest$' +stdout '^x/inall/fromtestinall$' +stdout '^x/otherroot$' +stdout '^x/otherdep$' + +! stdout '^x/fromotherroottest$' +! stdout '^y/fromotherdeptest$' + +cmp go.mod go.mod.orig + +# With -deps -test, test dependencies of other roots should be included, +# but test dependencies of non-roots should not. + +go list -deps -test all x/otherroot +stdout '^x/inall$' +stdout '^x/inall/fromtest$' +stdout '^x/inall/fromtestinall$' +stdout '^x/otherroot$' +stdout '^x/otherdep$' + +stdout '^x/fromotherroottest$' +! stdout '^y/fromotherdeptest$' + +cmp go.mod go.mod.orig + +-- m.go -- +package m + +import _ "x/inall" +-- m_test.go -- +package m_test + +import _ "x/inall/fromtest" +-- go.mod -- +module m + +go 1.15 + +require x v0.1.0 + +replace ( + x v0.1.0 => ./x + y v0.1.0 => ./y +) +-- x/go.mod -- +module x + +go 1.15 +-- x/inall/inall.go -- +package inall +-- x/inall/inall_test.go -- +package inall_test + +import _ "x/inall/fromtestinall" +-- x/inall/fromtest/fromtest.go -- +package fromtest +-- x/inall/fromtestinall/fromtestinall.go -- +package fromtestinall +-- x/otherroot/otherroot.go -- +package otherroot + +import _ "x/otherdep" +-- x/otherroot/otherroot_test.go -- +package otherroot_test + +import _ "x/fromotherroottest" +-- x/fromotherroottest/fromotherroottest.go -- +package fromotherroottest +-- x/otherdep/otherdep.go -- +package otherdep +-- x/otherdep/otherdep_test.go -- +package otherdep_test + +import _ "y/fromotherdeptest" +-- x/otherroot/testonly/testonly.go -- +package testonly +-- y/go.mod -- +module y + +go 1.15 +-- y/fromotherdeptest/fromotherdeptest.go -- +// Package fromotherdeptest is a test dependency of x/otherdep that is +// not declared in x/go.mod. If the loader resolves this package, +// it will add this module to the main module's go.mod file, +// and we can detect the mistake. +package fromotherdeptest diff --git a/libgo/go/cmd/go/testdata/script/mod_outside.txt b/libgo/go/cmd/go/testdata/script/mod_outside.txt index 5655892..33341f7 100644 --- a/libgo/go/cmd/go/testdata/script/mod_outside.txt +++ b/libgo/go/cmd/go/testdata/script/mod_outside.txt @@ -61,6 +61,11 @@ stderr 'go: cannot match "all": go.mod file not found in current directory or an stderr 'go: cannot match "all": go.mod file not found in current directory or any parent directory; see ''go help modules''$' ! stdout 'example.com/version' +# 'go list -m <mods>' should fail if any of the mods lacks an explicit version. +! go list -m example.com/printversion +stderr 'go: cannot match "example.com/printversion" without -versions or an explicit version: go.mod file not found in current directory or any parent directory; see ''go help modules''$' +! stdout 'example.com/version' + # 'go list -m' with wildcards should fail. Wildcards match modules in the # build list, so they aren't meaningful outside a module. ! go list -m ... @@ -164,6 +169,8 @@ go build -n -o ignore ./stdonly/stdonly.go # 'go build' should succeed for standard-library packages. go build -n fmt +# 'go build' should use the latest version of the Go language. +go build ./newgo/newgo.go # 'go doc' without arguments implicitly operates on the current directory, and should fail. # TODO(golang.org/issue/32027): currently, it succeeds. @@ -200,10 +207,6 @@ stderr 'needmod[/\\]needmod.go:10:2: no required module provides package example go install cmd/addr2line ! stderr . -# 'go run' with a verison should fail due to syntax. -! go run example.com/printversion@v1.0.0 -stderr 'can only use path@version syntax with' - # 'go run' should fail if a package argument must be resolved to a module. ! go run example.com/printversion stderr '^no required module provides package example.com/printversion: go.mod file not found in current directory or any parent directory; see ''go help modules''$' @@ -326,3 +329,15 @@ func Test(t *testing.T) { fmt.Println("stdonly was tested") } +-- newgo/newgo.go -- +// Package newgo requires Go 1.14 or newer. +package newgo + +import "io" + +const C = 299_792_458 + +type ReadWriteCloser interface { + io.ReadCloser + io.WriteCloser +} diff --git a/libgo/go/cmd/go/testdata/script/mod_overlay.txt b/libgo/go/cmd/go/testdata/script/mod_overlay.txt new file mode 100644 index 0000000..86ab04b --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_overlay.txt @@ -0,0 +1,254 @@ +# Test overlays that affect go.mod files + +# The go.mod file can exist only in the overlay. +cd $WORK/gopath/src/no-go-mod +go list -overlay overlay.json . +stdout example.com/simple + +# Check content of overlaid go.mod is used. +cd $WORK/gopath/src/overlay-go-mod +go list -overlay overlay.json . +stdout use.this/module/name + +# Check content of overlaid go.mod in a replacement module is used. +# The go.mod in the replacement module is missing a requirement +# that the overlay has, so it will fail to list without the overlay. +cd $WORK/gopath/src/overlay-replaced-go-mod +! go list -deps . +go list -deps -overlay overlay.json . + +# Overlaid go.mod is not rewritten by 'go get'. +cd $WORK/gopath/src/get-doesnt-add-dep +cp $WORK/overlay/get_doesnt_add_dep_go_mod $WORK/want_go_mod +! go get -d -overlay overlay.json . +stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$' +cmp $WORK/overlay/get_doesnt_add_dep_go_mod $WORK/want_go_mod + +# Content of overlaid go.sum is used. +# The go.sum in the module directory has garbage values for its +# hashes, but the overlaid file has the correct values. If +# the correct go.sum is used with the overlay, 'go get .' should +# not report a security error. +cd $WORK/gopath/src/overlay-sum-used +! go get -d . +stderr 'SECURITY ERROR' +! go mod verify +stderr 'SECURITY ERROR' +go get -d -overlay overlay.json . +go mod verify -overlay overlay.json +# Overlaid go.sum is not rewritten. +# Copy an incomplete file to the overlay file, and expect an error +# attempting to update the file +cp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums +! go get -d -overlay overlay.json . +stderr '^go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay$' +cmp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums +! go mod tidy -overlay overlay.json +stderr '^go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay$' +cmp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums + +# -overlay works with -modfile. +# There's an empty go.mod file in the directory, and the file alternate.mod is +# overlaid to the true go.mod file, so the -modfile flag and the overlay +# mechanism need to work together to determine the name of the module. +cd $WORK/gopath/src/overlay-and-dash-modfile +go list -modfile=alternate.mod -overlay overlay.json . +stdout 'found.the/module' +# Even with -modfile, overlaid files can't be opened for write. +! go get -modfile=alternate.mod -overlay overlay.json -d rsc.io/quote +stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$' + +# Carving out a module by adding an overlaid go.mod file +cd $WORK/gopath/src/carve +go list ./... # without an overlay, hasmod is carved out and nomod isn't +stdout carve/nomod +! stdout carve/hasmod +go list -overlay overlay_carve_module.json ./... # The overlay carves out nomod, leaving nothing +! stdout . +stderr 'matched no packages' +go list -overlay overlay_uncarve_module.json ./... # The overlay uncarves out hasmod +stdout carve/nomod +stdout carve/hasmod + +# Carving out a module by adding an overlaid go.mod file and using +# -modfile to write to that file. +cd $WORK/gopath/src/carve2/nomod +go list -overlay overlay.json all +! stdout ^carve2$ +stdout ^carve2/nomod$ +# Editing go.mod file fails because overlay is read only +! go get -overlay overlay.json -d rsc.io/quote +stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$' +! grep rsc.io/quote $WORK/overlay/carve2-nomod-go.mod +# Editing go.mod file succeeds because we use -modfile to redirect to same file +go get -overlay overlay.json -modfile $WORK/overlay/carve2-nomod-go.mod -d rsc.io/quote +grep rsc.io/quote $WORK/overlay/carve2-nomod-go.mod + +-- no-go-mod/file.go -- +package simple +-- no-go-mod/overlay.json -- +{ + "Replace": { + "go.mod": "../../../overlay/simple_go_mod" + } +} +-- $WORK/overlay/simple_go_mod -- +module example.com/simple +-- overlay-go-mod/file.go -- +package name +-- overlay-go-mod/go.mod -- +module dont.use/this/module/name +-- overlay-go-mod/overlay.json -- +{ + "Replace": { + "go.mod": "../../../overlay/use_this_go_mod" + } +} +-- $WORK/overlay/use_this_go_mod -- +module use.this/module/name +-- overlay-replaced-go-mod/go.mod -- +module m + +go 1.15 + +require replaced/mod v1.0.0 +replace replaced/mod v1.0.0 => ../replaced-mod +replace dep/mod v1.0.0 => ../dep-mod +-- overlay-replaced-go-mod/source.go -- +package m + +import "replaced/mod/foo" + +func main() { + foo.f() +} +-- overlay-replaced-go-mod/overlay.json -- +{ + "Replace": { + "../replaced-mod/go.mod": "../../../overlay/replacement_module_go_mod" + } +} +-- replaced-mod/go.mod -- +module replaced/mod +-- replaced-mod/foo/foo.go -- +package foo + +import "dep/mod/foo" + +func f() { foo.g() } +-- dep-mod/go.mod -- +invalid +-- dep-mod/foo/foo.go -- +package foo + +func g() { fmt.Println("hello") } +-- $WORK/overlay/replacement_module_go_mod -- +module replaced/mod + +require dep/mod v1.0.0 + +-- get-doesnt-add-dep/overlay.json -- +{ + "Replace": { + "go.mod": "../../../overlay/get_doesnt_add_dep_go_mod" + } +} +-- get-doesnt-add-dep/p.go -- +package p + +import "dependency/mod" + +func f() { mod.G() } +-- get-doesnt-add-dep-dependency/go.mod -- +module dependency/mod +-- get-doesnt-add-dep-dependency/mod.go -- +package mod + +func G() {} +-- $WORK/overlay/get_doesnt_add_dep_go_mod -- +module get.doesnt/add/dep + +replace dependency/mod v1.0.0 => ../get-doesnt-add-dep-dependency +-- overlay-sum-used/go.mod -- +module overlay.sum/used + +require rsc.io/quote v1.5.0 +-- overlay-sum-used/p.go -- +package p + +import "rsc.io/quote" + +func f() string { + return quote.Hello() +} +-- overlay-sum-used/incomplete-sum-file -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw= +rsc.io/quote v1.5.0 h1:6fJa6E+wGadANKkUMlZ0DhXFpoKlslOQDCo259XtdIE= +rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII= +-- overlay-sum-used/overlay.json -- +{ + "Replace": { + "go.sum": "../../../overlay/overlay-sum-used-correct-sums" + } +} +-- overlay-sum-used/go.sum -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:garbage+hash +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:garbage+hash +rsc.io/quote v1.5.0 h1:garbage+hash +rsc.io/quote v1.5.0/go.mod h1:garbage+hash +rsc.io/sampler v1.3.0 h1:garbage+hash +rsc.io/sampler v1.3.0/go.mod h1:garbage+hash +-- $WORK/overlay/overlay-sum-used-correct-sums -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.0 h1:6fJa6E+wGadANKkUMlZ0DhXFpoKlslOQDCo259XtdIE= +rsc.io/quote v1.5.0/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +-- overlay-and-dash-modfile/p.go -- +package module +-- overlay-and-dash-modfile/go.mod -- +-- overlay-and-dash-modfile/overlay.json -- +{ + "Replace": { + "alternate.mod": "../../../overlay/overlay-and-dash-modfile-alternate-mod" + } +} +-- $WORK/overlay/overlay-and-dash-modfile-alternate-mod -- +module found.the/module +-- carve/go.mod -- +module carve +-- carve/overlay_carve_module.json -- +{ + "Replace": { + "nomod/go.mod": "../../../overlay/carve-nomod-go-mod" + } +} +-- carve/overlay_uncarve_module.json -- +{ + "Replace": { + "hasmod/go.mod": "" + } +} +-- carve/hasmod/a.go -- +package hasmod +-- carve/hasmod/go.mod -- +module carve/hasmod +-- carve/nomod/b.go -- +package nomod +-- $WORK/overlay/carve-nomod-go-mod -- +module carve/nomod +-- carve2/go.mod -- +module carve2 +-- carve2/p.go -- +package p +-- carve2/nomod/overlay.json -- +{ + "Replace": { + "go.mod": "../../../../overlay/carve2-nomod-go.mod" + } +} +-- carve2/nomod/b.go -- +package nomod +-- $WORK/overlay/carve2-nomod-go.mod -- +module carve2/nomod diff --git a/libgo/go/cmd/go/testdata/script/mod_prefer_compatible.txt b/libgo/go/cmd/go/testdata/script/mod_prefer_compatible.txt index aa6260f..1b408c3 100644 --- a/libgo/go/cmd/go/testdata/script/mod_prefer_compatible.txt +++ b/libgo/go/cmd/go/testdata/script/mod_prefer_compatible.txt @@ -23,8 +23,8 @@ stdout '^github.com/russross/blackfriday v1\.' go list -m github.com/russross/blackfriday@upgrade stdout '^github.com/russross/blackfriday v1\.' -go list -m github.com/russross/blackfriday@patch -stdout '^github.com/russross/blackfriday v1\.' +! go list -m github.com/russross/blackfriday@patch +stderr '^go list -m: github.com/russross/blackfriday@patch: can''t query version "patch" of module github.com/russross/blackfriday: no existing version is required$' # If we're fetching directly from version control, ignored +incompatible # versions should also be omitted by 'go list'. diff --git a/libgo/go/cmd/go/testdata/script/mod_proxy_https.txt b/libgo/go/cmd/go/testdata/script/mod_proxy_https.txt index a23090c..a5e28dd 100644 --- a/libgo/go/cmd/go/testdata/script/mod_proxy_https.txt +++ b/libgo/go/cmd/go/testdata/script/mod_proxy_https.txt @@ -10,6 +10,7 @@ stderr 'invalid proxy URL.*proxydir' # GOPROXY HTTPS paths may elide the "https://" prefix. # (See golang.org/issue/32191.) env GOPROXY=proxy.golang.org +env GOSUMDB= go list -versions -m golang.org/x/text -- go.mod -- diff --git a/libgo/go/cmd/go/testdata/script/mod_proxy_invalid.txt b/libgo/go/cmd/go/testdata/script/mod_proxy_invalid.txt new file mode 100644 index 0000000..6427cc1 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_proxy_invalid.txt @@ -0,0 +1,8 @@ +env GO111MODULE=on +env GOPROXY=$GOPROXY/invalid + +! go list -m rsc.io/quote@latest +stderr '^go list -m: module rsc.io/quote: invalid response from proxy "'$GOPROXY'": invalid character ''i'' looking for beginning of value$' + +! go list -m rsc.io/quote@1.5.2 +stderr '^go list -m: rsc.io/quote@1.5.2: invalid version: invalid response from proxy "'$GOPROXY'": invalid character ''i'' looking for beginning of value$' diff --git a/libgo/go/cmd/go/testdata/script/mod_query_main.txt b/libgo/go/cmd/go/testdata/script/mod_query_main.txt new file mode 100644 index 0000000..39e5841 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_query_main.txt @@ -0,0 +1,43 @@ +# 'go mod download' can download specific versions of the main module. +go mod download rsc.io/quote@5d9f230b +go mod download rsc.io/quote@v1.5.2 +go mod download rsc.io/quote@latest + +# 'go mod download' will not download @upgrade or @patch, since they always +# resolve to the main module. +go mod download rsc.io/quote@upgrade +stderr '^go mod download: skipping argument rsc.io/quote@upgrade that resolves to the main module$' +go mod download rsc.io/quote@patch +stderr '^go mod download: skipping argument rsc.io/quote@patch that resolves to the main module$' + +# 'go list -m' can show a version of the main module. +go list -m rsc.io/quote@5d9f230b +stdout '^rsc.io/quote v0.0.0-20180710144737-5d9f230bcfba$' +go list -m rsc.io/quote@v1.5.2 +stdout '^rsc.io/quote v1.5.2$' +go list -m rsc.io/quote@latest +stdout '^rsc.io/quote v1.5.2$' + +# 'go list -m -versions' shows available versions. +go list -m -versions rsc.io/quote +stdout '^rsc.io/quote.*v1.5.2' + +# 'go list -m' resolves @upgrade and @patch to the main module. +go list -m rsc.io/quote@upgrade +stdout '^rsc.io/quote$' +go list -m rsc.io/quote@patch +stdout '^rsc.io/quote$' + +# 'go get' will not attempt to upgrade the main module to any specific version. +# See also: mod_get_main.txt. +! go get rsc.io/quote@5d9f230b +stderr '^go get: can''t request version "5d9f230b" of the main module \(rsc.io/quote\)$' +! go get rsc.io/quote@v1.5.2 +stderr '^go get: can''t request version "v1.5.2" of the main module \(rsc.io/quote\)$' +! go get rsc.io/quote@latest +stderr '^go get: can''t request version "latest" of the main module \(rsc.io/quote\)$' + +-- go.mod -- +module rsc.io/quote + +go 1.16 diff --git a/libgo/go/cmd/go/testdata/script/mod_replace.txt b/libgo/go/cmd/go/testdata/script/mod_replace.txt index dc9667f..a0a367f 100644 --- a/libgo/go/cmd/go/testdata/script/mod_replace.txt +++ b/libgo/go/cmd/go/testdata/script/mod_replace.txt @@ -48,7 +48,7 @@ stderr 'module rsc.io/quote/v3@upgrade found \(v3.0.0, replaced by ./local/rsc.i # The reported Dir and GoMod for a replaced module should be accurate. cp go.mod.orig go.mod go mod edit -replace=rsc.io/quote/v3=not-rsc.io/quote@v0.1.0-nomod -go mod download +go mod download rsc.io/quote/v3 go list -m -f '{{.Path}} {{.Version}} {{.Dir}} {{.GoMod}}{{with .Replace}} => {{.Path}} {{.Version}} {{.Dir}} {{.GoMod}}{{end}}' rsc.io/quote/v3 stdout '^rsc.io/quote/v3 v3.0.0 '$GOPATH'[/\\]pkg[/\\]mod[/\\]not-rsc.io[/\\]quote@v0.1.0-nomod '$GOPATH'[/\\]pkg[/\\]mod[/\\]cache[/\\]download[/\\]not-rsc.io[/\\]quote[/\\]@v[/\\]v0.1.0-nomod.mod => not-rsc.io/quote v0.1.0-nomod '$GOPATH'[/\\]pkg[/\\]mod[/\\]not-rsc.io[/\\]quote@v0.1.0-nomod '$GOPATH'[/\\]pkg[/\\]mod[/\\]cache[/\\]download[/\\]not-rsc.io[/\\]quote[/\\]@v[/\\]v0.1.0-nomod.mod$' diff --git a/libgo/go/cmd/go/testdata/script/mod_replace_gopkgin.txt b/libgo/go/cmd/go/testdata/script/mod_replace_gopkgin.txt index df752d9..d24f37b 100644 --- a/libgo/go/cmd/go/testdata/script/mod_replace_gopkgin.txt +++ b/libgo/go/cmd/go/testdata/script/mod_replace_gopkgin.txt @@ -35,7 +35,7 @@ go list -m gopkg.in/src-d/go-git.v4 # A mismatched gopkg.in path should not be able to replace a different major version. cd ../3-to-gomod-4 ! go list -m gopkg.in/src-d/go-git.v3 -stderr '^go: gopkg\.in/src-d/go-git\.v3@v3\.2\.0 \(replaced by gopkg\.in/src-d/go-git\.v3@v3\.0\.0-20190801152248-0d1a009cbb60\): version "v3\.0\.0-20190801152248-0d1a009cbb60" invalid: go\.mod has non-\.\.\.\.v3 module path "gopkg\.in/src-d/go-git\.v4" at revision 0d1a009cbb60$' +stderr '^go list -m: gopkg\.in/src-d/go-git\.v3@v3\.2\.0 \(replaced by gopkg\.in/src-d/go-git\.v3@v3\.0\.0-20190801152248-0d1a009cbb60\): version "v3\.0\.0-20190801152248-0d1a009cbb60" invalid: go\.mod has non-\.\.\.\.v3 module path "gopkg\.in/src-d/go-git\.v4" at revision 0d1a009cbb60$' -- 4-to-4/go.mod -- module golang.org/issue/34254 diff --git a/libgo/go/cmd/go/testdata/script/mod_replace_readonly.txt b/libgo/go/cmd/go/testdata/script/mod_replace_readonly.txt new file mode 100644 index 0000000..d950d78 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_replace_readonly.txt @@ -0,0 +1,62 @@ +# Check that with -mod=readonly, when we load a package in a module that is +# replaced but not required, we emit an error with the command to add the +# requirement. +# Verifies golang.org/issue/41416, golang.org/issue/41577. +cp go.mod go.mod.orig + +# Replace all versions of a module without requiring it. +# With -mod=mod, we'd add a requirement for a "zero" pseudo-version, but we +# can't in readonly mode, since its go.mod may alter the build list. +go mod edit -replace rsc.io/quote=./quote +! go list rsc.io/quote +stderr '^module rsc.io/quote provides package rsc.io/quote and is replaced but not required; to add it:\n\tgo get rsc.io/quote$' +go get -d rsc.io/quote +cmp go.mod go.mod.latest +go list rsc.io/quote +cp go.mod.orig go.mod + +# Same test with a specific version. +go mod edit -replace rsc.io/quote@v1.0.0-doesnotexist=./quote +! go list rsc.io/quote +stderr '^module rsc.io/quote provides package rsc.io/quote and is replaced but not required; to add it:\n\tgo get rsc.io/quote@v1.0.0-doesnotexist$' +go get -d rsc.io/quote@v1.0.0-doesnotexist +cmp go.mod go.mod.specific +go list rsc.io/quote +cp go.mod.orig go.mod + +# If there are multiple versions, the highest is suggested. +go mod edit -replace rsc.io/quote@v1.0.0-doesnotexist=./quote +go mod edit -replace rsc.io/quote@v1.1.0-doesnotexist=./quote +! go list rsc.io/quote +stderr '^module rsc.io/quote provides package rsc.io/quote and is replaced but not required; to add it:\n\tgo get rsc.io/quote@v1.1.0-doesnotexist$' + +-- go.mod -- +module m + +go 1.16 +-- go.mod.latest -- +module m + +go 1.16 + +replace rsc.io/quote => ./quote + +require rsc.io/quote v1.5.2 // indirect +-- go.mod.specific -- +module m + +go 1.16 + +replace rsc.io/quote v1.0.0-doesnotexist => ./quote + +require rsc.io/quote v1.0.0-doesnotexist // indirect +-- use.go -- +package use + +import _ "rsc.io/quote" +-- quote/go.mod -- +module rsc.io/quote + +go 1.16 +-- quote/quote.go -- +package quote diff --git a/libgo/go/cmd/go/testdata/script/mod_require_exclude.txt b/libgo/go/cmd/go/testdata/script/mod_require_exclude.txt index 9156d4c..0946dbf 100644 --- a/libgo/go/cmd/go/testdata/script/mod_require_exclude.txt +++ b/libgo/go/cmd/go/testdata/script/mod_require_exclude.txt @@ -7,16 +7,27 @@ cp go.mod go.mod.orig ! go list -mod=readonly -m all stderr '^go: ignoring requirement on excluded version rsc.io/sampler v1\.99\.99$' -stderr '^go: updates to go.mod needed, disabled by -mod=readonly$' +stderr '^go: updates to go.mod needed, disabled by -mod=readonly; to update it:\n\tgo mod tidy$' ! stdout '^rsc.io/sampler v1.99.99' cmp go.mod go.mod.orig ! go list -mod=vendor -m rsc.io/sampler stderr '^go: ignoring requirement on excluded version rsc.io/sampler v1\.99\.99$' -stderr '^go list -m: module rsc.io/sampler: can''t resolve module using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass\.\)$' +stderr '^go: updates to go.mod needed, disabled by -mod=vendor; to update it:\n\tgo mod tidy$' ! stdout '^rsc.io/sampler v1.99.99' cmp go.mod go.mod.orig +# The failure message should be clear when -mod=vendor is implicit. + +go mod edit -go=1.14 +! go list -m rsc.io/sampler +stderr '^go: ignoring requirement on excluded version rsc.io/sampler v1\.99\.99$' +stderr '^go: updates to go.mod needed, disabled by -mod=vendor\n\t\(Go version in go.mod is at least 1.14 and vendor directory exists\.\)\n\tto update it:\n\tgo mod tidy$' +! stdout '^rsc.io/sampler v1.99.99' +go mod edit -go=1.13 +cmp go.mod go.mod.orig + + # With the selected version excluded, commands that load only modules should # drop the excluded module. @@ -58,7 +69,11 @@ module x go 1.13 exclude rsc.io/sampler v1.99.99 + require rsc.io/sampler v1.99.99 +-- vendor/modules.txt -- +# rsc.io/sampler v1.99.99 +## explicit -- go.moddrop -- module x diff --git a/libgo/go/cmd/go/testdata/script/mod_retention.txt b/libgo/go/cmd/go/testdata/script/mod_retention.txt index a4441c4..7a371b1 100644 --- a/libgo/go/cmd/go/testdata/script/mod_retention.txt +++ b/libgo/go/cmd/go/testdata/script/mod_retention.txt @@ -62,9 +62,10 @@ cmp go.mod go.mod.tidy # A missing "go" version directive should be added. # However, that should not remove other redundant requirements. +# In fact, it may *add* redundant requirements due to activating lazy loading. cp go.mod.nogo go.mod go list -mod=mod all -cmpenv go.mod go.mod.currentgo +cmpenv go.mod go.mod.addedgo -- go.mod.tidy -- @@ -133,7 +134,7 @@ require ( rsc.io/sampler v1.3.0 // indirect rsc.io/testonly v1.0.0 // indirect ) --- go.mod.currentgo -- +-- go.mod.addedgo -- module m go $goversion @@ -143,3 +144,5 @@ require ( rsc.io/sampler v1.3.0 // indirect rsc.io/testonly v1.0.0 // indirect ) + +require golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect diff --git a/libgo/go/cmd/go/testdata/script/mod_retract.txt b/libgo/go/cmd/go/testdata/script/mod_retract.txt new file mode 100644 index 0000000..4f95ece --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_retract.txt @@ -0,0 +1,45 @@ +cp go.mod go.mod.orig + +# 'go list pkg' does not report an error when a retracted version is used. +go list -e -f '{{if .Error}}{{.Error}}{{end}}' ./use +! stdout . +cmp go.mod go.mod.orig + +# Nor does 'go build'. +[!short] go build ./use +[!short] ! stderr . +[!short] cmp go.mod go.mod.orig + +# Neither 'go list' nor 'go build' should download go.mod from the version +# that would list retractions. +exists $GOPATH/pkg/mod/cache/download/example.com/retract/@v/v1.0.0-bad.mod +! exists $GOPATH/pkg/mod/cache/download/example.com/retract/@v/v1.1.0.mod + +# Importing a package from a module with a retracted latest version will +# select the latest non-retracted version. +go get -d ./use_self_prev +go list -m example.com/retract/self/prev +stdout '^example.com/retract/self/prev v1.1.0$' +exists $GOPATH/pkg/mod/cache/download/example.com/retract/self/prev/@v/v1.9.0.mod + +-- go.mod -- +module example.com/use + +go 1.15 + +require example.com/retract v1.0.0-bad + +-- go.sum -- +example.com/retract v1.0.0-bad h1:liAW69rbtjY67x2CcNzat668L/w+YGgNX3lhJsWIJis= +example.com/retract v1.0.0-bad/go.mod h1:0DvGGofJ9hr1q63cBrOY/jSY52OwhRGA0K47NE80I5Y= +example.com/retract/self/prev v1.1.0 h1:0/8I/GTG+1eJTFeDQ/fUbgrMsVHHyKhh3Z8DSZp1fuA= +example.com/retract/self/prev v1.1.0/go.mod h1:xl2EcklWuZZHVtHWcpzfSJQmnzAGpKZYpA/Wto7SZN4= +-- use/use.go -- +package use + +import _ "example.com/retract" + +-- use_self_prev/use.go -- +package use_self_prev + +import _ "example.com/retract/self/prev" diff --git a/libgo/go/cmd/go/testdata/script/mod_retract_fix_version.txt b/libgo/go/cmd/go/testdata/script/mod_retract_fix_version.txt new file mode 100644 index 0000000..e45758b --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_retract_fix_version.txt @@ -0,0 +1,48 @@ +# retract must not be used without a module directive. +! go list -m all +stderr 'go.mod:3: no module directive found, so retract cannot be used$' + +# Commands that update go.mod should fix non-canonical versions in +# retract directives. +# Verifies #44494. +go mod edit -module=rsc.io/quote/v2 +! go list -m all +stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy$' +go mod tidy +go list -m all +cmp go.mod go.mod.want + +# If a retracted version doesn't match the module's major version suffx, +# an error should be reported. +! go mod edit -retract=v3.0.1 +stderr '^go mod: -retract=v3.0.1: version "v3.0.1" invalid: should be v2, not v3$' +cp go.mod.mismatch-v2 go.mod +! go list -m all +stderr 'go.mod:3: retract rsc.io/quote/v2: version "v3.0.1" invalid: should be v2, not v3$' + +cp go.mod.mismatch-v1 go.mod +! go list -m all +stderr 'go.mod:3: retract rsc.io/quote: version "v3.0.1" invalid: should be v0 or v1, not v3$' + +-- go.mod -- +go 1.16 + +retract latest +-- go.mod.want -- +go 1.16 + +retract v2.0.1 + +module rsc.io/quote/v2 +-- go.mod.mismatch-v2 -- +go 1.16 + +retract v3.0.1 + +module rsc.io/quote/v2 +-- go.mod.mismatch-v1 -- +go 1.16 + +retract v3.0.1 + +module rsc.io/quote diff --git a/libgo/go/cmd/go/testdata/script/mod_retract_incompatible.txt b/libgo/go/cmd/go/testdata/script/mod_retract_incompatible.txt new file mode 100644 index 0000000..61538e8 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_retract_incompatible.txt @@ -0,0 +1,15 @@ +# The current version of a module should not be considered when loading +# retractions. If the current version is +incompatible, we should not prefer +# +incompatible versions when looking for retractions. +# Verifies #42601. + +go mod init m + +# Request a +incompatible version retracted in v1.0.0. +go get -d example.com/retract/incompatible@v2.0.0+incompatible +stderr '^go: warning: example.com/retract/incompatible@v2.0.0\+incompatible: retracted by module author$' + +# We should still see a warning if the +incompatible was previously in the +# build list. +go get -d example.com/retract/incompatible@v2.0.0+incompatible +stderr '^go: warning: example.com/retract/incompatible@v2.0.0\+incompatible: retracted by module author$' diff --git a/libgo/go/cmd/go/testdata/script/mod_retract_pseudo_base.txt b/libgo/go/cmd/go/testdata/script/mod_retract_pseudo_base.txt new file mode 100644 index 0000000..eb00e84 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_retract_pseudo_base.txt @@ -0,0 +1,62 @@ +# When converting a commit to a pseudo-version, don't use a retracted version +# as the base. +# Verifies golang.org/issue/41700. + +[!net] skip +[!exec:git] skip +env GOPROXY=direct +env GOSUMDB=off +go mod init m + +# Control: check that v1.0.0 is the only version and is retracted. +go list -m -versions vcs-test.golang.org/git/retract-pseudo.git +stdout '^vcs-test.golang.org/git/retract-pseudo.git$' +go list -m -versions -retracted vcs-test.golang.org/git/retract-pseudo.git +stdout '^vcs-test.golang.org/git/retract-pseudo.git v1.0.0$' + +# 713affd19d7b is a commit after v1.0.0. Don't use v1.0.0 as the base. +go list -m vcs-test.golang.org/git/retract-pseudo.git@713affd19d7b +stdout '^vcs-test.golang.org/git/retract-pseudo.git v0.0.0-20201009173747-713affd19d7b$' + +# 64c061ed4371 is the commit v1.0.0 refers to. Don't convert to v1.0.0. +go list -m vcs-test.golang.org/git/retract-pseudo.git@64c061ed4371 +stdout '^vcs-test.golang.org/git/retract-pseudo.git v0.0.0-20201009173747-64c061ed4371' + +# A retracted version is a valid base. Retraction should not validate existing +# pseudo-versions, nor should it turn invalid pseudo-versions valid. +go get -d vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-713affd19d7b +go list -m vcs-test.golang.org/git/retract-pseudo.git +stdout '^vcs-test.golang.org/git/retract-pseudo.git v1.0.1-0.20201009173747-713affd19d7b$' + +! go get -d vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-64c061ed4371 +stderr '^go get: vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-64c061ed4371: invalid pseudo-version: tag \(v1.0.0\) found on revision 64c061ed4371 is already canonical, so should not be replaced with a pseudo-version derived from that tag$' + +-- retract-pseudo.sh -- +#!/bin/bash + +# This is not part of the test. +# Run this to generate and update the repository on vcs-test.golang.org. + +set -euo pipefail + +rm -rf retract-pseudo +mkdir retract-pseudo +cd retract-pseudo +git init + +# Create the module. +# Retract v1.0.0 and tag v1.0.0 at the same commit. +# The module has no unretracted release versions. +go mod init vcs-test.golang.org/git/retract-pseudo.git +go mod edit -retract v1.0.0 +echo 'package p' >p.go +git add -A +git commit -m 'create module retract-pseudo' +git tag v1.0.0 + +# Commit a trivial change so the default branch does not point to v1.0.0. +git mv p.go q.go +git commit -m 'trivial change' + +zip -r ../retract-pseudo.zip . +gsutil cp ../retract-pseudo.zip gs://vcs-test/git/retract-pseudo.zip diff --git a/libgo/go/cmd/go/testdata/script/mod_retract_rationale.txt b/libgo/go/cmd/go/testdata/script/mod_retract_rationale.txt new file mode 100644 index 0000000..823c384 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_retract_rationale.txt @@ -0,0 +1,79 @@ +# When there is no rationale, 'go get' should print a hard-coded message. +go get -d example.com/retract/rationale@v1.0.0-empty +stderr '^go: warning: example.com/retract/rationale@v1.0.0-empty: retracted by module author$' + +# 'go list' should print the same hard-coded message. +go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale +stdout '^\[retracted by module author\]$' + + +# When there is a multi-line message, 'go get' should print the first line. +go get -d example.com/retract/rationale@v1.0.0-multiline1 +stderr '^go: warning: example.com/retract/rationale@v1.0.0-multiline1: retracted by module author: short description$' +! stderr 'detail' + +# 'go list' should show the full message. +go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale +cmp stdout multiline + +# 'go get' output should be the same whether the retraction appears at top-level +# or in a block. +go get -d example.com/retract/rationale@v1.0.0-multiline2 +stderr '^go: warning: example.com/retract/rationale@v1.0.0-multiline2: retracted by module author: short description$' +! stderr 'detail' + +# Same for 'go list'. +go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale +cmp stdout multiline + + +# 'go get' should omit long messages. +go get -d example.com/retract/rationale@v1.0.0-long +stderr '^go: warning: example.com/retract/rationale@v1.0.0-long: retracted by module author: \(message omitted: too long\)' + +# 'go list' should show the full message. +go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale +stdout '^\[lo{500}ng\]$' + + +# 'go get' should omit messages with unprintable characters. +go get -d example.com/retract/rationale@v1.0.0-unprintable +stderr '^go: warning: example.com/retract/rationale@v1.0.0-unprintable: retracted by module author: \(message omitted: contains non-printable characters\)' + +# 'go list' should show the full message. +go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale +stdout '^\[Ends with a BEL character. Beep!\x07\]$' + + +# When there is a comment on a block, but not on individual retractions within +# the block, the rationale should come from the block comment. +go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale@v1.0.0-block +stdout '^\[block comment\]$' +go list -m -retracted -f '{{.Retracted}}' example.com/retract/rationale@v1.0.0-blockwithcomment +stdout '^\[inner comment\]$' + + +# When a version is covered by multiple retractions, all retractions should +# be reported in the order they appear in the file. +go list -m -retracted -f '{{range .Retracted}}{{.}},{{end}}' example.com/retract/rationale@v1.0.0-order +stdout '^degenerate range,single version,$' +go list -m -retracted -f '{{range .Retracted}}{{.}},{{end}}' example.com/retract/rationale@v1.0.1-order +stdout '^single version,degenerate range,$' + +# 'go get' will only report the first retraction to avoid being too verbose. +go get -d example.com/retract/rationale@v1.0.0-order +stderr '^go: warning: example.com/retract/rationale@v1.0.0-order: retracted by module author: degenerate range$' +go get -d example.com/retract/rationale@v1.0.1-order +stderr '^go: warning: example.com/retract/rationale@v1.0.1-order: retracted by module author: single version$' + +-- go.mod -- +module m + +go 1.14 + +-- multiline -- +[short description +more + +detail +suffix] diff --git a/libgo/go/cmd/go/testdata/script/mod_retract_rename.txt b/libgo/go/cmd/go/testdata/script/mod_retract_rename.txt new file mode 100644 index 0000000..f54742c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_retract_rename.txt @@ -0,0 +1,28 @@ +# Populate go.sum. +go get -d + +# 'go list -m -retracted' should load retractions, even if the version +# containing retractions has a different module path. +go list -m -retracted -f '{{with .Retracted}}retracted{{end}}' example.com/retract/rename + +# 'go list -m -u' should load retractions, too. +go list -m -u -f '{{with .Retracted}}retracted{{end}}' example.com/retract/rename + +# 'go get' should warn about the retracted version. +go get -d +stderr '^go: warning: example.com/retract/rename@v1.0.0-bad: retracted by module author: bad$' + +# We can't upgrade, since this latest version has a different module path. +! go get -d example.com/retract/rename +stderr 'module declares its path as: example.com/retract/newname' + +-- go.mod -- +module example.com/use + +go 1.16 + +require example.com/retract/rename v1.0.0-bad +-- use.go -- +package use + +import _ "example.com/retract/rename" diff --git a/libgo/go/cmd/go/testdata/script/mod_retract_replace.txt b/libgo/go/cmd/go/testdata/script/mod_retract_replace.txt new file mode 100644 index 0000000..9cd7147 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_retract_replace.txt @@ -0,0 +1,63 @@ +# If the latest unretracted version of a module is replaced, 'go list' should +# obtain retractions from the replacement. + +# Populate go.sum. +go get -d + +# The latest version, v1.9.0, is not available on the proxy. +go list -m -retracted example.com/retract/missingmod +stdout '^example.com/retract/missingmod v1.0.0$' +exists $GOPATH/pkg/mod/cache/download/example.com/retract/missingmod/@v/v1.9.0.info +! exists $GOPATH/pkg/mod/cache/download/example.com/retract/missingmod/@v/v1.9.0.mod + +# If we replace that version, we should see retractions. +go mod edit -replace=example.com/retract/missingmod@v1.9.0=./missingmod-v1.9.0 +go list -m -retracted -f '{{range .Retracted}}{{.}}{{end}}' example.com/retract/missingmod +stdout '^bad version$' + +# If we replace the retracted version, we should not see a retraction. +go mod edit -replace=example.com/retract/missingmod=./missingmod-v1.9.0 +go list -m -retracted -f '{{if not .Retracted}}good version{{end}}' example.com/retract/missingmod +stdout '^good version$' + + +# If a replacement version is retracted, we should see a retraction. +# It should appear in both the replaced module and the replacement, as other +# fields like GoMod do. +go list -m -retracted -f '{{range .Retracted}}{{.}}{{end}}' example.com/retract +! stdout . +go list -m -retracted -f '{{if .Replace}}replaced{{end}}' example.com/retract +! stdout . +go mod edit -replace example.com/retract@v1.0.0-good=example.com/retract@v1.0.0-bad +go list -m -mod=mod -retracted -f '{{range .Retracted}}{{.}}{{end}}' example.com/retract +stdout '^bad$' +go list -m -mod=mod -retracted -f '{{with .Replace}}{{range .Retracted}}{{.}}{{end}}{{end}}' example.com/retract +stdout '^bad$' + +-- go.mod -- +module m + +go 1.14 + +require ( + example.com/retract v1.0.0-good + example.com/retract/missingmod v1.0.0 +) +-- use.go -- +package use + +import ( + _ "example.com/retract" + _ "example.com/retract/missingmod" +) +-- missingmod-v1.0.0/go.mod -- +module example.com/retract/missingmod + +go 1.14 +-- missingmod-v1.9.0/go.mod -- +module example.com/retract/missingmod + +go 1.14 + +// bad version +retract v1.0.0 diff --git a/libgo/go/cmd/go/testdata/script/mod_retract_versions.txt b/libgo/go/cmd/go/testdata/script/mod_retract_versions.txt new file mode 100644 index 0000000..012fa15 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_retract_versions.txt @@ -0,0 +1,22 @@ +# https://golang.org/issue/44296: the --versions flag should not affect +# the version reported by 'go list' in case of retractions. + +env FMT='{{.Path}}{{with .Error}}: {{printf "%q" .Err}}{{end}} {{printf "%q" .Version}}{{with .Versions}} {{.}}{{end}}' + +go list -m -e -f $FMT example.com/retract/self/pseudo +stdout '^example.com/retract/self/pseudo: "module example.com/retract/self/pseudo: not a known dependency" ""$' + +go list -m -e -f $FMT example.com/retract/self/pseudo@latest +stdout '^example.com/retract/self/pseudo: "module example.com/retract/self/pseudo: no matching versions for query \\"latest\\"" "latest"$' + + +go list -m -e -f $FMT --versions example.com/retract/self/pseudo +stdout '^example.com/retract/self/pseudo ""$' + +go list -m -e -f $FMT --versions example.com/retract/self/pseudo@latest +stdout '^example.com/retract/self/pseudo: "module example.com/retract/self/pseudo: no matching versions for query \\"latest\\"" "latest"$' + +-- go.mod -- +module test + +go 1.17 diff --git a/libgo/go/cmd/go/testdata/script/mod_run_nonmain.txt b/libgo/go/cmd/go/testdata/script/mod_run_nonmain.txt new file mode 100644 index 0000000..036755d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_run_nonmain.txt @@ -0,0 +1,18 @@ +! go run $PWD +! stderr 'no packages loaded' +stderr '^package example.net/nonmain is not a main package$' + +! go run . +stderr '^package example.net/nonmain is not a main package$' + +! go run ./... +stderr '^go: warning: "\./\.\.\." matched only non-main packages$' +stderr '^go run: no packages loaded from \./\.\.\.$' + +-- go.mod -- +module example.net/nonmain + +go 1.17 +-- nonmain.go -- +// Package nonmain is not a main package. +package nonmain diff --git a/libgo/go/cmd/go/testdata/script/mod_run_pkg_version.txt b/libgo/go/cmd/go/testdata/script/mod_run_pkg_version.txt new file mode 100644 index 0000000..e921fab --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_run_pkg_version.txt @@ -0,0 +1,103 @@ +# This test checks the behavior of 'go run' with a 'cmd@version' argument. +# Most of 'go run' is covered in other tests. +# mod_install_pkg_version covers most of the package loading functionality. +# This test focuses on 'go run' behavior specific to this mode. +[short] skip + +# 'go run pkg@version' works outside a module. +env GO111MODULE=auto +go run example.com/cmd/a@v1.0.0 +stdout '^a@v1.0.0$' + + +# 'go run pkg@version' reports an error if modules are disabled. +env GO111MODULE=off +! go run example.com/cmd/a@v1.0.0 +stderr '^go: modules disabled by GO111MODULE=off; see ''go help modules''$' +env GO111MODULE=on + + +# 'go run pkg@version' ignores go.mod in the current directory. +cd m +cp go.mod go.mod.orig +! go list -m all +stderr '^go list -m: example.com/cmd@v1.1.0-doesnotexist: missing go.sum entry; to add it:\n\tgo mod download example.com/cmd$' +go run example.com/cmd/a@v1.0.0 +stdout '^a@v1.0.0$' +cmp go.mod go.mod.orig +cd .. + + +# 'go install pkg@version' works on a module that doesn't have a go.mod file +# and with a module whose go.mod file has missing requirements. +# With a proxy, the two cases are indistinguishable. +go run rsc.io/fortune@v1.0.0 +stderr '^go: found rsc.io/quote in rsc.io/quote v1.5.2$' +stderr '^Hello, world.$' + + +# 'go run pkg@version' should report an error if pkg is not a main package. +! go run example.com/cmd/err@v1.0.0 +stderr '^package example.com/cmd/err is not a main package$' + + +# 'go run pkg@version' should report errors if the module contains +# replace or exclude directives. +go mod download example.com/cmd@v1.0.0-replace +! go run example.com/cmd/a@v1.0.0-replace +cmp stderr replace-err + +go mod download example.com/cmd@v1.0.0-exclude +! go run example.com/cmd/a@v1.0.0-exclude +cmp stderr exclude-err + + +# 'go run dir@version' works like a normal 'go run' command if +# dir is a relative or absolute path. +go mod download rsc.io/fortune@v1.0.0 +! go run $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0 +stderr '^go: go\.mod file not found in current directory or any parent directory; see ''go help modules''$' +! go run ../pkg/mod/rsc.io/fortune@v1.0.0 +stderr '^go: go\.mod file not found in current directory or any parent directory; see ''go help modules''$' +mkdir tmp +cd tmp +go mod init tmp +go mod edit -require=rsc.io/fortune@v1.0.0 +! go run -mod=readonly $GOPATH/pkg/mod/rsc.io/fortune@v1.0.0 +stderr '^missing go\.sum entry for module providing package rsc\.io/fortune; to add:\n\tgo mod download rsc\.io/fortune$' +! go run -mod=readonly ../../pkg/mod/rsc.io/fortune@v1.0.0 +stderr '^missing go\.sum entry for module providing package rsc\.io/fortune; to add:\n\tgo mod download rsc\.io/fortune$' +cd .. +rm tmp + + +# 'go run' does not interpret @version arguments after the first. +go run example.com/cmd/a@v1.0.0 example.com/doesnotexist@v1.0.0 +stdout '^a@v1.0.0$' + + +# 'go run pkg@version' succeeds when -mod=readonly is set explicitly. +# Verifies #43278. +go run -mod=readonly example.com/cmd/a@v1.0.0 +stdout '^a@v1.0.0$' + +-- m/go.mod -- +module m + +go 1.16 + +require example.com/cmd v1.1.0-doesnotexist +-- x/x.go -- +package main + +func main() {} +-- replace-err -- +go run: example.com/cmd/a@v1.0.0-replace (in example.com/cmd@v1.0.0-replace): + The go.mod file for the module providing named packages contains one or + more replace directives. It must not contain directives that would cause + it to be interpreted differently than if it were the main module. +-- exclude-err -- +go run: example.com/cmd/a@v1.0.0-exclude (in example.com/cmd@v1.0.0-exclude): + The go.mod file for the module providing named packages contains one or + more exclude directives. It must not contain directives that would cause + it to be interpreted differently than if it were the main module. diff --git a/libgo/go/cmd/go/testdata/script/mod_run_pkgerror.txt b/libgo/go/cmd/go/testdata/script/mod_run_pkgerror.txt new file mode 100644 index 0000000..48f900d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_run_pkgerror.txt @@ -0,0 +1,32 @@ +# https://golang.org/issue/39986: files reported as invalid by go/build should +# be listed in InvalidGoFiles. + +go list -e -f '{{.Incomplete}}{{"\n"}}{{.Error}}{{"\n"}}{{.InvalidGoFiles}}{{"\n"}}' . +stdout '^true\nfound packages m \(m\.go\) and main \(main\.go\) in '$PWD'\n\[main.go\]\n' + + +# https://golang.org/issue/45827: 'go run .' should report the same package +# errors as 'go build' and 'go list'. + +! go build +stderr '^found packages m \(m\.go\) and main \(main\.go\) in '$PWD'$' + +! go list . +stderr '^found packages m \(m\.go\) and main \(main\.go\) in '$PWD'$' + +! go run . +! stderr 'no packages loaded' +stderr '^found packages m \(m\.go\) and main \(main\.go\) in '$PWD'$' + +! go run ./... +! stderr 'no packages loaded' +stderr '^found packages m \(m\.go\) and main \(main\.go\) in '$PWD'$' + +-- go.mod -- +module m + +go 1.17 +-- m.go -- +package m +-- main.go -- +package main diff --git a/libgo/go/cmd/go/testdata/script/mod_std_vendor.txt b/libgo/go/cmd/go/testdata/script/mod_std_vendor.txt index fb954d7..c3cde52 100644 --- a/libgo/go/cmd/go/testdata/script/mod_std_vendor.txt +++ b/libgo/go/cmd/go/testdata/script/mod_std_vendor.txt @@ -36,11 +36,11 @@ stderr 'use of vendored package' # When run within the 'std' module, 'go list -test' should report vendored -# transitive dependencies at their original module paths. +# transitive dependencies at their vendored paths. cd $GOROOT/src go list -test -f '{{range .Deps}}{{.}}{{"\n"}}{{end}}' net/http -stdout ^golang.org/x/net/http2/hpack -! stdout ^vendor/golang.org/x/net/http2/hpack +! stdout ^golang.org/x/net/http2/hpack +stdout ^vendor/golang.org/x/net/http2/hpack -- go.mod -- module m diff --git a/libgo/go/cmd/go/testdata/script/mod_sum_ambiguous.txt b/libgo/go/cmd/go/testdata/script/mod_sum_ambiguous.txt new file mode 100644 index 0000000..07c6659 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_sum_ambiguous.txt @@ -0,0 +1,62 @@ +# Confirm our build list. +cp go.sum.buildlist-only go.sum +go list -m all +stdout '^example.com/ambiguous/a v1.0.0$' +stdout '^example.com/ambiguous/a/b v0.0.0-empty$' + +# If two modules could provide a package, but only one does, +# 'go mod tidy' should retain sums for both zips. +go mod tidy +grep '^example.com/ambiguous/a v1.0.0 h1:' go.sum +grep '^example.com/ambiguous/a/b v0.0.0-empty h1:' go.sum + +# 'go mod download' should also add sums. +cp go.sum.buildlist-only go.sum +go mod download example.com/ambiguous/a +grep '^example.com/ambiguous/a v1.0.0 h1:' go.sum +! grep '^example.com/ambiguous/a/b v0.0.0-empty h1:' go.sum +go mod download example.com/ambiguous/a/b +grep '^example.com/ambiguous/a/b v0.0.0-empty h1:' go.sum + +# If two modules could provide a package, and we're missing a sum for one, +# we should see a missing sum error, even if we have a sum for a module that +# provides the package. +cp go.sum.a-only go.sum +! go list example.com/ambiguous/a/b +stderr '^missing go.sum entry needed to verify package example.com/ambiguous/a/b is provided by exactly one module; to add:\n\tgo mod download example.com/ambiguous/a/b$' +! go list -deps . +stderr '^use.go:3:8: missing go.sum entry needed to verify package example.com/ambiguous/a/b \(imported by m\) is provided by exactly one module; to add:\n\tgo get m$' + +cp go.sum.b-only go.sum +! go list example.com/ambiguous/a/b +stderr '^missing go.sum entry for module providing package example.com/ambiguous/a/b; to add:\n\tgo mod download example.com/ambiguous/a$' +! go list -deps . +stderr '^use.go:3:8: missing go.sum entry for module providing package example.com/ambiguous/a/b \(imported by m\); to add:\n\tgo get m$' + +cp go.sum.buildlist-only go.sum +! go list example.com/ambiguous/a/b +stderr '^missing go.sum entry for module providing package example.com/ambiguous/a/b; to add:\n\tgo mod download example.com/ambiguous/a example.com/ambiguous/a/b$' +! go list -deps . +stderr '^use.go:3:8: missing go.sum entry for module providing package example.com/ambiguous/a/b \(imported by m\); to add:\n\tgo get m$' + +-- go.mod -- +module m + +go 1.15 + +require example.com/ambiguous/a v1.0.0 +-- go.sum.buildlist-only -- +example.com/ambiguous/a v1.0.0/go.mod h1:TrBl/3xTPFJ2gmMIYz53h2gkNtg0dokszEMuyS1QEb0= +example.com/ambiguous/a/b v0.0.0-empty/go.mod h1:MajJq5jPEBnnXP+NTWIeXX7kwaPS1sbVEJdooTmsePQ= +-- go.sum.a-only -- +example.com/ambiguous/a v1.0.0 h1:pGZhTXy6+titE2rNfwHwJykSjXDR4plO52PfZrBM0T8= +example.com/ambiguous/a v1.0.0/go.mod h1:TrBl/3xTPFJ2gmMIYz53h2gkNtg0dokszEMuyS1QEb0= +example.com/ambiguous/a/b v0.0.0-empty/go.mod h1:MajJq5jPEBnnXP+NTWIeXX7kwaPS1sbVEJdooTmsePQ= +-- go.sum.b-only -- +example.com/ambiguous/a v1.0.0/go.mod h1:TrBl/3xTPFJ2gmMIYz53h2gkNtg0dokszEMuyS1QEb0= +example.com/ambiguous/a/b v0.0.0-empty h1:xS29ReXXuhjT7jc79mo91h/PevaZ2oS9PciF1DucXtg= +example.com/ambiguous/a/b v0.0.0-empty/go.mod h1:MajJq5jPEBnnXP+NTWIeXX7kwaPS1sbVEJdooTmsePQ= +-- use.go -- +package use + +import _ "example.com/ambiguous/a/b" diff --git a/libgo/go/cmd/go/testdata/script/mod_sum_lookup.txt b/libgo/go/cmd/go/testdata/script/mod_sum_lookup.txt new file mode 100644 index 0000000..e021921 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_sum_lookup.txt @@ -0,0 +1,34 @@ +# When we attempt to resolve an import that doesn't exist, we should not save +# hashes for downloaded modules. +# Verifies golang.org/issue/36260. +# TODO(golang.org/issue/26603): use 'go mod tidy -e' when implemented. +go list -e -mod=mod -tags=ignore ./noexist +! exists go.sum + +# When an import is resolved successfully, we should only save hashes for +# the module that provides the package, not for other modules looked up. +# Verifies golang.org/issue/31580. +go get -d ./exist +grep '^example.com/join v1.1.0 h1:' go.sum +! grep '^example.com/join/subpkg' go.sum +cp go.sum go.list.sum +go mod tidy +cmp go.sum go.list.sum + +-- go.mod -- +module m + +go 1.15 + +-- noexist/use.go -- +// ignore tags prevents errors in 'go mod tidy' +// +build ignore + +package use + +import _ "example.com/join/subpkg/noexist" + +-- exist/use.go -- +package use + +import _ "example.com/join/subpkg" diff --git a/libgo/go/cmd/go/testdata/script/mod_sum_readonly.txt b/libgo/go/cmd/go/testdata/script/mod_sum_readonly.txt new file mode 100644 index 0000000..113f13e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_sum_readonly.txt @@ -0,0 +1,87 @@ +# Test that go.sum does not get updated when -mod=readonly flag is set +env GO111MODULE=on + +# When a sum is needed to load the build list, we get an error for the +# specific module. The .mod file is not downloaded, and go.sum is not written. +! go list -m all +stderr '^go list -m: rsc.io/quote@v1.5.2: missing go.sum entry; to add it:\n\tgo mod download rsc.io/quote$' +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod +! exists go.sum + +# If go.sum exists but contains hashes from an algorithm we don't know about, +# we should see the same error. +cp go.sum.h2only go.sum +! go list -m all +stderr '^go list -m: rsc.io/quote@v1.5.2: missing go.sum entry; to add it:\n\tgo mod download rsc.io/quote$' +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod +cmp go.sum go.sum.h2only +rm go.sum + +# If we replace a module, we should see a missing sum error for the replacement. +cp go.mod go.mod.orig +go mod edit -replace rsc.io/quote@v1.5.2=rsc.io/quote@v1.5.1 +! go list -m all +stderr '^go list -m: rsc.io/quote@v1.5.2 \(replaced by rsc.io/quote@v1.5.1\): missing go.sum entry; to add it:\n\tgo mod download rsc.io/quote$' +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.1.mod +! exists go.sum +cp go.mod.orig go.mod + +# Control: when sums are present, loading the build list downloads .mod files. +cp go.sum.buildlistonly go.sum +go list -m all +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod + + +# When a sum is needed to load a .mod file for a package outside the build list, +# we get a generic missing import error. +! go list example.com/doesnotexist +stderr '^no required module provides package example.com/doesnotexist; to add it:\n\tgo get example.com/doesnotexist$' + +# When a sum is needed to load a .zip file, we get a more specific error. +# The .zip file is not downloaded. +! go list rsc.io/quote +stderr '^missing go.sum entry for module providing package rsc.io/quote; to add:\n\tgo mod download rsc.io/quote$' +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip + +# The error is attached to the package from the missing module. We can load +# a package that imports it without that error. +go list -e -deps -f '{{.ImportPath}}{{with .Error}} {{.Err}}{{end}}' . +stdout '^m$' +stdout '^rsc.io/quote missing go.sum entry for module providing package rsc.io/quote \(imported by m\); to add:\n\tgo get m$' +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip + +# go.sum should not have been written. +cmp go.sum go.sum.buildlistonly + +# Control: when sums are present, 'go list' downloads .zip files. +cp go.sum.tidy go.sum +go list . +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip + +-- go.mod -- +module m + +go 1.15 + +require rsc.io/quote v1.5.2 +-- use.go -- +package use + +import _ "rsc.io/quote" +-- go.sum.h2only -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h2:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.2/go.mod h2:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0/go.mod h2:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +-- go.sum.buildlistonly -- +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= +-- go.sum.tidy -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64= +rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY= diff --git a/libgo/go/cmd/go/testdata/script/mod_sumdb.txt b/libgo/go/cmd/go/testdata/script/mod_sumdb.txt index 9a688e1..fa3483c 100644 --- a/libgo/go/cmd/go/testdata/script/mod_sumdb.txt +++ b/libgo/go/cmd/go/testdata/script/mod_sumdb.txt @@ -37,3 +37,9 @@ go get -d rsc.io/fortune -- go.mod.orig -- module m + +go 1.16 +-- m.go -- +package m + +import _ "rsc.io/quote" diff --git a/libgo/go/cmd/go/testdata/script/mod_sumdb_cache.txt b/libgo/go/cmd/go/testdata/script/mod_sumdb_cache.txt index 2937b2e..1b38475 100644 --- a/libgo/go/cmd/go/testdata/script/mod_sumdb_cache.txt +++ b/libgo/go/cmd/go/testdata/script/mod_sumdb_cache.txt @@ -43,12 +43,5 @@ env GOPROXY=$proxy/sumdb-504 ! go get -d rsc.io/quote@v1.5.2 stderr 504 -# but -insecure bypasses the checksum lookup entirely -env GOINSECURE= -go get -d -insecure rsc.io/quote@v1.5.2 - -# and then it is in go.sum again -go get -d rsc.io/quote@v1.5.2 - -- go.mod.orig -- module m diff --git a/libgo/go/cmd/go/testdata/script/mod_sumdb_golang.txt b/libgo/go/cmd/go/testdata/script/mod_sumdb_golang.txt index cc0b0da..becd88b 100644 --- a/libgo/go/cmd/go/testdata/script/mod_sumdb_golang.txt +++ b/libgo/go/cmd/go/testdata/script/mod_sumdb_golang.txt @@ -10,45 +10,73 @@ go env GOSUMDB stdout '^sum.golang.org$' # Download direct from github. + [!net] skip [!exec:git] skip env GOSUMDB=sum.golang.org env GOPROXY=direct + go get -d rsc.io/quote@v1.5.2 cp go.sum saved.sum + # Download from proxy.golang.org with go.sum entry already. # Use 'go list' instead of 'go get' since the latter may download extra go.mod # files not listed in go.sum. + go clean -modcache env GOSUMDB= env GOPROXY= -go list -x -deps rsc.io/quote + +go list -x -m all # Download go.mod files. ! stderr github stderr proxy.golang.org/rsc.io/quote ! stderr sum.golang.org/tile ! stderr sum.golang.org/lookup/rsc.io/quote + +go list -x -deps rsc.io/quote # Download module source. +! stderr github +stderr proxy.golang.org/rsc.io/quote +! stderr sum.golang.org/tile +! stderr sum.golang.org/lookup/rsc.io/quote + cmp go.sum saved.sum + # Download again. # Should use the checksum database to validate new go.sum lines, # but not need to fetch any new data from the proxy. + rm go.sum -go list -mod=mod -x rsc.io/quote + +go list -mod=mod -x -m all # Add checksums for go.mod files. +stderr sum.golang.org/tile ! stderr github ! stderr proxy.golang.org/rsc.io/quote -stderr sum.golang.org/tile stderr sum.golang.org/lookup/rsc.io/quote + +go list -mod=mod -x rsc.io/quote # Add checksums for module source. +! stderr . # Adds checksums, but for entities already in the module cache. + cmp go.sum saved.sum + # test fallback to direct + env TESTGOPROXY404=1 go clean -modcache rm go.sum -go list -mod=mod -x rsc.io/quote + +go list -mod=mod -x -m all # Download go.mod files +stderr 'proxy.golang.org.*404 testing' +stderr github.com/rsc + +go list -mod=mod -x rsc.io/quote # Download module source. stderr 'proxy.golang.org.*404 testing' stderr github.com/rsc + cmp go.sum saved.sum + -- go.mod -- module m diff --git a/libgo/go/cmd/go/testdata/script/mod_symlink_dotgo.txt b/libgo/go/cmd/go/testdata/script/mod_symlink_dotgo.txt new file mode 100644 index 0000000..d4cc143 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_symlink_dotgo.txt @@ -0,0 +1,17 @@ +env GO111MODULE=on +[!symlink] skip + +symlink dir.go -> dir + +# Issue #39841: symlinks to directories should be ignored, not treated as source files. +go list -f '{{range .GoFiles}}{{.}}{{"\n"}}{{end}}' . +stdout 'p\.go$' +! stdout 'dir\.go$' + +-- go.mod -- +module example.com +go 1.15 +-- p.go -- +package p +-- dir/README.txt -- +This file exists to ensure that dir is a directory. diff --git a/libgo/go/cmd/go/testdata/script/mod_tagged_import_cycle.txt b/libgo/go/cmd/go/testdata/script/mod_tagged_import_cycle.txt new file mode 100644 index 0000000..0491acb --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tagged_import_cycle.txt @@ -0,0 +1,106 @@ +# Because 'go mod' subcommands ignore build constraints, they can encounter +# package-import cycles that are not possible in an ordinary build. This test +# verifies that such cycles are handled even when they cross module boundaries. + +# First, verify that the import graph depends on build tags as expected. +go list -deps example.com/left +stdout '^example.com/right$' +go list -deps example.com/right +! stdout left + +env GOFLAGS=-tags=mirror +go list -deps example.com/left +! stdout right +go list -deps example.com/right +stdout '^example.com/left$' +env GOFLAGS='' + +# 'go mod why' should be agnostic to build tags. +go mod why example.com/left +stdout '^example.com/chiral$\n^example.com/left$' +go mod why example.com/right +stdout '^example.com/chiral$\n^example.com/right$' + +env GOFLAGS='-tags=mirror' +go mod why example.com/left +stdout '^example.com/chiral$\n^example.com/left$' +go mod why example.com/right +stdout '^example.com/chiral$\n^example.com/right$' +env GOFLAGS='' + +# 'go mod tidy' should successfully handle the cycle. +env GOFLAGS=-mod=readonly +go mod tidy + +# 'go mod vendor' should copy in both packages without crashing. +go mod vendor +exists vendor/example.com/left/default.go +exists vendor/example.com/left/mirror.go +exists vendor/example.com/right/default.go +exists vendor/example.com/right/mirror.go + +-- go.mod -- +module example.com/chiral + +go 1.14 + +require ( + example.com/left v0.1.0 + example.com/right v0.1.0 +) + +replace ( + example.com/left => ./left + example.com/right => ./right +) +-- chiral.go -- +// Package chiral imports packages in an order that depends on build tags. +package chiral +-- default.go -- +// +build !mirror + +package chiral + +import _ "example.com/left" +-- mirror.go -- +// +build mirror + +package chiral + +import _ "example.com/right" +-- left/go.mod -- +module example.com/left + +go 1.14 + +require example.com/right v0.1.0 + +replace example.com/right v0.1.0 => ../right +-- left/default.go -- +// +build !mirror + +package left + +import _ "example.com/right" +-- left/mirror.go -- +// +build mirror + +package left +-- right/go.mod -- +module example.com/right + +go 1.14 + +require example.com/left v0.1.0 + +replace example.com/left v0.1.0 => ../left +-- right/default.go -- +// +build !mirror + +package right +-- right/mirror.go -- +// +build mirror + +package right + +import _ "example.com/left" diff --git a/libgo/go/cmd/go/testdata/script/mod_test.txt b/libgo/go/cmd/go/testdata/script/mod_test.txt index 50f0035..76f1d7a 100644 --- a/libgo/go/cmd/go/testdata/script/mod_test.txt +++ b/libgo/go/cmd/go/testdata/script/mod_test.txt @@ -60,6 +60,8 @@ go list -test -- a/go.mod.empty -- module example.com/user/a +go 1.11 + -- a/a.go -- package a diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_compat.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_compat.txt new file mode 100644 index 0000000..e6edef5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_compat.txt @@ -0,0 +1,95 @@ +# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by +# default preserve enough checksums for the module to be used by Go 1.16. +# +# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the +# 'go' version in the go.mod file to 1.16, without actually updating the +# requirements to match. + +[short] skip + +env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}' + + +# This module has the same module dependency graph in Go 1.16 as in Go 1.17, +# but in 1.16 requires (checksums for) additional (irrelevant) go.mod files. +# +# The module graph under both versions looks like: +# +# m ---- example.com/version v1.1.0 +# | +# + ---- example.net/lazy v0.1.0 ---- example.com/version v1.0.1 +# +# Go 1.17 avoids loading the go.mod file for example.com/version v1.0.1 +# (because it is lower than the verison explicitly required by m, +# and the module that requires it — m — specifies 'go 1.17'). +# +# That go.mod file happens not to affect the final 1.16 module graph anyway, +# so the pruned graph is equivalent to the unpruned one. + +cp go.mod go.mod.orig +go mod tidy +cmp go.mod go.mod.orig + +go list -m all +cmp stdout m_all.txt + +go mod edit -go=1.16 +go list -m all +cmp stdout m_all.txt + + +# If we explicitly drop compatibility with 1.16, we retain fewer checksums, +# which gives a cleaner go.sum file but causes 1.16 to fail in readonly mode. + +cp go.mod.orig go.mod +go mod tidy -compat=1.17 +cmp go.mod go.mod.orig + +go list -m all +cmp stdout m_all.txt + +go mod edit -go=1.16 +! go list -m all +stderr '^go list -m: example.net/lazy@v0.1.0 requires\n\texample.com/version@v1.0.1: missing go.sum entry; to add it:\n\tgo mod download example.com/version$' + + +-- go.mod -- +// Module m happens to have the exact same build list as what would be +// selected under Go 1.16, but computes that build list without looking at +// as many go.mod files. +module example.com/m + +go 1.17 + +replace example.net/lazy v0.1.0 => ./lazy + +require ( + example.com/version v1.1.0 + example.net/lazy v0.1.0 +) +-- m_all.txt -- +example.com/m +example.com/version v1.1.0 +example.net/lazy v0.1.0 => ./lazy +-- compatible.go -- +package compatible + +import ( + _ "example.com/version" + _ "example.net/lazy" +) +-- lazy/go.mod -- +// Module lazy requires example.com/version v1.0.1. +// +// However, since this module is lazy, its dependents +// should not need checksums for that version of the module +// unless they actually import packages from it. +module example.net/lazy + +go 1.17 + +require example.com/version v1.0.1 +-- lazy/lazy.go -- +package lazy + +import _ "example.com/version" diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_compat_added.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_added.txt new file mode 100644 index 0000000..94fa79b --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_added.txt @@ -0,0 +1,105 @@ +# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by +# default preserve enough checksums for the module to be used by Go 1.16. +# +# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the +# 'go' version in the go.mod file to 1.16, without actually updating the +# requirements to match. + +[short] skip + +env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}' + + +# For this module, Go 1.17 produces an error for one module, and Go 1.16 +# produces a different error for a different module. + +cp go.mod go.mod.orig + +! go mod tidy + +stderr '^example\.com/m imports\n\texample\.net/added: module example\.net/added@latest found \(v0\.3\.0, replaced by \./a1\), but does not contain package example\.net/added$' + +cmp go.mod go.mod.orig + + +# When we run 'go mod tidy -e', we should proceed past the first error and follow +# it with a second error describing the version descrepancy. +# +# We should not provide advice on how to push past the version descrepancy, +# because the '-e' flag should already do that, writing out an otherwise-tidied +# go.mod file. + +go mod tidy -e + +stderr '^example\.com/m imports\n\texample\.net/added: module example\.net/added@latest found \(v0\.3\.0, replaced by \./a1\), but does not contain package example\.net/added\nexample\.net/added failed to load from any module,\n\tbut go 1\.16 would load it from example\.net/added@v0\.2\.0$' + +! stderr '\n\tgo mod tidy' + +cmp go.mod go.mod.tidy + + +-- go.mod -- +module example.com/m + +go 1.17 + +replace ( + example.net/added v0.1.0 => ./a1 + example.net/added v0.2.0 => ./a2 + example.net/added v0.3.0 => ./a1 + example.net/lazy v0.1.0 => ./lazy + example.net/pruned v0.1.0 => ./pruned +) + +require ( + example.net/added v0.1.0 + example.net/lazy v0.1.0 +) +-- go.mod.tidy -- +module example.com/m + +go 1.17 + +replace ( + example.net/added v0.1.0 => ./a1 + example.net/added v0.2.0 => ./a2 + example.net/added v0.3.0 => ./a1 + example.net/lazy v0.1.0 => ./lazy + example.net/pruned v0.1.0 => ./pruned +) + +require example.net/lazy v0.1.0 +-- m.go -- +package m + +import ( + _ "example.net/added" + _ "example.net/lazy" +) + +-- a1/go.mod -- +module example.net/added + +go 1.17 +-- a2/go.mod -- +module example.net/added + +go 1.17 +-- a2/added.go -- +package added + +-- lazy/go.mod -- +module example.net/lazy + +go 1.17 + +require example.net/pruned v0.1.0 +-- lazy/lazy.go -- +package lazy + +-- pruned/go.mod -- +module example.net/pruned + +go 1.17 + +require example.net/added v0.2.0 diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt new file mode 100644 index 0000000..c544cb7 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt @@ -0,0 +1,98 @@ +# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by +# default preserve enough checksums for the module to be used by Go 1.16. +# +# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the +# 'go' version in the go.mod file to 1.16, without actually updating the +# requirements to match. + +[short] skip + +env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}' + +# For this module, the dependency providing package +# example.net/ambiguous/nested/pkg is unambiguous in Go 1.17 (because only one +# root of the module graph contains the package), whereas it is ambiguous in +# Go 1.16 (because two different modules contain plausible packages and Go 1.16 +# does not privilege roots above other dependencies). +# +# However, the overall build list is identical for both versions. + +cp go.mod go.mod.orig + +! go mod tidy + +stderr '^example\.com/m imports\n\texample\.net/indirect imports\n\texample\.net/ambiguous/nested/pkg loaded from example\.net/ambiguous/nested@v0\.1\.0,\n\tbut go 1.16 would fail to locate it:\n\tambiguous import: found package example\.net/ambiguous/nested/pkg in multiple modules:\n\texample\.net/ambiguous v0.1.0 \(.*\)\n\texample\.net/ambiguous/nested v0.1.0 \(.*\)\n\n' + +stderr '\n\nTo proceed despite packages unresolved in go 1\.16:\n\tgo mod tidy -e\nIf reproducibility with go 1.16 is not needed:\n\tgo mod tidy -compat=1\.17\nFor other options, see:\n\thttps://golang\.org/doc/modules/pruning\n' + +cmp go.mod go.mod.orig + + +# If we run 'go mod tidy -e', we should still save enough checksums to run +# 'go list -m all' reproducibly with go 1.16, even though we can't list +# the specific package. + +go mod tidy -e +! stderr '\n\tgo mod tidy' +cmp go.mod go.mod.orig + +go list -m all +cmp stdout all-m.txt + +go list -f $MODFMT example.net/ambiguous/nested/pkg +stdout '^example.net/ambiguous/nested v0\.1\.0$' +! stderr . + +go mod edit -go=1.16 +go list -m all +cmp stdout all-m.txt + +! go list -f $MODFMT example.net/ambiguous/nested/pkg +stderr '^ambiguous import: found package example\.net/ambiguous/nested/pkg in multiple modules:\n\texample\.net/ambiguous v0\.1\.0 \(.*\)\n\texample\.net/ambiguous/nested v0\.1\.0 \(.*\)\n' + + +# On the other hand, if we use -compat=1.17, 1.16 can't even load +# the build list (due to missing checksums). + +cp go.mod.orig go.mod +go mod tidy -compat=1.17 +! stderr . +go list -m all +cmp stdout all-m.txt + +go mod edit -go=1.16 +! go list -m all +stderr '^go list -m: example\.net/indirect@v0\.1\.0 requires\n\texample\.net/ambiguous@v0\.1\.0: missing go\.sum entry; to add it:\n\tgo mod download example\.net/ambiguous\n' + + +-- go.mod -- +module example.com/m + +go 1.17 + +replace example.net/indirect v0.1.0 => ./indirect + +require ( + example.net/ambiguous/nested v0.1.0 // indirect + example.net/indirect v0.1.0 +) +-- all-m.txt -- +example.com/m +example.net/ambiguous v0.1.0 +example.net/ambiguous/nested v0.1.0 +example.net/indirect v0.1.0 => ./indirect +-- m.go -- +package m + +import _ "example.net/indirect" + +-- indirect/go.mod -- +module example.net/indirect + +go 1.17 + +require example.net/ambiguous v0.1.0 +-- indirect/indirect.go -- +package indirect + +import _ "example.net/ambiguous/nested/pkg" diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_compat_deleted.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_deleted.txt new file mode 100644 index 0000000..dcf13e2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_deleted.txt @@ -0,0 +1,128 @@ +# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by +# default preserve enough checksums for the module to be used by Go 1.16. +# +# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the +# 'go' version in the go.mod file to 1.16, without actually updating the +# requirements to match. + +[short] skip + +env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}' + + +# For this module, the "deleted" dependency contains an imported package, but +# Go 1.16 selects a higher version (in which that package has been deleted). + +cp go.mod go.mod.orig + +! go mod tidy + +stderr '^example\.com/m imports\n\texample\.net/deleted loaded from example\.net/deleted@v0\.1\.0,\n\tbut go 1\.16 would fail to locate it in example\.net/deleted@v0\.2\.0\n\n' + +stderr '\n\nTo upgrade to the versions selected by go 1.16, leaving some packages unresolved:\n\tgo mod tidy -e -go=1\.16 && go mod tidy -e -go=1\.17\nIf reproducibility with go 1.16 is not needed:\n\tgo mod tidy -compat=1\.17\nFor other options, see:\n\thttps://golang\.org/doc/modules/pruning\n' + + +# The suggested 'go mod tidy -e' command should proceed anyway. + +go mod tidy -e +cmp go.mod go.mod.tidy + + +# In 'go 1.16' mode we should error out in the way we claimed. + +cd 116-outside +! go list -deps -f $MODFMT example.com/m +stderr '^\.\.[/\\]m\.go:4:2: no required module provides package example\.net/deleted; to add it:\n\tgo get example\.net/deleted$' +cd .. + +go mod edit -go=1.16 +! go list -deps -f $MODFMT example.com/m +stderr '^go: updates to go\.mod needed; to update it:\n\tgo mod tidy$' + +! go mod tidy +stderr '^example\.com/m imports\n\texample\.net/deleted: module example\.net/deleted@latest found \(v0\.2\.0, replaced by \./d2\), but does not contain package example\.net/deleted$' + + +-- go.mod -- +module example.com/m + +go 1.17 + +replace ( + example.net/deleted v0.1.0 => ./d1 + example.net/deleted v0.2.0 => ./d2 + example.net/lazy v0.1.0 => ./lazy + example.net/pruned v0.1.0 => ./pruned +) + +require ( + example.net/deleted v0.1.0 + example.net/deleted v0.1.0 // redundant + example.net/lazy v0.1.0 +) +-- go.mod.tidy -- +module example.com/m + +go 1.17 + +replace ( + example.net/deleted v0.1.0 => ./d1 + example.net/deleted v0.2.0 => ./d2 + example.net/lazy v0.1.0 => ./lazy + example.net/pruned v0.1.0 => ./pruned +) + +require ( + example.net/deleted v0.1.0 + example.net/lazy v0.1.0 +) +-- 116-outside/go.mod -- +module outside + +go 1.16 + +replace ( + example.com/m => ../ + example.net/deleted v0.1.0 => ../d1 + example.net/deleted v0.2.0 => ../d2 + example.net/lazy v0.1.0 => ../lazy + example.net/pruned v0.1.0 => ../pruned +) + +require example.com/m v0.1.0 +-- m.go -- +package m + +import ( + _ "example.net/deleted" + _ "example.net/lazy" +) + +-- d1/go.mod -- +module example.net/deleted + +go 1.17 +-- d1/deleted.go -- +package deleted +-- d2/go.mod -- +module example.net/deleted + +go 1.17 +-- d2/README -- +There is no longer a Go package here. + +-- lazy/go.mod -- +module example.net/lazy + +go 1.17 + +require example.net/pruned v0.1.0 +-- lazy/lazy.go -- +package lazy + +-- pruned/go.mod -- +module example.net/pruned + +go 1.17 + +require example.net/deleted v0.2.0 diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_compat_implicit.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_implicit.txt new file mode 100644 index 0000000..186a3f8 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_implicit.txt @@ -0,0 +1,129 @@ +# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by +# default preserve enough checksums for the module to be used by Go 1.16. +# +# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the +# 'go' version in the go.mod file to 1.16, without actually updating the +# requirements to match. + +[short] skip + +env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}' + + +# For this module, Go 1.16 selects the same versions of all explicit dependencies +# as Go 1.17 does. However, Go 1.16 selects a higher version of an *implicit* +# dependency, imported by a test of one of the (external) imported packages. +# As a result, Go 1.16 also needs checksums for the module sources for that higher +# version. +# +# The Go 1.16 module graph looks like: +# +# m ---- lazy v0.1.0 ---- incompatible v1.0.0 +# | +# + ------------- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible +# +# The Go 1.17 module graph is the same except that the dependencies of +# requireincompatible are pruned out (because the module that requires +# it — lazy v0.1.0 — specifies 'go 1.17', and it is not otherwise relevant to +# the main module). + +# 'go mod tidy' should by default diagnose the difference in dependencies as an +# error, with useful suggestions about how to resolve it. + +cp go.mod go.mod.orig +! go mod tidy +stderr '^example\.com/m imports\n\texample\.net/lazy tested by\n\texample\.net/lazy.test imports\n\texample\.com/retract/incompatible loaded from example\.com/retract/incompatible@v1\.0\.0,\n\tbut go 1\.16 would select v2\.0\.0\+incompatible\n\n' +stderr '\n\nTo upgrade to the versions selected by go 1\.16:\n\tgo mod tidy -go=1\.16 && go mod tidy -go=1\.17\nIf reproducibility with go 1.16 is not needed:\n\tgo mod tidy -compat=1.17\nFor other options, see:\n\thttps://golang\.org/doc/modules/pruning\n' + +cmp go.mod go.mod.orig + +# The suggested '-compat' flag to ignore differences should silence the error +# and leave go.mod unchanged, resulting in checksum errors when Go 1.16 tries +# to load a module pruned out by Go 1.17. + +go mod tidy -compat=1.17 +! stderr . +cmp go.mod go.mod.orig + +go list -deps -test -f $MODFMT all +stdout '^example\.com/retract/incompatible v1\.0\.0$' + +go mod edit -go=1.16 +! go list -deps -test -f $MODFMT all + + # TODO(#46160): -count=1 instead of -count=2. +stderr -count=2 '^go: example\.net/lazy@v0\.1\.0 requires\n\texample\.com/retract/incompatible@v1\.0\.0: missing go\.sum entry; to add it:\n\tgo mod download example\.com/retract/incompatible$' + + +# If we combine a Go 1.16 go.sum file... +go mod tidy -go=1.16 + +# ...with a Go 1.17 go.mod file... +cp go.mod.orig go.mod + +# ...then Go 1.17 no longer works. 😞 +! go list -deps -test -f $MODFMT all +stderr -count=1 '^can''t load test package: lazy[/\\]lazy_test.go:3:8: missing go\.sum entry for module providing package example\.com/retract/incompatible \(imported by example\.net/lazy\); to add:\n\tgo get -t example.net/lazy@v0\.1\.0$' + + +# However, if we take the union of the go.sum files... +go list -mod=mod -deps -test all +cmp go.mod go.mod.orig + +# ...then Go 1.17 continues to work... +go list -deps -test -f $MODFMT all +stdout '^example\.com/retract/incompatible v1\.0\.0$' + +# ...and 1.16 also works(‽), but selects a different version for the +# external-test dependency. +go mod edit -go=1.16 +go list -deps -test -f $MODFMT all +stdout '^example\.com/retract/incompatible v2\.0\.0\+incompatible$' + + +-- go.mod -- +// Module m imports packages from the same versions under Go 1.17 +// as under Go 1.16, but under 1.16 its (implicit) external test dependencies +// are higher. +module example.com/m + +go 1.17 + +replace ( + example.net/lazy v0.1.0 => ./lazy + example.net/requireincompatible v0.1.0 => ./requireincompatible +) + +require example.net/lazy v0.1.0 +-- implicit.go -- +package implicit + +import _ "example.net/lazy" +-- lazy/go.mod -- +// Module lazy requires example.com/retract/incompatible v1.0.0. +// +// When viewed from the outside it also has a transitive dependency +// on v2.0.0+incompatible, but in lazy mode that transitive dependency +// is pruned out. +module example.net/lazy + +go 1.17 + +exclude example.com/retract/incompatible v2.0.0+incompatible + +require ( + example.com/retract/incompatible v1.0.0 + example.net/requireincompatible v0.1.0 +) +-- lazy/lazy.go -- +package lazy +-- lazy/lazy_test.go -- +package lazy_test + +import _ "example.com/retract/incompatible" +-- requireincompatible/go.mod -- +module example.net/requireincompatible + +go 1.15 + +require example.com/retract/incompatible v2.0.0+incompatible diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt new file mode 100644 index 0000000..ea9e42e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt @@ -0,0 +1,135 @@ +# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by +# default preserve enough checksums for the module to be used by Go 1.16. +# +# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the +# 'go' version in the go.mod file to 1.16, without actually updating the +# requirements to match. + +[short] skip + +env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}' + + +# For this module, Go 1.17 prunes out a (transitive and otherwise-irrelevant) +# requirement on a retracted higher version of a dependency. +# However, when Go 1.16 reads the same requirements from the go.mod file, +# it does not prune out that requirement, and selects the retracted version. +# +# The Go 1.16 module graph looks like: +# +# m ---- lazy v0.1.0 ---- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible +# | | +# + -------+------------- incompatible v1.0.0 +# +# The Go 1.17 module graph is the same except that the dependencies of +# requireincompatible are pruned out (because the module that requires +# it — lazy v0.1.0 — specifies 'go 1.17', and it is not otherwise relevant to +# the main module). + + +# 'go mod tidy' should by default diagnose the difference in dependencies as an +# error, with useful suggestions about how to resolve it. + +cp go.mod go.mod.orig +! go mod tidy +stderr '^example\.com/m imports\n\texample\.net/lazy imports\n\texample\.com/retract/incompatible loaded from example\.com/retract/incompatible@v1\.0\.0,\n\tbut go 1\.16 would select v2\.0\.0\+incompatible\n\n' +stderr '\n\nTo upgrade to the versions selected by go 1\.16:\n\tgo mod tidy -go=1\.16 && go mod tidy -go=1\.17\nIf reproducibility with go 1\.16 is not needed:\n\tgo mod tidy -compat=1.17\nFor other options, see:\n\thttps://golang\.org/doc/modules/pruning\n' + +cmp go.mod go.mod.orig + + +# The suggested '-compat' flag to ignore differences should silence the error +# and leave go.mod unchanged, resulting in checksum errors when Go 1.16 tries +# to load a module pruned out by Go 1.17. + +go mod tidy -compat=1.17 +! stderr . +cmp go.mod go.mod.orig + +go mod edit -go=1.16 +! go list -f $MODFMT -deps ./... + # TODO(#46160): -count=1 instead of -count=2. +stderr -count=2 '^go: example\.net/lazy@v0\.1\.0 requires\n\texample\.net/requireincompatible@v0\.1\.0 requires\n\texample\.com/retract/incompatible@v2\.0\.0\+incompatible: missing go.sum entry; to add it:\n\tgo mod download example.com/retract/incompatible$' + + +# There are two ways for the module author to bring the two into alignment. +# One is to *explicitly* 'exclude' the version that is already *implicitly* +# pruned out under 1.17. + +go mod edit -exclude=example.com/retract/incompatible@v2.0.0+incompatible +go list -f $MODFMT -deps ./... +stdout '^example.com/retract/incompatible v1\.0\.0$' +! stdout 'v2\.0\.0' + + +# The other is to explicitly upgrade the version required under Go 1.17 +# to match the version selected by Go 1.16. The commands suggested by +# 'go mod tidy' should do exactly that. + +cp go.mod.orig go.mod + +go mod tidy -go=1.16 +go list -f $MODFMT -deps ./... +stdout '^example.com/retract/incompatible v2\.0\.0\+incompatible$' +! stdout 'v1\.0\.0' + +go mod tidy -go=1.17 +go list -f $MODFMT -deps ./... +stdout '^example.com/retract/incompatible v2\.0\.0\+incompatible$' +! stdout 'v1\.0\.0' + +go mod edit -go=1.16 +go list -f $MODFMT -deps ./... +stdout '^example.com/retract/incompatible v2\.0\.0\+incompatible$' +! stdout 'v1\.0\.0' + + +-- go.mod -- +// Module m indirectly imports a package from +// example.com/retract/incompatible. Its selected version of +// that module is lower under Go 1.17 semantics than under Go 1.16. +module example.com/m + +go 1.17 + +replace ( + example.net/lazy v0.1.0 => ./lazy + example.net/requireincompatible v0.1.0 => ./requireincompatible +) + +require ( + example.com/retract/incompatible v1.0.0 // indirect + example.net/lazy v0.1.0 +) +-- incompatible.go -- +package incompatible + +import _ "example.net/lazy" + +-- lazy/go.mod -- +// Module lazy requires example.com/retract/incompatible v1.0.0. +// +// When viewed from the outside it also has a transitive dependency +// on v2.0.0+incompatible, but in lazy mode that transitive dependency +// is pruned out. +module example.net/lazy + +go 1.17 + +exclude example.com/retract/incompatible v2.0.0+incompatible + +require ( + example.com/retract/incompatible v1.0.0 + example.net/requireincompatible v0.1.0 +) +-- lazy/lazy.go -- +package lazy + +import _ "example.com/retract/incompatible" + +-- requireincompatible/go.mod -- +module example.net/requireincompatible + +go 1.15 + +require example.com/retract/incompatible v2.0.0+incompatible diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_compat_irrelevant.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_irrelevant.txt new file mode 100644 index 0000000..7c22fca --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_compat_irrelevant.txt @@ -0,0 +1,99 @@ +# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by +# default preserve enough checksums for the module to be used by Go 1.16. +# +# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the +# 'go' version in the go.mod file to 1.16, without actually updating the +# requirements to match. + +[short] skip + +env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}' + + +# This module selects the same versions in Go 1.16 and 1.17 for all modules +# that provide packages (or test dependencies of packages) imported by the +# main module. However, in Go 1.16 it selects a higher version of a +# transitive module dependency that is not otherwise relevant to the main module. +# As a result, Go 1.16 needs an additional checksum for the go.mod file of +# that irrelevant dependency. +# +# The Go 1.16 module graph looks like: +# +# m ---- lazy v0.1.0 ---- incompatible v1.0.0 +# | +# + ------------- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible + +cp go.mod go.mod.orig +go mod tidy +cmp go.mod go.mod.orig + +go list -deps -test -f $MODFMT all +cp stdout out-117.txt + +go mod edit -go=1.16 +go list -deps -test -f $MODFMT all +cmp stdout out-117.txt + + +# If we explicitly drop compatibility with 1.16, we retain fewer checksums, +# which gives a cleaner go.sum file but causes 1.16 to fail in readonly mode. + +cp go.mod.orig go.mod +go mod tidy -compat=1.17 +cmp go.mod go.mod.orig + +go list -deps -test -f $MODFMT all +cmp stdout out-117.txt + +go mod edit -go=1.16 +! go list -deps -test -f $MODFMT all + # TODO(#46160): -count=1 instead of -count=2. +stderr -count=2 '^go: example.net/lazy@v0.1.0 requires\n\texample.com/retract/incompatible@v1.0.0: missing go.sum entry; to add it:\n\tgo mod download example.com/retract/incompatible$' + + +-- go.mod -- +// Module m imports packages from the same versions under Go 1.17 +// as under Go 1.16, but under 1.16 its (implicit) external test dependencies +// are higher. +module example.com/m + +go 1.17 + +replace ( + example.net/lazy v0.1.0 => ./lazy + example.net/requireincompatible v0.1.0 => ./requireincompatible +) + +require example.net/lazy v0.1.0 +-- m.go -- +package m + +import _ "example.net/lazy" +-- lazy/go.mod -- +// Module lazy requires example.com/retract/incompatible v1.0.0. +// +// When viewed from the outside it also has a transitive dependency +// on v2.0.0+incompatible, but in lazy mode that transitive dependency +// is pruned out. +module example.net/lazy + +go 1.17 + +exclude example.com/retract/incompatible v2.0.0+incompatible + +require ( + example.com/retract/incompatible v1.0.0 + example.net/requireincompatible v0.1.0 +) +-- lazy/lazy.go -- +package lazy +-- lazy/unimported/unimported.go -- +package unimported + +import _ "example.com/retract/incompatible" +-- requireincompatible/go.mod -- +module example.net/requireincompatible + +go 1.15 + +require example.com/retract/incompatible v2.0.0+incompatible diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_convergence.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_convergence.txt new file mode 100644 index 0000000..09c46f7 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_convergence.txt @@ -0,0 +1,202 @@ +# This test demonstrates a simple case in which 'go mod tidy' may resolve a +# missing package, only to remove that package when resolving its dependencies. +# +# If we naively iterate 'go mod tidy' until the dependency graph converges, this +# scenario may fail to converge. + +# The import graph used in this test looks like: +# +# m --- x +# | +# x_test --- y +# +# The module dependency graph of m is initially empty. +# Modules x and y look like: +# +# x.1 (provides package x that imports y, but does not depend on module y) +# +# x.2-pre (no dependencies, but does not provide package x) +# +# y.1 (no dependencies, but provides package y) +# +# y.2 --- x.2-pre (provides package y) +# +# +# When we resolve the missing import of y in x_test, we add y@latest — which is +# y.2, not y.1 — as a new dependency. That upgrades to x to x.2-pre, which +# removes package x (and also the need for module y). We can then safely remove +# the dependency on module y, because nothing imports package y any more! +# +# We might be tempted to remove the dependency on module x for the same reason: +# it no longer provides any imported package. However, that would cause 'go mod +# tidy -e' to become unstable: with x.2-pre out of the way, we could once again +# resolve the missing import of package x by re-adding x.1. + +cp go.mod go.mod.orig + +# 'go mod tidy' without -e should fail without modifying go.mod, +# because it cannot resolve x and y simultaneously. +! go mod tidy + +cmp go.mod go.mod.orig + +stderr '^go: found example\.net/y in example\.net/y v0.2.0$' +stderr '^go: finding module for package example\.net/x$' + + # TODO: This error message should be clearer — it doesn't indicate why v0.2.0-pre is required. +stderr '^example\.net/m imports\n\texample\.net/x: package example\.net/x provided by example\.net/x at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$' + + +# 'go mod tidy -e' should follow upgrades to try to resolve the modules that it +# can, and then stop. When we resolve example.net/y, we upgrade to example.net/x +# to v0.2.0-pre. At that version, package x no longer exists and no longer +# imports package y, so the import of x should be left unsatisfied and the +# existing dependency on example.net/x removed. +# +# TODO(bcmills): It would be ever better if we could keep the original +# dependency on example.net/x v0.1.0, but I don't see a way to do that without +# making the algorithm way too complicated. (We would have to detect that the +# new dependency on example.net/y interferes with the package that caused us to +# to add that dependency in the first place, and back out that part of the change +# without also backing out any other needed changes.) + +go mod tidy -e +cmp go.mod go.mod.tidye +stderr '^go: found example\.net/y in example\.net/y v0.2.0$' + + # TODO: This error message should be clearer — it doesn't indicate why v0.2.0-pre is required. +stderr '^example\.net/m imports\n\texample\.net/x: package example\.net/x provided by example\.net/x at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$' + + +# Since we attempt to resolve the dependencies of package x whenever we add x itself, +# this end state is stable. + +go mod tidy -e +cmp go.mod go.mod.tidye + + +# An explicit 'go get' with the correct versions should allow 'go mod tidy' to +# succeed and remain stable. y.1 does not upgrade x, and can therefore be used +# with it. + +go get -d example.net/x@v0.1.0 example.net/y@v0.1.0 +go mod tidy +cmp go.mod go.mod.postget + + +# The 'tidy' logic for a lazy main module is somewhat different from that for an +# eager main module, but the overall behavior is the same. + +cp go.mod.orig go.mod +go mod edit -go=1.17 go.mod +go mod edit -go=1.17 go.mod.tidye + +go mod tidy -e +cmp go.mod go.mod.tidye +stderr '^go: found example\.net/y in example\.net/y v0.2.0$' +stderr '^example\.net/m imports\n\texample\.net/x: package example\.net/x provided by example\.net/x at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$' + +go get -d example.net/x@v0.1.0 example.net/y@v0.1.0 +go mod tidy +cmp go.mod go.mod.postget-117 + + +-- go.mod -- +module example.net/m + +go 1.16 + +replace ( + example.net/x v0.1.0 => ./x1 + example.net/x v0.2.0-pre => ./x2-pre + example.net/y v0.1.0 => ./y1 + example.net/y v0.2.0 => ./y2 +) + +require ( + example.net/x v0.1.0 +) +-- go.mod.tidye -- +module example.net/m + +go 1.16 + +replace ( + example.net/x v0.1.0 => ./x1 + example.net/x v0.2.0-pre => ./x2-pre + example.net/y v0.1.0 => ./y1 + example.net/y v0.2.0 => ./y2 +) +-- go.mod.postget -- +module example.net/m + +go 1.16 + +replace ( + example.net/x v0.1.0 => ./x1 + example.net/x v0.2.0-pre => ./x2-pre + example.net/y v0.1.0 => ./y1 + example.net/y v0.2.0 => ./y2 +) + +require ( + example.net/x v0.1.0 + example.net/y v0.1.0 // indirect +) +-- go.mod.postget-117 -- +module example.net/m + +go 1.17 + +replace ( + example.net/x v0.1.0 => ./x1 + example.net/x v0.2.0-pre => ./x2-pre + example.net/y v0.1.0 => ./y1 + example.net/y v0.2.0 => ./y2 +) + +require example.net/x v0.1.0 + +require example.net/y v0.1.0 // indirect +-- m.go -- +package m + +import _ "example.net/x" + +-- x1/go.mod -- +module example.net/x + +go 1.16 +-- x1/x.go -- +package x +-- x1/x_test.go -- +package x + +import _ "example.net/y" + +-- x2-pre/go.mod -- +module example.net/x + +go 1.16 +-- x2-pre/README.txt -- +There is no package x here. Use example.com/x/subpkg instead. +-- x2-pre/subpkg/subpkg.go -- +package subpkg // import "example.net/x/subpkg" + +-- y1/go.mod -- +module example.net/y + +go 1.16 +-- y1/y.go -- +package y + +-- y2/go.mod -- +module example.net/y + +go 1.16 + +require example.net/x v0.2.0-pre +-- y2/y.go -- +package y + +import _ "example.net/x/subpkg" diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_convergence_loop.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_convergence_loop.txt new file mode 100644 index 0000000..3c4d324 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_convergence_loop.txt @@ -0,0 +1,329 @@ +# This test demonstrates a simple case in which 'go mod tidy' may resolve a +# missing package, only to remove that package when resolving its dependencies. +# +# If we naively iterate 'go mod tidy' until the dependency graph converges, this +# scenario may fail to converge. + +# The import graph used in this test looks like: +# +# m --- w +# | +# + --- x +# | +# + --- y +# | +# + --- z +# +# The module dependency graph of m initially contains w.1 (and, by extension, +# y.2-pre and z.2-pre). This is an arbitrary point in the cycle of possible +# configurations. +# +# w.1 requires y.2-pre and z.2-pre +# x.1 requires z.2-pre and w.2-pre +# y.1 requires w.2-pre and x.2-pre +# z.1 requires x.2-pre and y.2-pre +# +# At each point, exactly one missing package can be resolved by adding a +# dependency on the .1 release of the module that provides that package. +# However, adding that dependency causes the module providing another package to +# roll over from its .1 release to its .2-pre release, which removes the +# package. Once the package is removed, 'go mod tidy -e' no longer sees the +# module as relevant to the main module, and will happily remove the existing +# dependency on it. +# +# The cycle is of length 4 so that at every step only one package can be +# resolved. This is important because it prevents the iteration from ever +# reaching a state in which every package is simultaneously over-upgraded — such +# a state is stable and does not exhibit failure to converge. + +cp go.mod go.mod.orig + +# 'go mod tidy' without -e should fail without modifying go.mod, +# because it cannot resolve x, y, and z simultaneously. +! go mod tidy + +cmp go.mod go.mod.orig + +stderr '^go: finding module for package example\.net/w$' +stderr '^go: finding module for package example\.net/x$' +stderr -count=2 '^go: finding module for package example\.net/y$' +stderr -count=2 '^go: finding module for package example\.net/z$' +stderr '^go: found example\.net/x in example\.net/x v0.1.0$' + + # TODO: These error messages should be clearer — it doesn't indicate why v0.2.0-pre is required. +stderr '^example\.net/m imports\n\texample\.net/w: package example\.net/w provided by example\.net/w at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$' +stderr '^example\.net/m imports\n\texample\.net/y: package example\.net/y provided by example\.net/y at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$' +stderr '^example\.net/m imports\n\texample\.net/z: package example\.net/z provided by example\.net/z at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$' + + +# 'go mod tidy -e' should preserve all of the upgrades to modules that could +# provide the missing packages but don't. That would at least explain why they +# are missing, and why no individual module can be upgraded in order to satisfy +# a missing import. +# +# TODO(bcmills): Today, it doesn't preserve those upgrades, and instead advances +# the state by one through the cycle of semi-tidy states. + +go mod tidy -e + +cmp go.mod go.mod.tidye1 + +stderr '^go: finding module for package example\.net/w$' +stderr '^go: finding module for package example\.net/x$' +stderr -count=2 '^go: finding module for package example\.net/y$' +stderr -count=2 '^go: finding module for package example\.net/z$' +stderr '^go: found example\.net/x in example\.net/x v0.1.0$' + +stderr '^example\.net/m imports\n\texample\.net/w: package example\.net/w provided by example\.net/w at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$' +stderr '^example\.net/m imports\n\texample\.net/y: package example\.net/y provided by example\.net/y at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$' +stderr '^example\.net/m imports\n\texample\.net/z: package example\.net/z provided by example\.net/z at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$' + + +go mod tidy -e +cmp go.mod go.mod.tidye2 + +go mod tidy -e +cmp go.mod go.mod.tidye3 + +go mod tidy -e +cmp go.mod go.mod.orig + + +# If we upgrade away all of the packages simultaneously, the resulting tidy +# state converges at "no dependencies", because simultaneously adding all of the +# packages simultaneously over-upgrades all of the dependencies, and 'go mod +# tidy' treats "no package can be added" as a terminal state. + +go get -d example.net/w@v0.2.0-pre example.net/x@v0.2.0-pre example.net/y@v0.2.0-pre example.net/z@v0.2.0-pre +go mod tidy -e +cmp go.mod go.mod.postget +go mod tidy -e +cmp go.mod go.mod.postget + + +# The 'tidy' logic for a lazy main module requires more iterations to converge, +# because it is willing to drop dependencies on non-root modules that do not +# otherwise provide imported packages. +# +# On the first iteration, it adds x.1 as a root, which upgrades z and w, +# dropping w.1's requirement on y. w.1 was initially a root, so the upgraded +# w.2-pre is retained as a root. +# +# On the second iteration, it adds y.1 as a root, which upgrades w and x, +# dropping x.1's requirement on z. x.1 was added as a root in the previous step, +# so the upgraded x.2-pre is retained as a root. +# +# On the third iteration, it adds z.1 as a root, which upgrades x and y. +# x and y were already roots (from the previous steps), so their upgraded versions +# are retained (not dropped) and the iteration stops. +# +# At that point, we have z.1 as a root providing package z, +# and w, x, and y have all been upgraded to no longer provide any packages. +# So only z is retained as a new root. +# +# (From the above, we can see that in a lazy module we still cycle through the +# same possible root states, but in a different order from the eager case.) +# +# TODO(bcmills): if we retained the upgrades on w, x, and y (since they are +# lexical prefixes for unresolved packages w, x, and y, respectively), then 'go +# mod tidy -e' itself would become stable and no longer cycle through states. + +cp go.mod.orig go.mod +go mod edit -go=1.17 go.mod +cp go.mod go.mod.117 +go mod edit -go=1.17 go.mod.tidye1 +go mod edit -go=1.17 go.mod.tidye2 +go mod edit -go=1.17 go.mod.tidye3 +go mod edit -go=1.17 go.mod.postget + +go list -m all + +go mod tidy -e +cmp go.mod go.mod.tidye3 + +go mod tidy -e +cmp go.mod go.mod.tidye2 + +go mod tidy -e +cmp go.mod go.mod.tidye1 + +go mod tidy -e +cmp go.mod go.mod.117 + + +# As in the eager case, for the lazy module the fully-upgraded dependency graph +# becomes empty, and the empty graph is stable. + +go get -d example.net/w@v0.2.0-pre example.net/x@v0.2.0-pre example.net/y@v0.2.0-pre example.net/z@v0.2.0-pre +go mod tidy -e +cmp go.mod go.mod.postget +go mod tidy -e +cmp go.mod go.mod.postget + + +-- m.go -- +package m + +import ( + _ "example.net/w" + _ "example.net/x" + _ "example.net/y" + _ "example.net/z" +) + +-- go.mod -- +module example.net/m + +go 1.16 + +replace ( + example.net/w v0.1.0 => ./w1 + example.net/w v0.2.0-pre => ./w2-pre + example.net/x v0.1.0 => ./x1 + example.net/x v0.2.0-pre => ./x2-pre + example.net/y v0.1.0 => ./y1 + example.net/y v0.2.0-pre => ./y2-pre + example.net/z v0.1.0 => ./z1 + example.net/z v0.2.0-pre => ./z2-pre +) + +require example.net/w v0.1.0 +-- go.mod.tidye1 -- +module example.net/m + +go 1.16 + +replace ( + example.net/w v0.1.0 => ./w1 + example.net/w v0.2.0-pre => ./w2-pre + example.net/x v0.1.0 => ./x1 + example.net/x v0.2.0-pre => ./x2-pre + example.net/y v0.1.0 => ./y1 + example.net/y v0.2.0-pre => ./y2-pre + example.net/z v0.1.0 => ./z1 + example.net/z v0.2.0-pre => ./z2-pre +) + +require example.net/x v0.1.0 +-- go.mod.tidye2 -- +module example.net/m + +go 1.16 + +replace ( + example.net/w v0.1.0 => ./w1 + example.net/w v0.2.0-pre => ./w2-pre + example.net/x v0.1.0 => ./x1 + example.net/x v0.2.0-pre => ./x2-pre + example.net/y v0.1.0 => ./y1 + example.net/y v0.2.0-pre => ./y2-pre + example.net/z v0.1.0 => ./z1 + example.net/z v0.2.0-pre => ./z2-pre +) + +require example.net/y v0.1.0 +-- go.mod.tidye3 -- +module example.net/m + +go 1.16 + +replace ( + example.net/w v0.1.0 => ./w1 + example.net/w v0.2.0-pre => ./w2-pre + example.net/x v0.1.0 => ./x1 + example.net/x v0.2.0-pre => ./x2-pre + example.net/y v0.1.0 => ./y1 + example.net/y v0.2.0-pre => ./y2-pre + example.net/z v0.1.0 => ./z1 + example.net/z v0.2.0-pre => ./z2-pre +) + +require example.net/z v0.1.0 +-- go.mod.postget -- +module example.net/m + +go 1.16 + +replace ( + example.net/w v0.1.0 => ./w1 + example.net/w v0.2.0-pre => ./w2-pre + example.net/x v0.1.0 => ./x1 + example.net/x v0.2.0-pre => ./x2-pre + example.net/y v0.1.0 => ./y1 + example.net/y v0.2.0-pre => ./y2-pre + example.net/z v0.1.0 => ./z1 + example.net/z v0.2.0-pre => ./z2-pre +) +-- w1/go.mod -- +module example.net/w + +go 1.16 + +require ( + example.net/y v0.2.0-pre + example.net/z v0.2.0-pre +) +-- w1/w.go -- +package w +-- w2-pre/go.mod -- +module example.net/w + +go 1.16 +-- w2-pre/README.txt -- +Package w has been removed. + +-- x1/go.mod -- +module example.net/x + +go 1.16 + +require ( + example.net/z v0.2.0-pre + example.net/w v0.2.0-pre +) +-- x1/x.go -- +package x +-- x2-pre/go.mod -- +module example.net/x + +go 1.16 +-- x2-pre/README.txt -- +Package x has been removed. + +-- y1/go.mod -- +module example.net/y + +go 1.16 + +require ( + example.net/w v0.2.0-pre + example.net/x v0.2.0-pre +) +-- y1/y.go -- +package y + +-- y2-pre/go.mod -- +module example.net/y + +go 1.16 +-- y2-pre/README.txt -- +Package y has been removed. + +-- z1/go.mod -- +module example.net/z + +go 1.16 + +require ( + example.net/x v0.2.0-pre + example.net/y v0.2.0-pre +) +-- z1/z.go -- +package z + +-- z2-pre/go.mod -- +module example.net/z + +go 1.16 +-- z2-pre/README.txt -- +Package z has been removed. diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_indirect.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_indirect.txt new file mode 100644 index 0000000..1f092b2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_indirect.txt @@ -0,0 +1,67 @@ +cp go.mod go.mod.orig +go mod tidy +cmp go.mod go.mod.orig + +-- go.mod -- +module example.com/tidy + +go 1.16 + +require ( + example.net/incomplete v0.1.0 + example.net/indirect v0.2.0 // indirect + example.net/toolow v0.1.0 +) + +replace ( + example.net/incomplete v0.1.0 => ./incomplete + example.net/indirect v0.1.0 => ./indirect.1 + example.net/indirect v0.2.0 => ./indirect.2 + example.net/toolow v0.1.0 => ./toolow +) +-- tidy.go -- +package tidy + +import ( + _ "example.net/incomplete" + _ "example.net/toolow" +) + +-- incomplete/go.mod -- +module example.net/incomplete + +go 1.16 + +// This module omits a needed requirement on example.net/indirect. +-- incomplete/incomplete.go -- +package incomplete + +import _ "example.net/indirect/newpkg" + +-- toolow/go.mod -- +module example.net/toolow + +go 1.16 + +require example.net/indirect v0.1.0 +-- toolow/toolow.go -- +package toolow + +import _ "example.net/indirect/oldpkg" + +-- indirect.1/go.mod -- +module example.net/indirect + +go 1.16 +-- indirect.1/oldpkg/oldpkg.go -- +package oldpkg + + +-- indirect.2/go.mod -- +module example.net/indirect + +go 1.16 +-- indirect.2/oldpkg/oldpkg.go -- +package oldpkg +-- indirect.2/newpkg/newpkg.go -- +package newpkg diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_lazy_self.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_lazy_self.txt new file mode 100644 index 0000000..ffcea18 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_lazy_self.txt @@ -0,0 +1,71 @@ +# Regression test for https://golang.org/issue/46078: +# 'go mod tidy' should not panic if the main module initially +# requires an older version of itself. + + +# A module that explicitly requires an older version of itself should be +# rejected as inconsistent: we enforce that every explicit requirement is the +# selected version of its module path, but the selected version of the main +# module is always itself — not some explicit version. + +! go list -m all +stderr '^go: updates to go\.mod needed; to update it:\n\tgo mod tidy$' + + +# The suggested 'go mod tidy' command should succeed (not crash). + +go mod tidy + + +# We prune out redundant roots very early on in module loading, and at that +# point the indirect requirement on example.net/x v0.1.0 appears to be +# irrelevant. It should be pruned out; when the import of "example.net/x" is +# later resolved, it should resolve at the latest version (v0.2.0), not the +# version implied by the (former) misleading requirement on the older version of +# the main module. + +cmp go.mod go.mod.tidy + + +-- go.mod -- +module golang.org/issue/46078 + +go 1.17 + +replace ( + example.net/x v0.1.0 => ./x + example.net/x v0.2.0 => ./x + golang.org/issue/46078 v0.1.0 => ./old +) + +require golang.org/issue/46078 v0.1.0 +-- go.mod.tidy -- +module golang.org/issue/46078 + +go 1.17 + +replace ( + example.net/x v0.1.0 => ./x + example.net/x v0.2.0 => ./x + golang.org/issue/46078 v0.1.0 => ./old +) + +require example.net/x v0.2.0 +-- issue46078/issue.go -- +package issue46078 + +import _ "example.net/x" + +-- old/go.mod -- +module golang.org/issue/46078 + +go 1.17 + +require example.net/x v0.1.0 + +-- x/go.mod -- +module example.net/x + +go 1.17 +-- x/x.go -- +package x diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_newroot.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_newroot.txt new file mode 100644 index 0000000..3abd5ef --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_newroot.txt @@ -0,0 +1,82 @@ +# https://golang.org/issue/45952: 'go mod tidy' in an eager module failed due +# to an erroneous check on root completeness. +# +# Per the issue report: +# > It may have to do with: +# > +# > package A imports package B in go.mod, which imports package C in its own go.mod +# > package A drops direct dependency on package B … +# +# We infer from that that package C is still needed by some other indirect +# dependency, and must be at a higher version than what is required by that +# dependency (or else no new root would be needed). An additional package D +# in its own module satisfies that condition, reproducing the bug. + +go mod tidy +cmp go.mod go.mod.tidy + +-- go.mod -- +module example.net/a + +go 1.16 + +require ( + example.net/b v0.1.0 + example.net/d v0.1.0 +) + +replace ( + example.net/b v0.1.0 => ./b + example.net/c v0.1.0 => ./c + example.net/c v0.2.0 => ./c + example.net/d v0.1.0 => ./d +) +-- go.mod.tidy -- +module example.net/a + +go 1.16 + +require ( + example.net/c v0.2.0 // indirect + example.net/d v0.1.0 +) + +replace ( + example.net/b v0.1.0 => ./b + example.net/c v0.1.0 => ./c + example.net/c v0.2.0 => ./c + example.net/d v0.1.0 => ./d +) +-- a.go -- +package a + +import _ "example.net/d" + +-- b/go.mod -- +module example.net/b + +go 1.16 + +require example.net/c v0.2.0 +-- b/b.go -- +package b + +import _ "example.net/c" + +-- c/go.mod -- +module example.net/c + +go 1.16 +-- c/c.go -- +package c + +-- d/go.mod -- +module example.net/d + +go 1.16 + +require example.net/c v0.1.0 +-- d/d.go -- +package d + +import _ "example.net/c" diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_old.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_old.txt new file mode 100644 index 0000000..7428f0c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_old.txt @@ -0,0 +1,46 @@ +# 'go mod tidy' should remove content sums for module versions that aren't +# in the build list. It should preserve go.mod sums for module versions that +# are in the module graph though. +# Verifies golang.org/issue/33008. +go mod tidy +! grep '^rsc.io/quote v1.5.0 h1:' go.sum +grep '^rsc.io/quote v1.5.0/go.mod h1:' go.sum + +-- go.mod -- +module m + +go 1.15 + +require ( + rsc.io/quote v1.5.2 + example.com/r v0.0.0 +) + +replace example.com/r => ./r + +-- go.sum -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.0 h1:6fJa6E+wGadANKkUMlZ0DhXFpoKlslOQDCo259XtdIE= +rsc.io/quote v1.5.0/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64= +rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY= + +-- r/go.mod -- +module example.com/r + +require rsc.io/quote v1.5.0 + +-- use.go -- +package use + +import _ "example.com/r" + +-- r/use.go -- +package use + +import _ "rsc.io/quote" diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_oldgo.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_oldgo.txt new file mode 100644 index 0000000..0e88b06 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_oldgo.txt @@ -0,0 +1,21 @@ +# Modules were introduced in Go 1.11, but for various reasons users may +# decide to declare a (much!) older go version in their go.mod file. +# Modules with very old versions should not be rejected, and should have +# the same module-graph semantics as in Go 1.11. + +cp go.mod go.mod.orig +go mod tidy +cmp go.mod go.mod.orig + +-- go.mod -- +module example.com/legacy/go1 + +go 1.0 + +require golang.org/x/text v0.3.0 +-- main.go -- +package main + +import _ "golang.org/x/text/language" + +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_replace.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_replace.txt index dd99438..297f6a6 100644 --- a/libgo/go/cmd/go/testdata/script/mod_tidy_replace.txt +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_replace.txt @@ -136,3 +136,10 @@ require ( ) replace not-rsc.io/quote/v3 => rsc.io/quote/v3 v3.0.0 +-- multiple-paths/use.go -- +package quoter + +import ( + _ "not-rsc.io/quote/v3" + _ "rsc.io/quote/v3" +) diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_replace_old.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_replace_old.txt new file mode 100644 index 0000000..cfd3792 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_replace_old.txt @@ -0,0 +1,34 @@ +# Regression test for https://golang.org/issue/46659. +# +# If a 'replace' directive specifies an older-than-selected version of a module, +# 'go mod tidy' shouldn't try to add that version to the build list to resolve a +# missing package: it won't be selected, and would cause the module loader to +# loop indefinitely trying to resolve the package. + +cp go.mod go.mod.orig + +! go mod tidy +! stderr panic +stderr '^golang\.org/issue46659 imports\n\texample\.com/missingpkg/deprecated: package example\.com/missingpkg/deprecated provided by example\.com/missingpkg at latest version v1\.0\.0 but not at required version v1\.0\.1-beta$' + +go mod tidy -e + +cmp go.mod go.mod.orig + +-- go.mod -- +module golang.org/issue46659 + +go 1.17 + +replace example.com/missingpkg v1.0.1-alpha => example.com/missingpkg v1.0.0 + +require example.com/usemissingpre v1.0.0 + +require example.com/missingpkg v1.0.1-beta // indirect +-- m.go -- +package m + +import ( + _ "example.com/missingpkg/deprecated" + _ "example.com/usemissingpre" +) diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_symlink_issue35941.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_symlink_issue35941.txt new file mode 100644 index 0000000..d4658c6 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_symlink_issue35941.txt @@ -0,0 +1,36 @@ +env GO111MODULE=on +[!symlink] skip + +cd m +symlink symlink -> ../outside + +cp go.mod go.mod.orig + +# Issue 35941: suppress symlink warnings when running 'go mod tidy'. +# 'go mod tidy' should not scan packages in symlinked subdirectories. +go mod tidy +! stderr 'warning: ignoring symlink' +cmp go.mod go.mod.orig + +! go build ./symlink +stderr '^symlink[\\/]symlink.go:3:8: module example.net/unresolved provides package example.net/unresolved and is replaced but not required; to add it:\n\tgo get example.net/unresolved@v0.1.0$' + +-- m/go.mod -- +module example.net/m + +go 1.16 + +replace example.net/unresolved v0.1.0 => ../unresolved +-- m/a.go -- +package a +-- outside/symlink.go -- +package symlink + +import _ "example.net/unresolved" +-- unresolved/go.mod -- +module example.net/unresolved + +go 1.16 +-- unresolved/unresolved.go -- +// Package unresolved exists, but 'go mod tidy' won't add it. +package unresolved diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_too_new.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_too_new.txt new file mode 100644 index 0000000..b9c53b5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_too_new.txt @@ -0,0 +1,57 @@ +# https://golang.org/issue/46142: 'go mod tidy' should error out if the version +# in the go.mod file is newer than the most recent supported version. + +cp go.mod go.mod.orig + + +# If the go.mod file specifies an unsupported Go version, 'go mod tidy' should +# refuse to edit it: we don't know what a tidy go.mod file for that version +# would look like. + +! go mod tidy +stderr 'go mod tidy: go.mod file indicates go 2000.0, but maximum supported version is '$goversion'$' +cmp go.mod go.mod.orig + + +# The -e flag should push past the error and edit the file anyway, +# but preserve the too-high version. + +cp go.mod.orig go.mod +go mod tidy -e +stderr 'go mod tidy: go.mod file indicates go 2000.0, but maximum supported version is '$goversion'$' +cmp go.mod go.mod.tidy + + +# Explicitly switching to a supported version should suppress the error completely. + +cp go.mod.orig go.mod +go mod tidy -go=1.17 +! stderr 'maximum supported version' +go mod edit -go=1.17 go.mod.tidy +cmp go.mod go.mod.tidy + + +-- go.mod -- +module example.net/from/the/future + +go 2000.0 + +replace example.net/m v0.0.0 => ./m +-- go.mod.tidy -- +module example.net/from/the/future + +go 2000.0 + +replace example.net/m v0.0.0 => ./m + +require example.net/m v0.0.0 +-- x.go -- +package x + +import "example.net/m" +-- m/go.mod -- +module example.net/m + +go 1.17 +-- m/m.go -- +package m diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_version.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_version.txt new file mode 100644 index 0000000..3bc97bc --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_version.txt @@ -0,0 +1,262 @@ +# https://golang.org/issue/45094: 'go mod tidy' now accepts a '-go' flag +# to change the language version in use. +# +# The package import graph used in this test looks like: +# +# m --- a --- b +# | +# b_test --- c +# | +# c_test --- d +# +# The module diagram looks like: +# +# m --- a --- b +# | +# + --- c +# | +# + --- d +# +# Module b omits its dependency on c, and module c omits its dependency on d. +# +# In go 1.15, the tidy main module must require a (because it is direct), +# c (because it is a missing test dependency of an imported package), +# and d (because it is a missing transitive test dependency). +# +# In go 1.16, the tidy main module can omit d because it is no longer +# included in "all". +# +# In go 1.17, the main module must explicitly require b +# (because it is transitively imported by the main module). + + +cp go.mod go.mod.orig + + +# An invalid argument should be rejected. + +! go mod tidy -go=bananas +stderr '^invalid value "bananas" for flag -go: expecting a Go version like "'$goversion'"$' +cmp go.mod go.mod.orig + +! go mod tidy -go=0.9 +stderr '^invalid value "0.9" for flag -go: expecting a Go version like "'$goversion'"$' + +! go mod tidy -go=2000.0 +stderr '^invalid value "2000.0" for flag -go: maximum supported Go version is '$goversion'$' + + +# Supported versions should change the go.mod file to be tidy according to the +# indicated version. + +go mod tidy -go=1.15 +cmp go.mod go.mod.115 + +go mod tidy +cmp go.mod go.mod.115 + + +go mod tidy -go=1.16 +cmp go.mod go.mod.116 + +go mod tidy +cmp go.mod go.mod.116 + + +go mod tidy -go=1.17 +cmp go.mod go.mod.117 + +go mod tidy +cmp go.mod go.mod.117 + + +# If we downgrade back to 1.15, we should re-resolve d to v0.2.0 instead +# of the original v0.1.0 (because the original requirement is lost). + +go mod tidy -go=1.15 +cmp go.mod go.mod.115-2 + + +# -go= (with an empty argument) maintains the existing version or adds the +# default version (just like omitting the flag). + +go mod tidy -go='' +cmp go.mod go.mod.115-2 + +cp go.mod.orig go.mod +go mod tidy -go='' +cmpenv go.mod go.mod.latest + + + +-- go.mod -- +module example.com/m + +require example.net/a v0.1.0 + +require ( + example.net/c v0.1.0 // indirect + example.net/d v0.1.0 // indirect +) + +replace ( + example.net/a v0.1.0 => ./a + example.net/a v0.2.0 => ./a + example.net/b v0.1.0 => ./b + example.net/b v0.2.0 => ./b + example.net/c v0.1.0 => ./c + example.net/c v0.2.0 => ./c + example.net/d v0.1.0 => ./d + example.net/d v0.2.0 => ./d +) +-- m.go -- +package m + +import _ "example.net/a" + +-- go.mod.115 -- +module example.com/m + +go 1.15 + +require example.net/a v0.1.0 + +require ( + example.net/c v0.1.0 // indirect + example.net/d v0.1.0 // indirect +) + +replace ( + example.net/a v0.1.0 => ./a + example.net/a v0.2.0 => ./a + example.net/b v0.1.0 => ./b + example.net/b v0.2.0 => ./b + example.net/c v0.1.0 => ./c + example.net/c v0.2.0 => ./c + example.net/d v0.1.0 => ./d + example.net/d v0.2.0 => ./d +) +-- go.mod.115-2 -- +module example.com/m + +go 1.15 + +require example.net/a v0.1.0 + +require ( + example.net/c v0.1.0 // indirect + example.net/d v0.2.0 // indirect +) + +replace ( + example.net/a v0.1.0 => ./a + example.net/a v0.2.0 => ./a + example.net/b v0.1.0 => ./b + example.net/b v0.2.0 => ./b + example.net/c v0.1.0 => ./c + example.net/c v0.2.0 => ./c + example.net/d v0.1.0 => ./d + example.net/d v0.2.0 => ./d +) +-- go.mod.116 -- +module example.com/m + +go 1.16 + +require example.net/a v0.1.0 + +require example.net/c v0.1.0 // indirect + +replace ( + example.net/a v0.1.0 => ./a + example.net/a v0.2.0 => ./a + example.net/b v0.1.0 => ./b + example.net/b v0.2.0 => ./b + example.net/c v0.1.0 => ./c + example.net/c v0.2.0 => ./c + example.net/d v0.1.0 => ./d + example.net/d v0.2.0 => ./d +) +-- go.mod.117 -- +module example.com/m + +go 1.17 + +require example.net/a v0.1.0 + +require ( + example.net/b v0.1.0 // indirect + example.net/c v0.1.0 // indirect +) + +replace ( + example.net/a v0.1.0 => ./a + example.net/a v0.2.0 => ./a + example.net/b v0.1.0 => ./b + example.net/b v0.2.0 => ./b + example.net/c v0.1.0 => ./c + example.net/c v0.2.0 => ./c + example.net/d v0.1.0 => ./d + example.net/d v0.2.0 => ./d +) +-- go.mod.latest -- +module example.com/m + +go $goversion + +require example.net/a v0.1.0 + +require ( + example.net/b v0.1.0 // indirect + example.net/c v0.1.0 // indirect +) + +replace ( + example.net/a v0.1.0 => ./a + example.net/a v0.2.0 => ./a + example.net/b v0.1.0 => ./b + example.net/b v0.2.0 => ./b + example.net/c v0.1.0 => ./c + example.net/c v0.2.0 => ./c + example.net/d v0.1.0 => ./d + example.net/d v0.2.0 => ./d +) +-- a/go.mod -- +module example.net/a + +go 1.15 + +require example.net/b v0.1.0 +-- a/a.go -- +package a + +import _ "example.net/b" + +-- b/go.mod -- +module example.net/b + +go 1.15 +-- b/b.go -- +package b +-- b/b_test.go -- +package b_test + +import _ "example.net/c" + +-- c/go.mod -- +module example.net/c + +go 1.15 +-- c/c.go -- +package c +-- c/c_test.go -- +package c_test + +import _ "example.net/d" + +-- d/go.mod -- +module example.net/d + +go 1.15 +-- d/d.go -- +package d diff --git a/libgo/go/cmd/go/testdata/script/mod_update_sum_readonly.txt b/libgo/go/cmd/go/testdata/script/mod_update_sum_readonly.txt new file mode 100644 index 0000000..41f12e4 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_update_sum_readonly.txt @@ -0,0 +1,34 @@ +# When finding the latest version of a module, we should not download version +# contents. Previously, we downloaded .zip files to determine whether a real +# .mod file was present in order to decide whether +incompatible versions +# could be "latest". +# +# Verifies #47377. + +# rsc.io/breaker has two versions, neither of which has a .mod file. +go list -m -versions rsc.io/breaker +stdout '^rsc.io/breaker v1.0.0 v2.0.0\+incompatible$' +go mod download rsc.io/breaker@v1.0.0 +! grep '^go' $GOPATH/pkg/mod/cache/download/rsc.io/breaker/@v/v1.0.0.mod +go mod download rsc.io/breaker@v2.0.0+incompatible +! grep '^go' $GOPATH/pkg/mod/cache/download/rsc.io/breaker/@v/v2.0.0+incompatible.mod + +# Delete downloaded .zip files. +go clean -modcache + +# Check for updates. +go list -m -u rsc.io/breaker +stdout '^rsc.io/breaker v1.0.0 \[v2.0.0\+incompatible\]$' + +# We should not have downloaded zips. +! exists $GOPATH/pkg/mod/cache/download/rsc.io/breaker/@v/v1.0.0.zip +! exists $GOPATH/pkg/mod/cache/download/rsc.io/breaker/@v/v2.0.0+incompatible.zip + +-- go.mod -- +module m + +go 1.16 + +require rsc.io/breaker v1.0.0 +-- go.sum -- +rsc.io/breaker v1.0.0/go.mod h1:s5yxDXvD88U1/ESC23I2FK3Lkv4YIKaB1ij/Hbm805g= diff --git a/libgo/go/cmd/go/testdata/script/mod_vendor_embed.txt b/libgo/go/cmd/go/testdata/script/mod_vendor_embed.txt new file mode 100644 index 0000000..be11415 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_vendor_embed.txt @@ -0,0 +1,179 @@ +go mod vendor +cmp vendor/example.com/a/samedir_embed.txt a/samedir_embed.txt +cmp vendor/example.com/a/subdir/embed.txt a/subdir/embed.txt +cmp vendor/example.com/a/subdir/test/embed.txt a/subdir/test/embed.txt +cmp vendor/example.com/a/subdir/test/xtest/embed.txt a/subdir/test/xtest/embed.txt + +cd broken_no_matching_files +! go mod vendor +stderr 'go mod vendor: pattern foo.txt: no matching files found' + +cd ../broken_bad_pattern +! go mod vendor +stderr 'go mod vendor: pattern ../foo.txt: invalid pattern syntax' + +# matchPotentialSourceFile prunes out tests and unbuilt code. +# Make sure that they are vendored if they are embedded files. +cd ../embed_unbuilt +go mod vendor +cmp vendor/example.com/dep/unbuilt.go dep/unbuilt.go +cmp vendor/example.com/dep/dep_test.go dep/dep_test.go +! exists vendor/example.com/dep/not_embedded_unbuilt.go +! exists vendor/example.com/dep/not_embedded_dep_test.go +-- go.mod -- +module example.com/foo +go 1.16 + +require ( + example.com/a v0.1.0 +) + +replace ( + example.com/a v0.1.0 => ./a +) +-- foo.go -- +package main + +import ( + "fmt" + + "example.com/a" +) + +func main() { + fmt.Println(a.Str()) +} +-- a/go.mod -- +module example.com/a +-- a/a.go -- +package a + +import _ "embed" + +//go:embed samedir_embed.txt +var sameDir string + +//go:embed subdir/embed.txt +var subDir string + +func Str() string { + return sameDir + subDir +} +-- a/a_test.go -- +package a + +import _ "embed" + +//go:embed subdir/test/embed.txt +var subderTest string +-- a/a_x_test.go -- +package a_test + +import _ "embed" + +//go:embed subdir/test/xtest/embed.txt +var subdirXtest string +-- a/samedir_embed.txt -- +embedded file in same directory as package +-- a/subdir/embed.txt -- +embedded file in subdirectory of package +-- a/subdir/test/embed.txt -- +embedded file of test in subdirectory of package +-- a/subdir/test/xtest/embed.txt -- +embedded file of xtest in subdirectory of package +-- broken_no_matching_files/go.mod -- +module example.com/broken +go 1.16 + +require ( + example.com/brokendep v0.1.0 +) + +replace ( + example.com/brokendep v0.1.0 => ./brokendep +) +-- broken_no_matching_files/f.go -- +package broken + +import _ "example.com/brokendep" + +func F() {} +-- broken_no_matching_files/brokendep/go.mod -- +module example.com/brokendep +go 1.16 +-- broken_no_matching_files/brokendep/f.go -- +package brokendep + +import _ "embed" + +//go:embed foo.txt +var foo string +-- broken_bad_pattern/go.mod -- +module example.com/broken +go 1.16 + +require ( + example.com/brokendep v0.1.0 +) + +replace ( + example.com/brokendep v0.1.0 => ./brokendep +) +-- broken_bad_pattern/f.go -- +package broken + +import _ "example.com/brokendep" + +func F() {} +-- broken_bad_pattern/brokendep/go.mod -- +module example.com/brokendep +go 1.16 +-- broken_bad_pattern/brokendep/f.go -- +package brokendep + +import _ "embed" + +//go:embed ../foo.txt +var foo string +-- embed_unbuilt/go.mod -- +module example.com/foo +go 1.16 + +require ( + example.com/dep v0.1.0 +) + +replace ( + example.com/dep v0.1.0 => ./dep +) +-- embed_unbuilt/foo.go -- +package a + +import _ "example.com/dep" + +func F() {} +-- embed_unbuilt/dep/go.mod -- +module example.com/dep +go 1.16 +-- embed_unbuilt/dep/dep.go -- +package dep + +import _ "embed" + +//go:embed unbuilt.go +var unbuilt string + +//go:embed dep_test.go +var depTest string +-- embed_unbuilt/dep/unbuilt.go -- +// +build ignore + +package dep +-- embed_unbuilt/dep/not_embedded_unbuilt.go -- +// +build ignore + +package dep +-- embed_unbuilt/dep/dep_test.go -- +package dep +-- embed_unbuilt/dep/not_embedded_dep_test.go -- +package dep diff --git a/libgo/go/cmd/go/testdata/script/mod_vendor_gomod.txt b/libgo/go/cmd/go/testdata/script/mod_vendor_gomod.txt new file mode 100644 index 0000000..3f6ea35 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_vendor_gomod.txt @@ -0,0 +1,38 @@ +# https://golang.org/issue/42970: As of Go 1.17, go.mod and go.sum files should +# be stripped from vendored dependencies. + +go mod vendor +cd vendor/example.net/x +go list all +! stdout '^example.net/m' +stdout '^example.net/x$' +exists ./go.sum + +cd ../../.. +go mod edit -go=1.17 +go mod vendor +cd vendor/example.net/x +go list all +stdout '^example.net/m$' +stdout '^example.net/x$' +! exists ./go.sum + +-- go.mod -- +module example.net/m + +go 1.16 + +require example.net/x v0.1.0 + +replace example.net/x v0.1.0 => ./x +-- m.go -- +package m + +import _ "example.net/x" +-- x/go.mod -- +module example.net/x + +go 1.16 +-- x/go.sum -- +-- x/x.go -- +package x diff --git a/libgo/go/cmd/go/testdata/script/mod_vendor_goversion.txt b/libgo/go/cmd/go/testdata/script/mod_vendor_goversion.txt new file mode 100644 index 0000000..aa4cb41 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_vendor_goversion.txt @@ -0,0 +1,102 @@ +# https://golang.org/issue/36876: As of Go 1.17, vendor/modules.txt should +# indicate the language version used by each dependency. + +[short] skip + + +# Control case: without a vendor directory, need117 builds and bad114 doesn't. + +go build example.net/need117 +! go build example.net/bad114 +stderr '^bad114[/\\]bad114.go:15:2: duplicate method Y$' + + +# With a vendor/modules.txt lacking language versions, the world is topsy-turvy, +# because we have to guess a uniform version for everything. +# +# We always guess Go 1.16, because that was the last version for which +# 'go mod vendor' failed to record dependency versions, and it has most of +# the language features added since modules were introduced in Go 1.11. +# +# Even so, modules that declare 'go 1.17' and use 1.17 features spuriously fail +# to build, and modules that declare an older version and use features from a +# newer one spuriously build (instead of failing as they ought to). + +go mod vendor + +! grep 1.17 vendor/modules.txt +! go build example.net/need117 +stderr '^vendor[/\\]example\.net[/\\]need117[/\\]need117.go:5:18: .*\n\tconversion of slices to array pointers only supported as of -lang=go1\.17' + +! grep 1.13 vendor/modules.txt +go build example.net/bad114 + + +# Upgrading the main module to 1.17 adds version annotations. +# Then everything is once again consistent with the non-vendored world. + +go mod edit -go=1.17 +go mod vendor + +grep '^## explicit; go 1.17$' vendor/modules.txt +go build example.net/need117 + +grep '^## explicit; go 1.13$' vendor/modules.txt +! go build example.net/bad114 +stderr '^vendor[/\\]example\.net[/\\]bad114[/\\]bad114.go:15:2: duplicate method Y$' + +-- go.mod -- +module example.net/m + +go 1.16 + +require ( + example.net/bad114 v0.1.0 + example.net/need117 v0.1.0 +) + +replace ( + example.net/bad114 v0.1.0 => ./bad114 + example.net/need117 v0.1.0 => ./need117 +) +-- m.go -- +package m + +import _ "example.net/bad114" +import _ "example.net/need117" + +-- bad114/go.mod -- +// Module bad114 requires Go 1.14 or higher, but declares Go 1.13. +module example.net/bad114 + +go 1.13 +-- bad114/bad114.go -- +package bad114 + +type XY interface { + X() + Y() +} + +type YZ interface { + Y() + Z() +} + +type XYZ interface { + XY + YZ +} + +-- need117/go.mod -- +// Module need117 requires Go 1.17 or higher. +module example.net/need117 + +go 1.17 +-- need117/need117.go -- +package need117 + +func init() { + s := make([]byte, 4) + _ = (*[4]byte)(s) +} diff --git a/libgo/go/cmd/go/testdata/script/mod_vendor_issue46867.txt b/libgo/go/cmd/go/testdata/script/mod_vendor_issue46867.txt new file mode 100644 index 0000000..38ae87b --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_vendor_issue46867.txt @@ -0,0 +1,31 @@ +# Regression test for golang.org/issue/46867: +# 'go mod vendor' on Windows attempted to open and copy +# files from directories outside of the module. + +cd subdir +go mod vendor +! exists vendor/example.net/NOTICE +exists vendor/example.net/m/NOTICE + +-- subdir/go.mod -- +module golang.org/issue46867 + +go 1.17 + +replace example.net/m v0.1.0 => ./m + +require example.net/m v0.1.0 +-- subdir/issue.go -- +package issue + +import _ "example.net/m/n" +-- subdir/m/go.mod -- +module example.net/m + +go 1.17 +-- subdir/m/n/n.go -- +package n +-- subdir/m/NOTICE -- +This notice is in module m and SHOULD be vendored. +-- subdir/NOTICE -- +This notice is outside of module m and SHOULD NOT be vendored. diff --git a/libgo/go/cmd/go/testdata/script/mod_vendor_trimpath.txt b/libgo/go/cmd/go/testdata/script/mod_vendor_trimpath.txt new file mode 100644 index 0000000..5451aa7 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_vendor_trimpath.txt @@ -0,0 +1,45 @@ +# Check that when -trimpath and -mod=vendor are used together, +# paths in vendored packages are properly trimmed. +# Verifies golang.org/issue/36566. + +[short] skip + +# Only the main module has a root directory in vendor mode. +go mod vendor +go list -f {{.Module.Dir}} example.com/main +stdout $PWD +go list -f {{.Module.Dir}} example.com/stack +! stdout . + +# The program prints a file name from a vendored package. +# Without -trimpath, the name should include the vendor directory. +go run main.go +stdout vendor + +# With -trimpath, everything before the package path should be trimmed. +# As with -mod=mod, the version should appear as part of the module path. +go run -mod=vendor -trimpath main.go +stdout '^example.com/stack@v1.0.0/stack.go$' + +# With pristinely vendored source code, a trimmed binary built from vendored +# code should have the same behavior as one build from the module cache. +go run -mod=mod -trimpath main.go +stdout '^example.com/stack@v1.0.0/stack.go$' + +-- go.mod -- +module example.com/main + +require example.com/stack v1.0.0 + +-- main.go -- +package main + +import ( + "fmt" + + "example.com/stack" +) + +func main() { + fmt.Println(stack.TopFile()) +} diff --git a/libgo/go/cmd/go/testdata/script/mod_vendor_unused_only.txt b/libgo/go/cmd/go/testdata/script/mod_vendor_unused_only.txt new file mode 100644 index 0000000..839c645 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_vendor_unused_only.txt @@ -0,0 +1,17 @@ +# Ensure that we generate a vendor/modules.txt file even when the only +# requirements in go.mod are unused. Regression test for +# golang.org/issue/36580 + +env GO111MODULE=on + +go mod vendor +cmp go1.14-modules.txt vendor/modules.txt + +-- go.mod -- +module example.com/m +go 1.14 + +require example.com v1.0.0 // indirect +-- go1.14-modules.txt -- +# example.com v1.0.0 +## explicit diff --git a/libgo/go/cmd/go/testdata/script/run_dirs.txt b/libgo/go/cmd/go/testdata/script/run_dirs.txt new file mode 100644 index 0000000..538a6ac --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/run_dirs.txt @@ -0,0 +1,11 @@ +cd rundir + +! go run x.go sub/sub.go +stderr 'named files must all be in one directory; have ./ and sub/' +! go run sub/sub.go x.go +stderr 'named files must all be in one directory; have sub/ and ./' + +-- rundir/sub/sub.go -- +package main +-- rundir/x.go -- +package main diff --git a/libgo/go/cmd/go/testdata/script/run_hello_pkg.txt b/libgo/go/cmd/go/testdata/script/run_hello_pkg.txt new file mode 100644 index 0000000..ea2b4d7 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/run_hello_pkg.txt @@ -0,0 +1,17 @@ +go run m/hello +stderr 'hello, world' + +cd hello +go run . +stderr 'hello, world' + +-- go.mod -- +module m + +go 1.16 +-- hello/hello.go -- +package main + +func main() { + println("hello, world") +} diff --git a/libgo/go/cmd/go/testdata/script/run_internal.txt b/libgo/go/cmd/go/testdata/script/run_internal.txt new file mode 100644 index 0000000..d021850 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/run_internal.txt @@ -0,0 +1,64 @@ +env GO111MODULE=off + +go list -e -f '{{.Incomplete}}' m/runbad1.go +stdout true +! go run m/runbad1.go +stderr 'use of internal package m/x/internal not allowed' + +go list -e -f '{{.Incomplete}}' m/runbad2.go +stdout true +! go run m/runbad2.go +stderr 'use of internal package m/x/internal/y not allowed' + +go list -e -f '{{.Incomplete}}' m/runok.go +stdout false +go run m/runok.go + +cd m +env GO111MODULE=on + +go list -e -f '{{.Incomplete}}' runbad1.go +stdout true +! go run runbad1.go +stderr 'use of internal package m/x/internal not allowed' + +go list -e -f '{{.Incomplete}}' runbad2.go +stdout true +! go run runbad2.go +stderr 'use of internal package m/x/internal/y not allowed' + +go list -e -f '{{.Incomplete}}' runok.go +stdout false +go run runok.go + + +-- m/go.mod -- +module m + +-- m/x/internal/internal.go -- +package internal + +-- m/x/internal/y/y.go -- +package y + +-- m/internal/internal.go -- +package internal + +-- m/internal/z/z.go -- +package z + +-- m/runbad1.go -- +package main +import _ "m/x/internal" +func main() {} + +-- m/runbad2.go -- +package main +import _ "m/x/internal/y" +func main() {} + +-- m/runok.go -- +package main +import _ "m/internal" +import _ "m/internal/z" +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/run_issue11709.txt b/libgo/go/cmd/go/testdata/script/run_issue11709.txt new file mode 100644 index 0000000..c8ba998 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/run_issue11709.txt @@ -0,0 +1,15 @@ +# 'go run' should not pass extraneous environment variables to the subprocess. +go run run.go +! stdout . +! stderr . + +-- run.go -- +package main + +import "os" + +func main() { + if os.Getenv("TERM") != "" { + os.Exit(1) + } +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/run_vendor.txt b/libgo/go/cmd/go/testdata/script/run_vendor.txt new file mode 100644 index 0000000..46cac06 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/run_vendor.txt @@ -0,0 +1,34 @@ +# Run +env GO111MODULE=off +cd vend/hello +go run hello.go +stdout 'hello, world' + +-- vend/hello/hello.go -- +package main + +import ( + "fmt" + "strings" // really ../vendor/strings +) + +func main() { + fmt.Printf("%s\n", strings.Msg) +} +-- vend/hello/hello_test.go -- +package main + +import ( + "strings" // really ../vendor/strings + "testing" +) + +func TestMsgInternal(t *testing.T) { + if strings.Msg != "hello, world" { + t.Fatalf("unexpected msg: %v", strings.Msg) + } +} +-- vend/vendor/strings/msg.go -- +package strings + +var Msg = "hello, world" diff --git a/libgo/go/cmd/go/testdata/script/test_benchmark_chatty_fail.txt b/libgo/go/cmd/go/testdata/script/test_benchmark_chatty_fail.txt new file mode 100644 index 0000000..6031ead --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_benchmark_chatty_fail.txt @@ -0,0 +1,32 @@ +# Run chatty tests. Assert on CONT lines. +! go test chatty_test.go -v -bench . chatty_bench + +# Sanity check that output occurs. +stdout -count=2 'this is sub-0' +stdout -count=2 'this is sub-1' +stdout -count=2 'this is sub-2' +stdout -count=1 'error from sub-0' +stdout -count=1 'error from sub-1' +stdout -count=1 'error from sub-2' + +# Benchmarks should not print CONT. +! stdout CONT + +-- chatty_test.go -- +package chatty_bench + +import ( + "testing" + "fmt" +) + +func BenchmarkChatty(b *testing.B) { + for i := 0; i < 3; i++ { + b.Run(fmt.Sprintf("sub-%d", i), func(b *testing.B) { + for j := 0; j < 2; j++ { + b.Logf("this is sub-%d", i) + } + b.Errorf("error from sub-%d", i) + }) + } +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_benchmark_chatty_success.txt b/libgo/go/cmd/go/testdata/script/test_benchmark_chatty_success.txt new file mode 100644 index 0000000..a1c0d65 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_benchmark_chatty_success.txt @@ -0,0 +1,29 @@ +# Run chatty tests. Assert on CONT lines. +go test chatty_test.go -v -bench . chatty_bench + +# Sanity check that output happens. We don't provide -count because the amount +# of output is variable. +stdout 'this is sub-0' +stdout 'this is sub-1' +stdout 'this is sub-2' + +# Benchmarks should not print CONT. +! stdout CONT + +-- chatty_test.go -- +package chatty_bench + +import ( + "testing" + "fmt" +) + +func BenchmarkChatty(b *testing.B) { + for i := 0; i < 3; i++ { + b.Run(fmt.Sprintf("sub-%d", i), func(b *testing.B) { + for j := 0; j < 2; j++ { + b.Logf("this is sub-%d", i) + } + }) + } +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_benchmark_fatal.txt b/libgo/go/cmd/go/testdata/script/test_benchmark_fatal.txt new file mode 100644 index 0000000..e281379 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_benchmark_fatal.txt @@ -0,0 +1,19 @@ +# Test that calling t.Fatal in a benchmark causes a non-zero exit status. + +! go test -run '^$' -bench . benchfatal +! stdout ^ok +! stderr ^ok +stdout FAIL.*benchfatal + +-- go.mod -- +module benchfatal + +go 1.16 +-- x_test.go -- +package benchfatal + +import "testing" + +func BenchmarkThatCallsFatal(b *testing.B) { + b.Fatal("called by benchmark") +} diff --git a/libgo/go/cmd/go/testdata/script/test_benchmark_labels.txt b/libgo/go/cmd/go/testdata/script/test_benchmark_labels.txt new file mode 100644 index 0000000..6b424c1 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_benchmark_labels.txt @@ -0,0 +1,23 @@ +# Tests that go test -bench prints out goos, goarch, and pkg. + +# Check for goos, goarch, and pkg. +go test -run ^$ -bench . bench +stdout '^goos: '$GOOS +stdout '^goarch: '$GOARCH +stdout '^pkg: bench' + +# Check go test does not print pkg multiple times +! stdout 'pkg:.*pkg: ' +! stderr 'pkg:.*pkg:' + +-- go.mod -- +module bench + +go 1.16 +-- x_test.go -- +package bench + +import "testing" + +func Benchmark(b *testing.B) { +} diff --git a/libgo/go/cmd/go/testdata/script/test_benchmark_timeout.txt b/libgo/go/cmd/go/testdata/script/test_benchmark_timeout.txt new file mode 100644 index 0000000..4bae7e7 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_benchmark_timeout.txt @@ -0,0 +1,18 @@ +# Tests issue #18845 +[short] skip + +go test -bench . -timeout=750ms timeoutbench_test.go +stdout ok +stdout PASS + +-- timeoutbench_test.go -- +package timeoutbench_test + +import ( + "testing" + "time" +) + +func BenchmarkSleep1s(b *testing.B) { + time.Sleep(1 * time.Second) +} diff --git a/libgo/go/cmd/go/testdata/script/test_build_failure.txt b/libgo/go/cmd/go/testdata/script/test_build_failure.txt new file mode 100644 index 0000000..8d13634 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_build_failure.txt @@ -0,0 +1,31 @@ +[short] skip + +! go test -x coverbad +! stderr '[\\/]coverbad\.test( |$)' # 'go test' should not claim to have run the test. +stderr 'undefined: g' +stderr 'undefined: j' + +-- go.mod -- +module coverbad + +go 1.16 +-- p.go -- +package p + +func f() { + g() +} +-- p1.go -- +package p + +import "C" + +func h() { + j() +} +-- p_test.go -- +package p + +import "testing" + +func Test(t *testing.T) {} diff --git a/libgo/go/cmd/go/testdata/script/test_cache_inputs.txt b/libgo/go/cmd/go/testdata/script/test_cache_inputs.txt index 50486e1..d694a30 100644 --- a/libgo/go/cmd/go/testdata/script/test_cache_inputs.txt +++ b/libgo/go/cmd/go/testdata/script/test_cache_inputs.txt @@ -99,6 +99,15 @@ rm $WORK/external.txt go test testcache -run=ExternalFile stdout '\(cached\)' +# The -benchtime flag without -bench should not affect caching. +go test testcache -run=Benchtime -benchtime=1x +go test testcache -run=Benchtime -benchtime=1x +stdout '\(cached\)' + +go test testcache -run=Benchtime -bench=Benchtime -benchtime=1x +go test testcache -run=Benchtime -bench=Benchtime -benchtime=1x +! stdout '\(cached\)' + # Executables within GOROOT and GOPATH should affect caching, # even if the test does not stat them explicitly. @@ -228,6 +237,10 @@ func TestExternalFile(t *testing.T) { func TestOSArgs(t *testing.T) { t.Log(os.Args) } + +func TestBenchtime(t *testing.T) { +} + -- mkold.go -- package main diff --git a/libgo/go/cmd/go/testdata/script/test_chatty_fail.txt b/libgo/go/cmd/go/testdata/script/test_chatty_fail.txt new file mode 100644 index 0000000..a5ef559 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_chatty_fail.txt @@ -0,0 +1,32 @@ +# Run chatty tests. Assert on CONT lines. +! go test chatty_test.go -v + +# Sanity check that output occurs. +stdout -count=2 'this is sub-0' +stdout -count=2 'this is sub-1' +stdout -count=2 'this is sub-2' +stdout -count=1 'error from sub-0' +stdout -count=1 'error from sub-1' +stdout -count=1 'error from sub-2' + +# Non-parallel tests should not print CONT. +! stdout CONT + +-- chatty_test.go -- +package chatty_test + +import ( + "testing" + "fmt" +) + +func TestChatty(t *testing.T) { + for i := 0; i < 3; i++ { + t.Run(fmt.Sprintf("sub-%d", i), func(t *testing.T) { + for j := 0; j < 2; j++ { + t.Logf("this is sub-%d", i) + } + t.Errorf("error from sub-%d", i) + }) + } +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_chatty_parallel_fail.txt b/libgo/go/cmd/go/testdata/script/test_chatty_parallel_fail.txt new file mode 100644 index 0000000..f8faa93 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_chatty_parallel_fail.txt @@ -0,0 +1,58 @@ +# Run parallel chatty tests. Assert on CONT lines. This test makes sure that +# multiple parallel outputs have the appropriate CONT lines between them. +! go test -parallel 3 chatty_parallel_test.go -v + +stdout -count=1 '^=== CONT TestChattyParallel/sub-0\n chatty_parallel_test.go:38: error from sub-0$' +stdout -count=1 '^=== CONT TestChattyParallel/sub-1\n chatty_parallel_test.go:38: error from sub-1$' +stdout -count=1 '^=== CONT TestChattyParallel/sub-2\n chatty_parallel_test.go:38: error from sub-2$' + +# Run parallel chatty tests with -json. Assert on CONT lines as above - make +# sure there are CONT lines before each output line. +! go test -json -parallel 3 chatty_parallel_test.go -v +stdout -count=1 '{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-0","Output":"=== CONT TestChattyParallel/sub-0\\n"}\n{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-0","Output":" chatty_parallel_test.go:38: error from sub-0\\n"}' +stdout -count=1 '{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-1","Output":"=== CONT TestChattyParallel/sub-1\\n"}\n{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-1","Output":" chatty_parallel_test.go:38: error from sub-1\\n"}' +stdout -count=1 '{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-2","Output":"=== CONT TestChattyParallel/sub-2\\n"}\n{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-2","Output":" chatty_parallel_test.go:38: error from sub-2\\n"}' + +-- chatty_parallel_test.go -- +package chatty_parallel_test + +import ( + "testing" + "fmt" + "flag" +) + +// This test ensures the order of CONT lines in parallel chatty tests. +func TestChattyParallel(t *testing.T) { + t.Parallel() + + // The number of concurrent tests running. This is closely tied to the + // -parallel test flag, so we grab it from the flag rather than setting it + // to some constant. + parallel := flag.Lookup("test.parallel").Value.(flag.Getter).Get().(int) + + // ready is a synchronization mechanism that causes subtests to execute + // round robin. + ready := make([]chan bool, parallel) + for i := range ready { + ready[i] = make(chan bool, 1) + } + ready[0] <- true + + for i := range ready { + i := i + t.Run(fmt.Sprintf("sub-%d", i), func(t *testing.T) { + t.Parallel() + + // Some basic log output to precede the failures. + <-ready[i] + t.Logf("this is sub-%d", i) + ready[(i+1)%len(ready)] <- true + + // The actual failure messages we care about. + <-ready[i] + t.Errorf("error from sub-%d", i) + ready[(i+1)%len(ready)] <- true + }) + } +} diff --git a/libgo/go/cmd/go/testdata/script/test_chatty_parallel_success.txt b/libgo/go/cmd/go/testdata/script/test_chatty_parallel_success.txt new file mode 100644 index 0000000..63034fa --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_chatty_parallel_success.txt @@ -0,0 +1,52 @@ +# Run parallel chatty tests. Assert on CONT lines. This test makes sure that +# multiple parallel outputs have the appropriate CONT lines between them. +go test -parallel 3 chatty_parallel_test.go -v +stdout -count=2 '^=== CONT TestChattyParallel/sub-0\n chatty_parallel_test.go:32: this is sub-0$' +stdout -count=2 '^=== CONT TestChattyParallel/sub-1\n chatty_parallel_test.go:32: this is sub-1$' +stdout -count=2 '^=== CONT TestChattyParallel/sub-2\n chatty_parallel_test.go:32: this is sub-2$' + +# Run parallel chatty tests with -json. Assert on CONT lines as above - make +# sure there are CONT lines before each output line. +go test -json -parallel 3 chatty_parallel_test.go -v +stdout -count=2 '{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-0","Output":"=== CONT TestChattyParallel/sub-0\\n"}\n{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-0","Output":" chatty_parallel_test.go:32: this is sub-0\\n"}' +stdout -count=2 '{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-1","Output":"=== CONT TestChattyParallel/sub-1\\n"}\n{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-1","Output":" chatty_parallel_test.go:32: this is sub-1\\n"}' +stdout -count=2 '{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-2","Output":"=== CONT TestChattyParallel/sub-2\\n"}\n{"Time":"[0-9TZ:.+-]{20,40}","Action":"output","Package":"command-line-arguments","Test":"TestChattyParallel/sub-2","Output":" chatty_parallel_test.go:32: this is sub-2\\n"}' + +-- chatty_parallel_test.go -- +package chatty_parallel_test + +import ( + "testing" + "fmt" + "flag" +) + +// This test ensures the order of CONT lines in parallel chatty tests. +func TestChattyParallel(t *testing.T) { + t.Parallel() + + // The number of concurrent tests running. This is closely tied to the + // -parallel test flag, so we grab it from the flag rather than setting it + // to some constant. + parallel := flag.Lookup("test.parallel").Value.(flag.Getter).Get().(int) + + // ready is a synchronization mechanism that causes subtests to execute + // round robin. + ready := make([]chan bool, parallel) + for i := range ready { + ready[i] = make(chan bool, 1) + } + ready[0] <- true + + for i := range ready { + i := i + t.Run(fmt.Sprintf("sub-%d", i), func(t *testing.T) { + t.Parallel() + for j := 0; j < 2; j++ { + <-ready[i] + t.Logf("this is sub-%d", i) + ready[(i+1)%len(ready)] <- true + } + }) + } +} diff --git a/libgo/go/cmd/go/testdata/script/test_chatty_parallel_success_sleepy.txt b/libgo/go/cmd/go/testdata/script/test_chatty_parallel_success_sleepy.txt new file mode 100644 index 0000000..e651a7e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_chatty_parallel_success_sleepy.txt @@ -0,0 +1,39 @@ +# Run parallel chatty tests. Assert on CONT lines. This test makes sure that +# multiple parallel outputs have the appropriate CONT lines between them. +go test -parallel 3 chatty_parallel_test.go -v + +stdout '--- PASS: TestFast \([0-9.]{4}s\)\n=== CONT TestSlow\n chatty_parallel_test.go:31: this is the second TestSlow log\n--- PASS: TestSlow \([0-9.]{4}s\)' + +-- chatty_parallel_test.go -- +package chatty_parallel_test + +import ( + "testing" + "time" +) + +var ( + run = make(chan struct{}) + afterFirstLog = make(chan struct{}) + afterPass = make(chan struct{}) +) + +func TestFast(t *testing.T) { + t.Parallel() + + <-afterFirstLog + t.Cleanup(func() { + close(afterPass) + }) +} + +func TestSlow(t *testing.T) { + t.Parallel() + + t.Logf("this is the first TestSlow log") + close(afterFirstLog) + + <-afterPass + time.Sleep(100 * time.Millisecond) + t.Logf("this is the second TestSlow log") +} diff --git a/libgo/go/cmd/go/testdata/script/test_chatty_success.txt b/libgo/go/cmd/go/testdata/script/test_chatty_success.txt new file mode 100644 index 0000000..8bfa569 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_chatty_success.txt @@ -0,0 +1,27 @@ +# Run chatty tests. Assert on CONT lines. +go test chatty_test.go -v + +# Non-parallel tests should not print CONT. +! stdout CONT + +# The assertion is condensed into one line so that it precisely matches output, +# rather than skipping lines and allow rogue CONT lines. +stdout '=== RUN TestChatty\n=== RUN TestChatty/sub-0\n chatty_test.go:12: this is sub-0\n chatty_test.go:12: this is sub-0\n=== RUN TestChatty/sub-1\n chatty_test.go:12: this is sub-1\n chatty_test.go:12: this is sub-1\n=== RUN TestChatty/sub-2\n chatty_test.go:12: this is sub-2\n chatty_test.go:12: this is sub-2\n--- PASS: TestChatty' + +-- chatty_test.go -- +package chatty_test + +import ( + "testing" + "fmt" +) + +func TestChatty(t *testing.T) { + for i := 0; i < 3; i++ { + t.Run(fmt.Sprintf("sub-%d", i), func(t *testing.T) { + for j := 0; j < 2; j++ { + t.Logf("this is sub-%d", i) + } + }) + } +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_cleanup_failnow.txt b/libgo/go/cmd/go/testdata/script/test_cleanup_failnow.txt new file mode 100644 index 0000000..0737a93 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_cleanup_failnow.txt @@ -0,0 +1,47 @@ +# For issue 41355 +[short] skip + +# This test could fail if the testing package does not wait until +# a panicking test does the panic. Turn off multithreading, GC, and +# async preemption to increase the probability of such a failure. +env GOMAXPROCS=1 +env GOGC=off +env GODEBUG=asyncpreempt=off + +# If the test exits with 'no tests to run', it means the testing package +# implementation is incorrect and does not wait until a test panic. +# If the test exits with '(?s)panic: die.*panic: die', it means +# the testing package did an extra panic for a panicking test. + +! go test -v cleanup_failnow/panic_nocleanup_test.go +! stdout 'no tests to run' +stdout '(?s)panic: die \[recovered\].*panic: die' +! stdout '(?s)panic: die \[recovered\].*panic: die.*panic: die' + +! go test -v cleanup_failnow/panic_withcleanup_test.go +! stdout 'no tests to run' +stdout '(?s)panic: die \[recovered\].*panic: die' +! stdout '(?s)panic: die \[recovered\].*panic: die.*panic: die' + +-- cleanup_failnow/panic_nocleanup_test.go -- +package panic_nocleanup_test +import "testing" +func TestX(t *testing.T) { + t.Run("x", func(t *testing.T) { + panic("die") + }) +} + +-- cleanup_failnow/panic_withcleanup_test.go -- +package panic_withcleanup_test +import "testing" +func TestCleanupWithFailNow(t *testing.T) { + t.Cleanup(func() { + t.FailNow() + }) + t.Run("x", func(t *testing.T) { + t.Run("y", func(t *testing.T) { + panic("die") + }) + }) +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_deadline.txt b/libgo/go/cmd/go/testdata/script/test_deadline.txt new file mode 100644 index 0000000..06ae16f --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_deadline.txt @@ -0,0 +1,54 @@ +[short] skip + +go test -timeout=0 -run=TestNoDeadline +go test -timeout=1m -run=TestDeadlineWithinMinute +go test -timeout=1m -run=TestSubtestDeadlineWithinMinute + +-- go.mod -- +module m + +go 1.16 +-- deadline_test.go -- +package testing_test + +import ( + "testing" + "time" +) + +func TestNoDeadline(t *testing.T) { + d, ok := t.Deadline() + if ok || !d.IsZero() { + t.Fatalf("t.Deadline() = %v, %v; want 0, false", d, ok) + } +} + +func TestDeadlineWithinMinute(t *testing.T) { + now := time.Now() + d, ok := t.Deadline() + if !ok || d.IsZero() { + t.Fatalf("t.Deadline() = %v, %v; want nonzero deadline", d, ok) + } + if !d.After(now) { + t.Fatalf("t.Deadline() = %v; want after start of test (%v)", d, now) + } + if d.Sub(now) > time.Minute { + t.Fatalf("t.Deadline() = %v; want within one minute of start of test (%v)", d, now) + } +} + +func TestSubtestDeadlineWithinMinute(t *testing.T) { + t.Run("sub", func(t *testing.T) { + now := time.Now() + d, ok := t.Deadline() + if !ok || d.IsZero() { + t.Fatalf("t.Deadline() = %v, %v; want nonzero deadline", d, ok) + } + if !d.After(now) { + t.Fatalf("t.Deadline() = %v; want after start of test (%v)", d, now) + } + if d.Sub(now) > time.Minute { + t.Fatalf("t.Deadline() = %v; want within one minute of start of test (%v)", d, now) + } + }) +} diff --git a/libgo/go/cmd/go/testdata/script/test_empty.txt b/libgo/go/cmd/go/testdata/script/test_empty.txt new file mode 100644 index 0000000..5ebbecd --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_empty.txt @@ -0,0 +1,53 @@ +[!race] skip + +cd $GOPATH/src/empty/pkg +go test -cover -coverpkg=. -race + +[short] stop # Only run first case in short mode + +cd $GOPATH/src/empty/test +go test -cover -coverpkg=. -race + +cd $GOPATH/src/empty/xtest +go test -cover -coverpkg=. -race + +cd $GOPATH/src/empty/pkgtest +go test -cover -coverpkg=. -race + +cd $GOPATH/src/empty/pkgxtest +go test -cover -coverpkg=. -race + +cd $GOPATH/src/empty/pkgtestxtest +go test -cover -coverpkg=. -race + +cd $GOPATH/src/empty/testxtest +go test -cover -coverpkg=. -race + +-- empty/go.mod -- +module empty + +go 1.16 +-- empty/pkg/pkg.go -- +package p +-- empty/pkgtest/pkg.go -- +package p +-- empty/pkgtest/test_test.go -- +package p +-- empty/pkgtestxtest/pkg.go -- +package p +-- empty/pkgtestxtest/test_test.go -- +package p +-- empty/pkgtestxtest/xtest_test.go -- +package p_test +-- empty/pkgxtest/pkg.go -- +package p +-- empty/pkgxtest/xtest_test.go -- +package p_test +-- empty/test/test_test.go -- +package p +-- empty/testxtest/test_test.go -- +package p +-- empty/testxtest/xtest_test.go -- +package p_test +-- empty/xtest/xtest_test.go -- +package p_test diff --git a/libgo/go/cmd/go/testdata/script/test_env_term.txt b/libgo/go/cmd/go/testdata/script/test_env_term.txt new file mode 100644 index 0000000..8a5f79a --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_env_term.txt @@ -0,0 +1,15 @@ +# Tests golang.org/issue/12096 + +env TERM='' +go test test_test.go +! stdout '^ok.*\[no tests to run\]' +stdout '^ok' + +-- test_test.go -- +package main +import ("os"; "testing") +func TestEnv(t *testing.T) { + if os.Getenv("TERM") != "" { + t.Fatal("TERM is set") + } +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_example_goexit.txt b/libgo/go/cmd/go/testdata/script/test_example_goexit.txt new file mode 100644 index 0000000..984f434 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_example_goexit.txt @@ -0,0 +1,29 @@ +# For issue golang.org/issue/41084 +[short] skip + +! go test -v examplegoexit +stdout '(?s)--- PASS.*--- FAIL.*' +stdout 'panic: test executed panic\(nil\) or runtime\.Goexit' + +-- go.mod -- +module examplegoexit + +go 1.16 +-- example_test.go -- +package main + +import ( + "fmt" + "runtime" +) + +func ExamplePass() { + fmt.Println("pass") + // Output: + // pass +} + +func ExampleGoexit() { + runtime.Goexit() + // Output: +} diff --git a/libgo/go/cmd/go/testdata/script/test_exit.txt b/libgo/go/cmd/go/testdata/script/test_exit.txt new file mode 100644 index 0000000..3703ba5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_exit.txt @@ -0,0 +1,131 @@ +# Builds and runs test binaries, so skip in short mode. +[short] skip + +env GO111MODULE=on + +# If a test invoked by 'go test' exits with a zero status code, +# it will panic. +! go test ./zero +! stdout ^ok +! stdout 'exit status' +stdout 'panic' +stdout ^FAIL + +# If a test exits with a non-zero status code, 'go test' fails normally. +! go test ./one +! stdout ^ok +stdout 'exit status' +! stdout 'panic' +stdout ^FAIL + +# Ensure that other flags still do the right thing. +go test -list=. ./zero +stdout ExitZero + +! go test -bench=. ./zero +stdout 'panic' + +# 'go test' with no args streams output without buffering. Ensure that it still +# catches a zero exit with missing output. +cd zero +! go test +stdout 'panic' +cd ../normal +go test +stdout ^ok +cd .. + +# If a TestMain exits with a zero status code, 'go test' shouldn't +# complain about that. It's a common way to skip testing a package +# entirely. +go test ./main_zero +! stdout 'skipping all tests' +stdout ^ok + +# With -v, we'll see the warning from TestMain. +go test -v ./main_zero +stdout 'skipping all tests' +stdout ^ok + +# Listing all tests won't actually give a result if TestMain exits. That's okay, +# because this is how TestMain works. If we decide to support -list even when +# TestMain is used to skip entire packages, we can change this test case. +go test -list=. ./main_zero +stdout 'skipping all tests' +! stdout TestNotListed + +# Running the test directly still fails, if we pass the flag. +go test -c -o ./zero.exe ./zero +! exec ./zero.exe -test.paniconexit0 + +# Using -json doesn't affect the exit status. +! go test -json ./zero +! stdout '"Output":"ok' +! stdout 'exit status' +stdout 'panic' +stdout '"Output":"FAIL' + +# Running the test via test2json also fails. +! go tool test2json ./zero.exe -test.v -test.paniconexit0 +! stdout '"Output":"ok' +! stdout 'exit status' +stdout 'panic' + +-- go.mod -- +module m + +-- ./normal/normal.go -- +package normal +-- ./normal/normal_test.go -- +package normal + +import "testing" + +func TestExitZero(t *testing.T) { +} + +-- ./zero/zero.go -- +package zero +-- ./zero/zero_test.go -- +package zero + +import ( + "os" + "testing" +) + +func TestExitZero(t *testing.T) { + os.Exit(0) +} + +-- ./one/one.go -- +package one +-- ./one/one_test.go -- +package one + +import ( + "os" + "testing" +) + +func TestExitOne(t *testing.T) { + os.Exit(1) +} + +-- ./main_zero/zero.go -- +package zero +-- ./main_zero/zero_test.go -- +package zero + +import ( + "fmt" + "os" + "testing" +) + +func TestMain(m *testing.M) { + fmt.Println("skipping all tests") + os.Exit(0) +} + +func TestNotListed(t *testing.T) {} diff --git a/libgo/go/cmd/go/testdata/script/test_fail_fast.txt b/libgo/go/cmd/go/testdata/script/test_fail_fast.txt new file mode 100644 index 0000000..132ea70 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_fail_fast.txt @@ -0,0 +1,113 @@ +[short] skip + +# test fail fast +! go test ./failfast_test.go -run='TestFailingA' -failfast=true +stdout -count=1 'FAIL - ' +! go test ./failfast_test.go -run='TestFailing[AB]' -failfast=true +stdout -count=1 'FAIL - ' +! go test ./failfast_test.go -run='TestFailing[AB]' -failfast=false +stdout -count=2 'FAIL - ' + +# mix with non-failing tests +! go test ./failfast_test.go -run='TestA|TestFailing[AB]' -failfast=true +stdout -count=1 'FAIL - ' +! go test ./failfast_test.go -run='TestA|TestFailing[AB]' -failfast=false +stdout -count=2 'FAIL - ' + +# mix with parallel tests +! go test ./failfast_test.go -run='TestFailingB|TestParallelFailingA' -failfast=true +stdout -count=2 'FAIL - ' +! go test ./failfast_test.go -run='TestFailingB|TestParallelFailingA' -failfast=false +stdout -count=2 'FAIL - ' +! go test ./failfast_test.go -run='TestFailingB|TestParallelFailing[AB]' -failfast=true +stdout -count=3 'FAIL - ' +! go test ./failfast_test.go -run='TestFailingB|TestParallelFailing[AB]' -failfast=false +stdout -count=3 'FAIL - ' + +# mix with parallel sub-tests +! go test ./failfast_test.go -run='TestFailingB|TestParallelFailing[AB]|TestParallelFailingSubtestsA' -failfast=true +stdout -count=3 'FAIL - ' +! go test ./failfast_test.go -run='TestFailingB|TestParallelFailing[AB]|TestParallelFailingSubtestsA' -failfast=false +stdout -count=5 'FAIL - ' +! go test ./failfast_test.go -run='TestParallelFailingSubtestsA' -failfast=true +stdout -count=1 'FAIL - ' + +# only parallels +! go test ./failfast_test.go -run='TestParallelFailing[AB]' -failfast=false +stdout -count=2 'FAIL - ' + +# non-parallel subtests +! go test ./failfast_test.go -run='TestFailingSubtestsA' -failfast=true +stdout -count=1 'FAIL - ' +! go test ./failfast_test.go -run='TestFailingSubtestsA' -failfast=false +stdout -count=2 'FAIL - ' + +# fatal test +! go test ./failfast_test.go -run='TestFatal[CD]' -failfast=true +stdout -count=1 'FAIL - ' +! go test ./failfast_test.go -run='TestFatal[CD]' -failfast=false +stdout -count=2 'FAIL - ' + +-- failfast_test.go -- +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package failfast + +import "testing" + +func TestA(t *testing.T) { + // Edge-case testing, mixing unparallel tests too + t.Logf("LOG: %s", t.Name()) +} + +func TestFailingA(t *testing.T) { + t.Errorf("FAIL - %s", t.Name()) +} + +func TestB(t *testing.T) { + // Edge-case testing, mixing unparallel tests too + t.Logf("LOG: %s", t.Name()) +} + +func TestParallelFailingA(t *testing.T) { + t.Parallel() + t.Errorf("FAIL - %s", t.Name()) +} + +func TestParallelFailingB(t *testing.T) { + t.Parallel() + t.Errorf("FAIL - %s", t.Name()) +} + +func TestParallelFailingSubtestsA(t *testing.T) { + t.Parallel() + t.Run("TestFailingSubtestsA1", func(t *testing.T) { + t.Errorf("FAIL - %s", t.Name()) + }) + t.Run("TestFailingSubtestsA2", func(t *testing.T) { + t.Errorf("FAIL - %s", t.Name()) + }) +} + +func TestFailingSubtestsA(t *testing.T) { + t.Run("TestFailingSubtestsA1", func(t *testing.T) { + t.Errorf("FAIL - %s", t.Name()) + }) + t.Run("TestFailingSubtestsA2", func(t *testing.T) { + t.Errorf("FAIL - %s", t.Name()) + }) +} + +func TestFailingB(t *testing.T) { + t.Errorf("FAIL - %s", t.Name()) +} + +func TestFatalC(t *testing.T) { + t.Fatalf("FAIL - %s", t.Name()) +} + +func TestFatalD(t *testing.T) { + t.Fatalf("FAIL - %s", t.Name()) +} diff --git a/libgo/go/cmd/go/testdata/script/test_finished_subtest_goroutines.txt b/libgo/go/cmd/go/testdata/script/test_finished_subtest_goroutines.txt new file mode 100644 index 0000000..8db821e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_finished_subtest_goroutines.txt @@ -0,0 +1,52 @@ +# Regression test for https://golang.org/issue/45127: +# Goroutines for completed parallel subtests should exit immediately, +# not block until earlier subtests have finished. + +[short] skip + +! go test . +stdout 'panic: slow failure' +! stdout '\[chan send' + +-- go.mod -- +module golang.org/issue45127 + +go 1.16 +-- issue45127_test.go -- +package main + +import ( + "fmt" + "runtime" + "runtime/debug" + "sync" + "testing" +) + +func TestTestingGoroutineLeak(t *testing.T) { + debug.SetTraceback("all") + + var wg sync.WaitGroup + const nFast = 10 + + t.Run("slow", func(t *testing.T) { + t.Parallel() + wg.Wait() + for i := 0; i < nFast; i++ { + // If the subtest goroutines are going to park on the channel + // send, allow them to park now. If they're not going to park, + // make sure they have had a chance to run to completion so + // that they aren't spuriously parked when we panic. + runtime.Gosched() + } + panic("slow failure") + }) + + wg.Add(nFast) + for i := 0; i < nFast; i++ { + t.Run(fmt.Sprintf("leaky%d", i), func(t *testing.T) { + t.Parallel() + wg.Done() + }) + } +} diff --git a/libgo/go/cmd/go/testdata/script/test_flag.txt b/libgo/go/cmd/go/testdata/script/test_flag.txt new file mode 100644 index 0000000..0142b3f --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_flag.txt @@ -0,0 +1,40 @@ +[short] skip + +go test flag_test.go -v -args -v=7 # Two distinct -v flags +go test -v flag_test.go -args -v=7 # Two distinct -v flags + +# Using a custom flag mixed with regular 'go test' flags should be OK. +go test -count=1 -custom -args -v=7 + +# However, it should be an error to use custom flags when -i or -c are used, +# since we know for sure that no test binary will run at all. +! go test -i -custom +stderr '^go test: unknown flag -custom cannot be used with -i$' +! go test -c -custom +stderr '^go test: unknown flag -custom cannot be used with -c$' + +# The same should apply even if -c or -i come after a custom flag. +! go test -custom -c +stderr '^go test: unknown flag -custom cannot be used with -c$' + +-- go.mod -- +module m +-- flag_test.go -- +package flag_test + +import ( + "flag" + "log" + "testing" +) + +var v = flag.Int("v", 0, "v flag") + +var custom = flag.Bool("custom", false, "") + +// Run this as go test pkg -v=7 +func TestVFlagIsSet(t *testing.T) { + if *v != 7 { + log.Fatal("v flag not set") + } +} diff --git a/libgo/go/cmd/go/testdata/script/test_import_error_stack.txt b/libgo/go/cmd/go/testdata/script/test_import_error_stack.txt new file mode 100644 index 0000000..6c60f3d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_import_error_stack.txt @@ -0,0 +1,31 @@ +env GO111MODULE=off +! go test testdep/p1 +stderr 'package testdep/p1 \(test\)\n\timports testdep/p2\n\timports testdep/p3: build constraints exclude all Go files ' # check for full import stack +! go vet testdep/p1 +stderr 'package testdep/p1 \(test\)\n\timports testdep/p2\n\timports testdep/p3: build constraints exclude all Go files ' # check for full import stack + +env GO111MODULE=on +cd testdep +! go test testdep/p1 +stderr 'package testdep/p1 \(test\)\n\timports testdep/p2\n\timports testdep/p3: build constraints exclude all Go files ' # check for full import stack +! go vet testdep/p1 +stderr 'package testdep/p1 \(test\)\n\timports testdep/p2\n\timports testdep/p3: build constraints exclude all Go files ' # check for full import stack + +-- testdep/go.mod -- +module testdep + +go 1.16 +-- testdep/p1/p1.go -- +package p1 +-- testdep/p1/p1_test.go -- +package p1 + +import _ "testdep/p2" +-- testdep/p2/p2.go -- +package p2 + +import _ "testdep/p3" +-- testdep/p3/p3.go -- +// +build ignore + +package ignored diff --git a/libgo/go/cmd/go/testdata/script/test_json.txt b/libgo/go/cmd/go/testdata/script/test_json.txt new file mode 100644 index 0000000..cd5b0b9 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_json.txt @@ -0,0 +1,74 @@ +[gccgo] skip # gccgo does not have standard packages +[short] skip + +env GOCACHE=$WORK/tmp + +# Run go test -json on errors m/empty/pkg and m/skipper +# It would be nice to test that the output is interlaced +# but it seems to be impossible to do that in a short test +# that isn't also flaky. Just check that we get JSON output. +go test -json -short -v errors m/empty/pkg m/skipper + +# Check errors for run action +stdout '"Package":"errors"' +stdout '"Action":"run","Package":"errors"' + +# Check m/empty/pkg for output and skip actions +stdout '"Action":"output","Package":"m/empty/pkg","Output":".*no test files' +stdout '"Action":"skip","Package":"m/empty/pkg"' + +# Check skipper for output and skip actions +stdout '"Action":"output","Package":"m/skipper","Test":"Test","Output":"--- SKIP:' +stdout '"Action":"skip","Package":"m/skipper","Test":"Test"' + +# Run go test -json on errors and check it's cached +go test -json -short -v errors +stdout '"Action":"output","Package":"errors","Output":".*\(cached\)' + +go test -json -bench=NONE -short -v errors +stdout '"Package":"errors"' +stdout '"Action":"run"' + +# Test running test2json +go test -o $WORK/tmp/errors.test$GOEXE -c errors +go tool test2json -p errors $WORK/tmp/errors.test$GOEXE -test.v -test.short +stdout '"Package":"errors"' +stdout '"Action":"run"' +stdout '\{"Action":"pass","Package":"errors"\}' + +-- go.mod -- +module m + +go 1.16 +-- skipper/skip_test.go -- +package skipper + +import "testing" + +func Test(t *testing.T) { + t.Skip("skipping") +} +-- empty/pkg/pkg.go -- +package p +-- empty/pkgtest/pkg.go -- +package p +-- empty/pkgtest/test_test.go -- +package p +-- empty/pkgtestxtest/pkg.go -- +package p +-- empty/pkgtestxtest/test_test.go -- +package p +-- empty/pkgtestxtest/xtest_test.go -- +package p_test +-- empty/pkgxtest/pkg.go -- +package p +-- empty/pkgxtest/xtest_test.go -- +package p_test +-- empty/test/test_test.go -- +package p +-- empty/testxtest/test_test.go -- +package p +-- empty/testxtest/xtest_test.go -- +package p_test +-- empty/xtest/xtest_test.go -- +package p_test diff --git a/libgo/go/cmd/go/testdata/script/test_json_exit.txt b/libgo/go/cmd/go/testdata/script/test_json_exit.txt new file mode 100644 index 0000000..dc7ffb0 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_json_exit.txt @@ -0,0 +1,102 @@ +[short] skip + +go test -c -o mainpanic.exe ./mainpanic & +go test -c -o mainexit0.exe ./mainexit0 & +go test -c -o testpanic.exe ./testpanic & +go test -c -o testbgpanic.exe ./testbgpanic & +wait + +# Test binaries that panic in TestMain should be marked as failing. + +! go test -json ./mainpanic +stdout '"Action":"fail"' +! stdout '"Action":"pass"' + +! go tool test2json ./mainpanic.exe +stdout '"Action":"fail"' +! stdout '"Action":"pass"' + +# Test binaries that exit with status 0 should be marked as passing. + +go test -json ./mainexit0 +stdout '"Action":"pass"' +! stdout '"Action":"fail"' + +go tool test2json ./mainexit0.exe +stdout '"Action":"pass"' +! stdout '"Action":"fail"' + +# Test functions that panic should never be marked as passing +# (https://golang.org/issue/40132). + +! go test -json ./testpanic +stdout '"Action":"fail"' +! stdout '"Action":"pass"' + +! go tool test2json ./testpanic.exe -test.v +stdout '"Action":"fail"' +! stdout '"Action":"pass"' + +! go tool test2json ./testpanic.exe +stdout '"Action":"fail"' +! stdout '"Action":"pass"' + +# Tests that panic in a background goroutine should be marked as failing. + +! go test -json ./testbgpanic +stdout '"Action":"fail"' +! stdout '"Action":"pass"' + +! go tool test2json ./testbgpanic.exe -test.v +stdout '"Action":"fail"' +! stdout '"Action":"pass"' + +! go tool test2json ./testbgpanic.exe +stdout '"Action":"fail"' +! stdout '"Action":"pass"' + +-- go.mod -- +module m +go 1.14 +-- mainpanic/mainpanic_test.go -- +package mainpanic_test + +import "testing" + +func TestMain(m *testing.M) { + panic("haha no") +} +-- mainexit0/mainexit0_test.go -- +package mainexit0_test + +import ( + "fmt" + "os" + "testing" +) + +func TestMain(m *testing.M) { + fmt.Println("nothing to do") + os.Exit(0) +} +-- testpanic/testpanic_test.go -- +package testpanic_test + +import "testing" + +func TestPanic(*testing.T) { + panic("haha no") +} +-- testbgpanic/testbgpanic_test.go -- +package testbgpanic_test + +import "testing" + +func TestPanicInBackground(*testing.T) { + c := make(chan struct{}) + go func() { + panic("haha no") + close(c) + }() + <-c +} diff --git a/libgo/go/cmd/go/testdata/script/test_json_interleaved.txt b/libgo/go/cmd/go/testdata/script/test_json_interleaved.txt new file mode 100644 index 0000000..e2d349e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_json_interleaved.txt @@ -0,0 +1,27 @@ +# Regression test for https://golang.org/issue/40657: output from the main test +# function should be attributed correctly even if interleaved with the PAUSE +# line for a new parallel subtest. + +[short] skip + +go test -json +stdout '"Test":"TestWeirdTiming","Output":"[^"]* logging to outer again\\n"' + +-- go.mod -- +module example.com +go 1.15 +-- main_test.go -- +package main + +import ( + "testing" +) + +func TestWeirdTiming(outer *testing.T) { + outer.Run("pauser", func(pauser *testing.T) { + outer.Logf("logging to outer") + pauser.Parallel() + }) + + outer.Logf("logging to outer again") +} diff --git a/libgo/go/cmd/go/testdata/script/test_json_panic_exit.txt b/libgo/go/cmd/go/testdata/script/test_json_panic_exit.txt new file mode 100644 index 0000000..d0a7991 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_json_panic_exit.txt @@ -0,0 +1,69 @@ +# Verifies golang.org/issue/37555. + +[short] skip + +# 'go test -json' should say a test passes if it says it passes. +go test -json ./pass +stdout '"Action":"pass".*\n\z' +! stdout '"Test":.*\n\z' + +# 'go test -json' should say a test passes if it exits 0 and prints nothing. +# TODO(golang.org/issue/29062): this should fail in the future. +go test -json ./exit0main +stdout '"Action":"pass".*\n\z' +! stdout '"Test":.*\n\z' + +# 'go test -json' should say a test fails if it exits 1 and prints nothing. +! go test -json ./exit1main +stdout '"Action":"fail".*\n\z' +! stdout '"Test":.*\n\z' + +# 'go test -json' should say a test fails if it panics. +! go test -json ./panic +stdout '"Action":"fail".*\n\z' +! stdout '"Test":.*\n\z' + +-- go.mod -- +module example.com/test + +go 1.14 + +-- pass/pass_test.go -- +package pass_test + +import "testing" + +func TestPass(t *testing.T) {} + +-- exit0main/exit0main_test.go -- +package exit0_test + +import ( + "os" + "testing" +) + +func TestMain(m *testing.M) { + os.Exit(0) +} + +-- exit1main/exit1main_test.go -- +package exit1_test + +import ( + "os" + "testing" +) + +func TestMain(m *testing.M) { + os.Exit(1) +} + +-- panic/panic_test.go -- +package panic_test + +import "testing" + +func TestPanic(t *testing.T) { + panic("oh no") +} diff --git a/libgo/go/cmd/go/testdata/script/test_main.txt b/libgo/go/cmd/go/testdata/script/test_main.txt new file mode 100644 index 0000000..25d02e4 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_main.txt @@ -0,0 +1,92 @@ +# Test TestMain +go test standalone_main_normal_test.go +! stdout '^ok.*\[no tests to run\]' +! stderr '^ok.*\[no tests to run\]' +stdout '^ok' + +# Test TestMain sees testing flags +go test standalone_testmain_flag_test.go +stdout '^ok.*\[no tests to run\]' + +# Test TestMain with wrong signature (Issue #22388) +! go test standalone_main_wrong_test.go +stderr 'wrong signature for TestMain, must be: func TestMain\(m \*testing.M\)' + +# Test TestMain does not call os.Exit (Issue #34129) +! go test standalone_testmain_not_call_os_exit_test.go +! stdout '^ok' + +-- standalone_main_normal_test.go -- +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package standalone_main_normal_test + +import "testing" + +func TestMain(t *testing.T) { +} +-- standalone_main_wrong_test.go -- +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package standalone_main_wrong_test + +import "testing" + +func TestMain(m *testing.Main) { +} +-- standalone_testmain_flag_test.go -- +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package standalone_testmain_flag_test + +import ( + "flag" + "fmt" + "os" + "testing" +) + +func TestMain(m *testing.M) { + // A TestMain should be able to access testing flags if it calls + // flag.Parse without needing to use testing.Init. + flag.Parse() + found := false + flag.VisitAll(func(f *flag.Flag) { + if f.Name == "test.count" { + found = true + } + }) + if !found { + fmt.Println("testing flags not registered") + os.Exit(1) + } + os.Exit(m.Run()) +} +-- standalone_testmain_not_call_os_exit_test.go -- +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package standalone_testmain_not_call_os_exit_test + +import ( + "testing" +) + +func TestWillFail(t *testing.T) { + t.Error("this test will fail.") +} + +func TestMain(m *testing.M) { + defer func() { + recover() + }() + exit := m.Run() + panic(exit) +} diff --git a/libgo/go/cmd/go/testdata/script/test_main_panic.txt b/libgo/go/cmd/go/testdata/script/test_main_panic.txt new file mode 100644 index 0000000..45887c5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_main_panic.txt @@ -0,0 +1,30 @@ +[short] skip +[!race] skip + +! go test -v -race main_panic/testmain_parallel_sub_panic_test.go +! stdout 'DATA RACE' +-- main_panic/testmain_parallel_sub_panic_test.go -- +package testmain_parallel_sub_panic_test + +import "testing" + +func setup() { println("setup()") } +func teardown() { println("teardown()") } +func TestA(t *testing.T) { + t.Run("1", func(t *testing.T) { + t.Run("1", func(t *testing.T) { + t.Parallel() + panic("A/1/1 panics") + }) + t.Run("2", func(t *testing.T) { + t.Parallel() + println("A/1/2 is ok") + }) + }) +} + +func TestMain(m *testing.M) { + setup() + defer teardown() + m.Run() +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_main_twice.txt b/libgo/go/cmd/go/testdata/script/test_main_twice.txt new file mode 100644 index 0000000..f32d4fc --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_main_twice.txt @@ -0,0 +1,27 @@ +[short] skip + +env GOCACHE=$WORK/tmp +go test -v multimain +stdout -count=2 notwithstanding # check tests ran twice + +-- go.mod -- +module multimain + +go 1.16 +-- multimain_test.go -- +package multimain_test + +import "testing" + +func TestMain(m *testing.M) { + // Some users run m.Run multiple times, changing + // some kind of global state between runs. + // This used to work so I guess now it has to keep working. + // See golang.org/issue/23129. + m.Run() + m.Run() +} + +func Test(t *testing.T) { + t.Log("notwithstanding") +} diff --git a/libgo/go/cmd/go/testdata/script/test_match_benchmark_labels.txt b/libgo/go/cmd/go/testdata/script/test_match_benchmark_labels.txt new file mode 100644 index 0000000..13c4007 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_match_benchmark_labels.txt @@ -0,0 +1,18 @@ +# Benchmark labels, file outside gopath +# TODO(matloob): This test was called TestBenchmarkLabelsOutsideGOPATH +# why "OutsideGOPATH"? Does the go command need to be run outside GOPATH? +# Do the files need to exist outside GOPATH? +cp $GOPATH/src/standalone_benchmark_test.go $WORK/tmp/standalone_benchmark_test.go +go test -run '^$' -bench . $WORK/tmp/standalone_benchmark_test.go +stdout '^goos: '$GOOS +stdout '^goarch: '$GOARCH +! stdout '^pkg:' +! stderr '^pkg:' + +-- standalone_benchmark_test.go -- +package standalone_benchmark + +import "testing" + +func Benchmark(b *testing.B) { +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_match_no_benchmarks.txt b/libgo/go/cmd/go/testdata/script/test_match_no_benchmarks.txt new file mode 100644 index 0000000..30f4be8 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_match_no_benchmarks.txt @@ -0,0 +1,13 @@ +# Matches no benchmarks +go test -run '^$' -bench ThisWillNotMatch standalone_benchmark_test.go +! stdout '^ok.*\[no tests to run\]' +! stderr '^ok.*\[no tests to run\]' +stdout '^ok' + +-- standalone_benchmark_test.go -- +package standalone_benchmark + +import "testing" + +func Benchmark(b *testing.B) { +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_match_no_subtests.txt b/libgo/go/cmd/go/testdata/script/test_match_no_subtests.txt new file mode 100644 index 0000000..7abb1eb --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_match_no_subtests.txt @@ -0,0 +1,12 @@ +# The subtests don't match +go test -run Test/ThisWillNotMatch standalone_sub_test.go +stdout '^ok.*\[no tests to run\]' + +-- standalone_sub_test.go -- +package standalone_sub_test + +import "testing" + +func Test(t *testing.T) { + t.Run("Sub", func(t *testing.T) {}) +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_match_no_subtests_failure.txt b/libgo/go/cmd/go/testdata/script/test_match_no_subtests_failure.txt new file mode 100644 index 0000000..b3c5b92 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_match_no_subtests_failure.txt @@ -0,0 +1,15 @@ +# Matches no subtests, but parent test still fails +! go test -run TestThatFails/ThisWillNotMatch standalone_fail_sub_test.go +! stdout '^ok.*\[no tests to run\]' +! stderr '^ok.*\[no tests to run\]' +stdout 'FAIL' + +-- standalone_fail_sub_test.go -- +package standalone_fail_sub_test + +import "testing" + +func TestThatFails(t *testing.T) { + t.Run("Sub", func(t *testing.T) {}) + t.Fail() +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_match_no_subtests_parallel.txt b/libgo/go/cmd/go/testdata/script/test_match_no_subtests_parallel.txt new file mode 100644 index 0000000..11c734c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_match_no_subtests_parallel.txt @@ -0,0 +1,19 @@ +# Matches no subtests, parallel +go test -run Test/Sub/ThisWillNotMatch standalone_parallel_sub_test.go +stdout '^ok.*\[no tests to run\]' + +-- standalone_parallel_sub_test.go -- +package standalone_parallel_sub_test + +import "testing" + +func Test(t *testing.T) { + ch := make(chan bool, 1) + t.Run("Sub", func(t *testing.T) { + t.Parallel() + <-ch + t.Run("Nested", func(t *testing.T) {}) + }) + // Ensures that Sub will finish after its t.Run call already returned. + ch <- true +} diff --git a/libgo/go/cmd/go/testdata/script/test_match_no_tests.txt b/libgo/go/cmd/go/testdata/script/test_match_no_tests.txt new file mode 100644 index 0000000..1ad2097 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_match_no_tests.txt @@ -0,0 +1,11 @@ +# Matches no tests +go test -run ThisWillNotMatch standalone_test.go +stdout '^ok.*\[no tests to run\]' + +-- standalone_test.go -- +package standalone_test + +import "testing" + +func Test(t *testing.T) { +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_match_no_tests_build_failure.txt b/libgo/go/cmd/go/testdata/script/test_match_no_tests_build_failure.txt new file mode 100644 index 0000000..e1c9643 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_match_no_tests_build_failure.txt @@ -0,0 +1,19 @@ +# Test that when there's a build failure and a -run flag that doesn't match, +# that the error for not matching tests does not override the error for +# the build failure. + +! go test -run ThisWillNotMatch syntaxerror +! stderr '(?m)^ok.*\[no tests to run\]' +stdout 'FAIL' + +-- go.mod -- +module syntaxerror + +go 1.16 +-- x.go -- +package p +-- x_test.go -- +package p + +func f() (x.y, z int) { +} diff --git a/libgo/go/cmd/go/testdata/script/test_match_no_tests_with_subtests.txt b/libgo/go/cmd/go/testdata/script/test_match_no_tests_with_subtests.txt new file mode 100644 index 0000000..0d94918 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_match_no_tests_with_subtests.txt @@ -0,0 +1,12 @@ +# Matches no tests with subtests +go test -run ThisWillNotMatch standalone_sub_test.go +stdout '^ok.*\[no tests to run\]' + +-- standalone_sub_test.go -- +package standalone_sub_test + +import "testing" + +func Test(t *testing.T) { + t.Run("Sub", func(t *testing.T) {}) +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_match_only_benchmarks.txt b/libgo/go/cmd/go/testdata/script/test_match_only_benchmarks.txt new file mode 100644 index 0000000..5dfb96e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_match_only_benchmarks.txt @@ -0,0 +1,13 @@ +# Matches only benchmarks +go test -run '^$' -bench . standalone_benchmark_test.go +! stdout '^ok.*\[no tests to run\]' +! stderr '^ok.*\[no tests to run\]' +stdout '^ok' + +-- standalone_benchmark_test.go -- +package standalone_benchmark + +import "testing" + +func Benchmark(b *testing.B) { +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_match_only_example.txt b/libgo/go/cmd/go/testdata/script/test_match_only_example.txt new file mode 100644 index 0000000..515ccb3 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_match_only_example.txt @@ -0,0 +1,31 @@ +[short] skip + +# Check that it's okay for test pattern to match only examples. +go test -run Example example1_test.go +! stderr '^ok.*\[no tests to run\]' +stdout '^ok' + +-- example1_test.go -- +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Make sure that go test runs Example_Z before Example_A, preserving source order. + +package p + +import "fmt" + +var n int + +func Example_Z() { + n++ + fmt.Println(n) + // Output: 1 +} + +func Example_A() { + n++ + fmt.Println(n) + // Output: 2 +} diff --git a/libgo/go/cmd/go/testdata/script/test_match_only_subtests.txt b/libgo/go/cmd/go/testdata/script/test_match_only_subtests.txt new file mode 100644 index 0000000..beea895 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_match_only_subtests.txt @@ -0,0 +1,14 @@ +# Matches only subtests +go test -run Test/Sub standalone_sub_test.go +! stdout '^ok.*\[no tests to run\]' +! stderr '^ok.*\[no tests to run\]' +stdout '^ok' + +-- standalone_sub_test.go -- +package standalone_sub_test + +import "testing" + +func Test(t *testing.T) { + t.Run("Sub", func(t *testing.T) {}) +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_match_only_subtests_parallel.txt b/libgo/go/cmd/go/testdata/script/test_match_only_subtests_parallel.txt new file mode 100644 index 0000000..11872c2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_match_only_subtests_parallel.txt @@ -0,0 +1,21 @@ +# Matches only subtests, parallel +go test -run Test/Sub/Nested standalone_parallel_sub_test.go +! stdout '^ok.*\[no tests to run\]' +! stderr '^ok.*\[no tests to run\]' +stdout '^ok' + +-- standalone_parallel_sub_test.go -- +package standalone_parallel_sub_test + +import "testing" + +func Test(t *testing.T) { + ch := make(chan bool, 1) + t.Run("Sub", func(t *testing.T) { + t.Parallel() + <-ch + t.Run("Nested", func(t *testing.T) {}) + }) + // Ensures that Sub will finish after its t.Run call already returned. + ch <- true +} diff --git a/libgo/go/cmd/go/testdata/script/test_match_only_tests.txt b/libgo/go/cmd/go/testdata/script/test_match_only_tests.txt new file mode 100644 index 0000000..9185793 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_match_only_tests.txt @@ -0,0 +1,13 @@ +# Matches only tests +go test -run Test standalone_test.go +! stdout '^ok.*\[no tests to run\]' +! stderr '^ok.*\[no tests to run\]' +stdout '^ok' + +-- standalone_test.go -- +package standalone_test + +import "testing" + +func Test(t *testing.T) { +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_minus_n.txt b/libgo/go/cmd/go/testdata/script/test_minus_n.txt new file mode 100644 index 0000000..9900dbc --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_minus_n.txt @@ -0,0 +1,14 @@ +# The intent here is to verify that 'go test -n' works without crashing. +# Any test will do. + +go test -n x_test.go + +-- x_test.go -- +package x_test + +import ( + "testing" +) + +func TestEmpty(t *testing.T) { +} diff --git a/libgo/go/cmd/go/testdata/script/test_no_run_example.txt b/libgo/go/cmd/go/testdata/script/test_no_run_example.txt new file mode 100644 index 0000000..53ac755 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_no_run_example.txt @@ -0,0 +1,30 @@ +go test -v norunexample +stdout 'File with non-runnable example was built.' + +-- go.mod -- +module norunexample + +go 1.16 +-- example_test.go -- +package pkg_test + +import "os" + +func init() { + os.Stdout.Write([]byte("File with non-runnable example was built.\n")) +} + +func Example_test() { + // This test will not be run, it has no "Output:" comment. +} +-- test_test.go -- +package pkg + +import ( + "os" + "testing" +) + +func TestBuilt(t *testing.T) { + os.Stdout.Write([]byte("A normal test was executed.\n")) +} diff --git a/libgo/go/cmd/go/testdata/script/test_no_tests.txt b/libgo/go/cmd/go/testdata/script/test_no_tests.txt new file mode 100644 index 0000000..2d624d1 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_no_tests.txt @@ -0,0 +1,15 @@ +# Tests issue #26242 + +go test testnorun +stdout 'testnorun\t\[no test files\]' + +-- go.mod -- +module testnorun + +go 1.16 +-- p.go -- +package p + +func init() { + panic("go test must not link and run test binaries without tests") +} diff --git a/libgo/go/cmd/go/testdata/script/test_overlay.txt b/libgo/go/cmd/go/testdata/script/test_overlay.txt new file mode 100644 index 0000000..b6bdc11 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_overlay.txt @@ -0,0 +1,24 @@ +[short] skip + +cd $WORK/gopath/src/foo +go test -list=. -overlay=overlay.json . +stdout 'TestBar' + +-- go.mod -- +module test.pkg +-- foo/foo_test.go -- +package foo + +import "testing" + +func TestFoo(t *testing.T) { } +-- tmp/bar_test.go -- +package foo + +import "testing" + +func TestBar(t *testing.T) { + t.Fatal("dummy failure") +} +-- foo/overlay.json -- +{"Replace": {"foo_test.go": "../tmp/bar_test.go"}} diff --git a/libgo/go/cmd/go/testdata/script/test_parallel_number.txt b/libgo/go/cmd/go/testdata/script/test_parallel_number.txt new file mode 100644 index 0000000..4eb9794 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_parallel_number.txt @@ -0,0 +1,25 @@ +[short] skip + +# go test -parallel -1 shouldn't work +! go test -parallel -1 standalone_parallel_sub_test.go +stdout '-parallel can only be given' + +# go test -parallel 0 shouldn't work +! go test -parallel 0 standalone_parallel_sub_test.go +stdout '-parallel can only be given' + +-- standalone_parallel_sub_test.go -- +package standalone_parallel_sub_test + +import "testing" + +func Test(t *testing.T) { + ch := make(chan bool, 1) + t.Run("Sub", func(t *testing.T) { + t.Parallel() + <-ch + t.Run("Nested", func(t *testing.T) {}) + }) + // Ensures that Sub will finish after its t.Run call already returned. + ch <- true +} diff --git a/libgo/go/cmd/go/testdata/script/test_profile.txt b/libgo/go/cmd/go/testdata/script/test_profile.txt new file mode 100644 index 0000000..4bfa2cc --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_profile.txt @@ -0,0 +1,19 @@ +[gccgo] skip 'gccgo has no standard packages' +[short] skip + +# Check go test -cpuprofile creates errors.test +go test -cpuprofile errors.prof errors +exists -exec errors.test$GOEXE + +# Check go test -cpuprofile -o myerrors.test creates errors.test +go test -cpuprofile errors.prof -o myerrors.test$GOEXE errors +exists -exec myerrors.test$GOEXE + +# Check go test -mutexprofile creates errors.test +go test -mutexprofile errors.prof errors +exists -exec errors.test$GOEXE + +# Check go test -mutexprofile -o myerrors.test creates errors.test +go test -mutexprofile errors.prof -o myerrors.test$GOEXE errors +exists -exec myerrors.test$GOEXE + diff --git a/libgo/go/cmd/go/testdata/script/test_race.txt b/libgo/go/cmd/go/testdata/script/test_race.txt new file mode 100644 index 0000000..2ffea46 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_race.txt @@ -0,0 +1,51 @@ +[short] skip +[!race] skip + +go test testrace + +! go test -race testrace +stdout 'FAIL: TestRace' +! stdout 'PASS' +! stderr 'PASS' + +! go test -race testrace -run XXX -bench . +stdout 'FAIL: BenchmarkRace' +! stdout 'PASS' +! stderr 'PASS' + +-- go.mod -- +module testrace + +go 1.16 +-- race_test.go -- +package testrace + +import "testing" + +func TestRace(t *testing.T) { + for i := 0; i < 10; i++ { + c := make(chan int) + x := 1 + go func() { + x = 2 + c <- 1 + }() + x = 3 + <-c + _ = x + } +} + +func BenchmarkRace(b *testing.B) { + for i := 0; i < b.N; i++ { + c := make(chan int) + x := 1 + go func() { + x = 2 + c <- 1 + }() + x = 3 + <-c + _ = x + } +} diff --git a/libgo/go/cmd/go/testdata/script/test_race_cover_mode_issue20435.txt b/libgo/go/cmd/go/testdata/script/test_race_cover_mode_issue20435.txt new file mode 100644 index 0000000..eacc882 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_race_cover_mode_issue20435.txt @@ -0,0 +1,48 @@ +[short] skip +[!race] skip + +# Make sure test is functional. +go test testrace + +# Now, check that -race -covermode=set is not allowed. +! go test -race -covermode=set testrace +stderr '-covermode must be "atomic", not "set", when -race is enabled' +! stdout PASS +! stderr PASS + +-- go.mod -- +module testrace + +go 1.16 +-- race_test.go -- +package testrace + +import "testing" + +func TestRace(t *testing.T) { + for i := 0; i < 10; i++ { + c := make(chan int) + x := 1 + go func() { + x = 2 + c <- 1 + }() + x = 3 + <-c + _ = x + } +} + +func BenchmarkRace(b *testing.B) { + for i := 0; i < b.N; i++ { + c := make(chan int) + x := 1 + go func() { + x = 2 + c <- 1 + }() + x = 3 + <-c + _ = x + } +} diff --git a/libgo/go/cmd/go/testdata/script/test_race_install.txt b/libgo/go/cmd/go/testdata/script/test_race_install.txt new file mode 100644 index 0000000..8b1f343 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_race_install.txt @@ -0,0 +1,18 @@ +[!race] skip +[short] skip + +mkdir $WORKDIR/tmp/pkg +go install -race -pkgdir=$WORKDIR/tmp/pkg std + +# Make sure go test -i -race doesn't rebuild cached packages +go test -race -pkgdir=$WORKDIR/tmp/pkg -i -v empty/pkg +cmp stderr stderr.txt + +-- go.mod -- +module empty + +go 1.16 +-- pkg/pkg.go -- +package p +-- stderr.txt -- +go test: -i flag is deprecated diff --git a/libgo/go/cmd/go/testdata/script/test_race_install_cgo.txt b/libgo/go/cmd/go/testdata/script/test_race_install_cgo.txt new file mode 100644 index 0000000..e1fe4f2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_race_install_cgo.txt @@ -0,0 +1,91 @@ +# Tests Issue #10500 + +[!race] skip + +env GOBIN=$WORK/bin +go install m/mtime m/sametime + +go tool -n cgo +cp stdout cgopath.txt +exec $GOBIN/mtime cgopath.txt # get the mtime of the file whose name is in cgopath.txt +cp stdout cgotime_before.txt + + # For this test, we don't actually care whether 'go test -race -i' succeeds. + # It may fail if GOROOT is read-only (perhaps it was installed as root). + # We only care that it does not overwrite cmd/cgo regardless. +? go test -race -i runtime/race + +exec $GOBIN/mtime cgopath.txt # get the mtime of the file whose name is in cgopath.txt +cp stdout cgotime_after.txt +exec $GOBIN/sametime cgotime_before.txt cgotime_after.txt + +-- go.mod -- +module m + +go 1.16 +-- mtime/mtime.go -- +package main + +import ( + "encoding/json" + "fmt" + "os" + "strings" +) + +func main() { + b, err := os.ReadFile(os.Args[1]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + filename := strings.TrimSpace(string(b)) + info, err := os.Stat(filename) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if err := json.NewEncoder(os.Stdout).Encode(info.ModTime()); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} +-- sametime/sametime.go -- +package main + +import ( + "encoding/json" + "fmt" + "os" + "time" +) + + +func main() { + var t1 time.Time + b1, err := os.ReadFile(os.Args[1]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if err := json.Unmarshal(b1, &t1); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + var t2 time.Time + b2, err := os.ReadFile(os.Args[2]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if err := json.Unmarshal(b2, &t2); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + if !t1.Equal(t2) { + fmt.Fprintf(os.Stderr, "time in %v (%v) is not the same as time in %v (%v)", os.Args[1], t1, os.Args[2], t2) + os.Exit(1) + } +} diff --git a/libgo/go/cmd/go/testdata/test_regexps.txt b/libgo/go/cmd/go/testdata/script/test_regexps.txt index a616195c..2f33080 100644 --- a/libgo/go/cmd/go/testdata/test_regexps.txt +++ b/libgo/go/cmd/go/testdata/script/test_regexps.txt @@ -35,7 +35,11 @@ stdout -count=1 '^ z_test.go:18: LOG: XX running N=1$' # a large number, and the last iteration count prints right before the results. stdout -count=2 '^ x_test.go:15: LOG: Y running N=[1-9]\d{4,}\nBenchmarkX/Y\s+\d+' --- testregexp/x_test.go -- +-- go.mod -- +module testregexp + +go 1.16 +-- x_test.go -- package x import "testing" @@ -53,7 +57,7 @@ func BenchmarkX(b *testing.B) { b.Logf("LOG: Y running N=%d", b.N) }) } --- testregexp/z_test.go -- +-- z_test.go -- package x import "testing" diff --git a/libgo/go/cmd/go/testdata/script/test_relative_cmdline.txt b/libgo/go/cmd/go/testdata/script/test_relative_cmdline.txt new file mode 100644 index 0000000..2f9c80f --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_relative_cmdline.txt @@ -0,0 +1,50 @@ +# Relative imports in command line package + +# Run tests outside GOPATH. +env GOPATH=$WORK/tmp + +go test ./testimport/p.go ./testimport/p_test.go ./testimport/x_test.go +stdout '^ok' + +-- testimport/p.go -- +package p + +func F() int { return 1 } +-- testimport/p1/p1.go -- +package p1 + +func F() int { return 1 } +-- testimport/p2/p2.go -- +package p2 + +func F() int { return 1 } +-- testimport/p_test.go -- +package p + +import ( + "./p1" + + "testing" +) + +func TestF(t *testing.T) { + if F() != p1.F() { + t.Fatal(F()) + } +} +-- testimport/x_test.go -- +package p_test + +import ( + . "../testimport" + + "./p2" + + "testing" +) + +func TestF1(t *testing.T) { + if F() != p2.F() { + t.Fatal(F()) + } +}
\ No newline at end of file diff --git a/libgo/go/cmd/go/testdata/script/test_relative_import.txt b/libgo/go/cmd/go/testdata/script/test_relative_import.txt new file mode 100644 index 0000000..938a875 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_relative_import.txt @@ -0,0 +1,31 @@ +# Relative imports in go test +env GO111MODULE=off # relative import not supported in module mode + +# Run tests outside GOPATH. +env GOPATH=$WORK/tmp + +go test ./testimport +stdout '^ok' + +-- testimport/p.go -- +package p + +func F() int { return 1 } +-- testimport/p1/p1.go -- +package p1 + +func F() int { return 1 } +-- testimport/p_test.go -- +package p + +import ( + "./p1" + + "testing" +) + +func TestF(t *testing.T) { + if F() != p1.F() { + t.Fatal(F()) + } +} diff --git a/libgo/go/cmd/go/testdata/script/test_relative_import_dash_i.txt b/libgo/go/cmd/go/testdata/script/test_relative_import_dash_i.txt new file mode 100644 index 0000000..b2716d8 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_relative_import_dash_i.txt @@ -0,0 +1,32 @@ +# Relative imports in go test -i +env GO111MODULE=off # relative import not supported in module mode + +# Run tests outside GOPATH. +env GOPATH=$WORK/tmp + +# Check that it's safe to pass -i (which installs dependencies in $GOPATH/pkg) to go test. +! stale runtime # don't let test -i overwrite runtime +go test -i ./testimport + +-- testimport/p.go -- +package p + +func F() int { return 1 } +-- testimport/p1/p1.go -- +package p1 + +func F() int { return 1 } +-- testimport/p_test.go -- +package p + +import ( + "./p1" + + "testing" +) + +func TestF(t *testing.T) { + if F() != p1.F() { + t.Fatal(F()) + } +} diff --git a/libgo/go/cmd/go/testdata/script/test_script_cmdcd.txt b/libgo/go/cmd/go/testdata/script/test_script_cmdcd.txt new file mode 100644 index 0000000..6e6f67e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_script_cmdcd.txt @@ -0,0 +1,13 @@ +# Tests that after a cd command, where usually the UNIX path separator is used, +# a match against $PWD does not fail on Windows. + +cd $WORK/a/b/c/pkg + +go list -find -f {{.Root}} +stdout $PWD + +-- $WORK/a/b/c/pkg/go.mod -- +module pkg + +-- $WORK/a/b/c/pkg/pkg.go -- +package pkg diff --git a/libgo/go/cmd/go/testdata/script/test_shuffle.txt b/libgo/go/cmd/go/testdata/script/test_shuffle.txt new file mode 100644 index 0000000..3a50605 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_shuffle.txt @@ -0,0 +1,148 @@ +# Shuffle order of tests and benchmarks + +# Run tests +go test -v foo_test.go +! stdout '-test.shuffle ' +stdout '(?s)TestOne(.*)TestTwo(.*)TestThree' + +go test -v -shuffle=off foo_test.go +! stdout '-test.shuffle ' +stdout '(?s)TestOne(.*)TestTwo(.*)TestThree' + +go test -v -shuffle=42 foo_test.go +stdout '^-test.shuffle 42' +stdout '(?s)TestThree(.*)TestOne(.*)TestTwo' + +go test -v -shuffle=43 foo_test.go +stdout '^-test.shuffle 43' +stdout '(?s)TestThree(.*)TestTwo(.*)TestOne' + +go test -v -shuffle=44 foo_test.go +stdout '^-test.shuffle 44' +stdout '(?s)TestOne(.*)TestThree(.*)TestTwo' + +go test -v -shuffle=0 foo_test.go +stdout '^-test.shuffle 0' +stdout '(?s)TestTwo(.*)TestOne(.*)TestThree' + +go test -v -shuffle -1 foo_test.go +stdout '^-test.shuffle -1' +stdout '(?s)TestThree(.*)TestOne(.*)TestTwo' + +go test -v -shuffle=on foo_test.go +stdout '^-test.shuffle ' +stdout '(?s)=== RUN TestOne(.*)--- PASS: TestOne' +stdout '(?s)=== RUN TestTwo(.*)--- PASS: TestTwo' +stdout '(?s)=== RUN TestThree(.*)--- PASS: TestThree' + + +# Run tests and benchmarks +go test -v -bench=. foo_test.go +! stdout '-test.shuffle ' +stdout '(?s)TestOne(.*)TestTwo(.*)TestThree(.*)BenchmarkOne(.*)BenchmarkTwo(.*)BenchmarkThree' + +go test -v -bench=. -shuffle=off foo_test.go +! stdout '-test.shuffle ' +stdout '(?s)TestOne(.*)TestTwo(.*)TestThree(.*)BenchmarkOne(.*)BenchmarkTwo(.*)BenchmarkThree' + +go test -v -bench=. -shuffle=42 foo_test.go +stdout '^-test.shuffle 42' +stdout '(?s)TestThree(.*)TestOne(.*)TestTwo(.*)BenchmarkThree(.*)BenchmarkOne(.*)BenchmarkTwo' + +go test -v -bench=. -shuffle=43 foo_test.go +stdout '^-test.shuffle 43' +stdout '(?s)TestThree(.*)TestTwo(.*)TestOne(.*)BenchmarkThree(.*)BenchmarkOne(.*)BenchmarkTwo' + +go test -v -bench=. -shuffle=44 foo_test.go +stdout '^-test.shuffle 44' +stdout '(?s)TestOne(.*)TestThree(.*)TestTwo(.*)BenchmarkTwo(.*)BenchmarkOne(.*)BenchmarkThree' + +go test -v -bench=. -shuffle=0 foo_test.go +stdout '^-test.shuffle 0' +stdout '(?s)TestTwo(.*)TestOne(.*)TestThree(.*)BenchmarkThree(.*)BenchmarkOne(.*)BenchmarkTwo' + +go test -v -bench=. -shuffle -1 foo_test.go +stdout '^-test.shuffle -1' +stdout '(?s)TestThree(.*)TestOne(.*)TestTwo(.*)BenchmarkOne(.*)BenchmarkThree(.*)BenchmarkTwo' + +go test -v -bench=. -shuffle=on foo_test.go +stdout '^-test.shuffle ' +stdout '(?s)=== RUN TestOne(.*)--- PASS: TestOne' +stdout '(?s)=== RUN TestTwo(.*)--- PASS: TestTwo' +stdout '(?s)=== RUN TestThree(.*)--- PASS: TestThree' +stdout -count=2 'BenchmarkOne' +stdout -count=2 'BenchmarkTwo' +stdout -count=2 'BenchmarkThree' + + +# When running go test -count=N, each of the N runs distinct runs should maintain the same +# shuffled order of these tests. +go test -v -shuffle=43 -count=4 foo_test.go +stdout '^-test.shuffle 43' +stdout '(?s)TestThree(.*)TestTwo(.*)TestOne(.*)TestThree(.*)TestTwo(.*)TestOne(.*)TestThree(.*)TestTwo(.*)TestOne(.*)TestThree(.*)TestTwo(.*)TestOne' + +go test -v -bench=. -shuffle=44 -count=2 foo_test.go +stdout '^-test.shuffle 44' +stdout '(?s)TestOne(.*)TestThree(.*)TestTwo(.*)TestOne(.*)TestThree(.*)TestTwo(.*)BenchmarkTwo(.*)BenchmarkOne(.*)BenchmarkThree(.*)' + + +# The feature should work with test binaries as well +go test -c +exec ./m.test -test.shuffle=off +! stdout '^-test.shuffle ' + +exec ./m.test -test.shuffle=on +stdout '^-test.shuffle ' + +exec ./m.test -test.v -test.bench=. -test.shuffle=0 foo_test.go +stdout '^-test.shuffle 0' +stdout '(?s)TestTwo(.*)TestOne(.*)TestThree(.*)BenchmarkThree(.*)BenchmarkOne(.*)BenchmarkTwo' + +exec ./m.test -test.v -test.bench=. -test.shuffle=123 foo_test.go +stdout '^-test.shuffle 123' +stdout '(?s)TestThree(.*)TestOne(.*)TestTwo(.*)BenchmarkThree(.*)BenchmarkTwo(.*)BenchmarkOne' + +exec ./m.test -test.v -test.bench=. -test.shuffle=-1 foo_test.go +stdout '^-test.shuffle -1' +stdout '(?s)TestThree(.*)TestOne(.*)TestTwo(.*)BenchmarkOne(.*)BenchmarkThree(.*)BenchmarkTwo' + +exec ./m.test -test.v -test.bench=. -test.shuffle=44 -test.count=2 foo_test.go +stdout '^-test.shuffle 44' +stdout '(?s)TestOne(.*)TestThree(.*)TestTwo(.*)TestOne(.*)TestThree(.*)TestTwo(.*)BenchmarkTwo(.*)BenchmarkOne(.*)BenchmarkThree(.*)' + + +# Negative testcases for invalid input +! go test -shuffle -count=2 +stderr 'invalid value "-count=2" for flag -shuffle: -shuffle argument must be "on", "off", or an int64: strconv.ParseInt: parsing "-count=2": invalid syntax' + +! go test -shuffle= +stderr '(?s)invalid value "" for flag -shuffle: -shuffle argument must be "on", "off", or an int64: strconv.ParseInt: parsing "": invalid syntax' + +! go test -shuffle=' ' +stderr '(?s)invalid value " " for flag -shuffle: -shuffle argument must be "on", "off", or an int64: strconv.ParseInt: parsing " ": invalid syntax' + +! go test -shuffle=true +stderr 'invalid value "true" for flag -shuffle: -shuffle argument must be "on", "off", or an int64: strconv.ParseInt: parsing "true": invalid syntax' + +! go test -shuffle='abc' +stderr 'invalid value "abc" for flag -shuffle: -shuffle argument must be "on", "off", or an int64: strconv.ParseInt: parsing "abc": invalid syntax' + +-- go.mod -- +module m + +go 1.16 +-- foo_test.go -- +package foo + +import "testing" + +func TestOne(t *testing.T) {} +func TestTwo(t *testing.T) {} +func TestThree(t *testing.T) {} + +func BenchmarkOne(b *testing.B) {} +func BenchmarkTwo(b *testing.B) {} +func BenchmarkThree(b *testing.B) {} + +-- foo.go -- +package foo diff --git a/libgo/go/cmd/go/testdata/script/test_source_order.txt b/libgo/go/cmd/go/testdata/script/test_source_order.txt new file mode 100644 index 0000000..2865276 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_source_order.txt @@ -0,0 +1,54 @@ +[short] skip + +# Control +! go test example2_test.go example1_test.go + +# This test only passes if the source order is preserved +go test example1_test.go example2_test.go + +-- example1_test.go -- +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Make sure that go test runs Example_Z before Example_A, preserving source order. + +package p + +import "fmt" + +var n int + +func Example_Z() { + n++ + fmt.Println(n) + // Output: 1 +} + +func Example_A() { + n++ + fmt.Println(n) + // Output: 2 +} +-- example2_test.go -- +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Make sure that go test runs Example_Y before Example_B, preserving source order. + +package p + +import "fmt" + +func Example_Y() { + n++ + fmt.Println(n) + // Output: 3 +} + +func Example_B() { + n++ + fmt.Println(n) + // Output: 4 +} diff --git a/libgo/go/cmd/go/testdata/script/test_syntax_error_says_fail.txt b/libgo/go/cmd/go/testdata/script/test_syntax_error_says_fail.txt new file mode 100644 index 0000000..44ff6e2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_syntax_error_says_fail.txt @@ -0,0 +1,25 @@ +# Test that the error message for a syntax error in a test go file +# says FAIL. + +env GO111MODULE=off +! go test syntaxerror +stderr 'x_test.go:' # check that the error is diagnosed +stdout 'FAIL' # check that go test says FAIL + +env GO111MODULE=on +cd syntaxerror +! go test syntaxerror +stderr 'x_test.go:' # check that the error is diagnosed +stdout 'FAIL' # check that go test says FAIL + +-- syntaxerror/go.mod -- +module syntaxerror + +go 1.16 +-- syntaxerror/x.go -- +package p +-- syntaxerror/x_test.go -- +package p + +func f() (x.y, z int) { +} diff --git a/libgo/go/cmd/go/testdata/script/test_trimpath.txt b/libgo/go/cmd/go/testdata/script/test_trimpath.txt new file mode 100644 index 0000000..065f9ce --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_trimpath.txt @@ -0,0 +1,51 @@ +[short] skip + +go test -trimpath -v . +! stdout '[/\\]pkg_test[/\\]' +stdout -count=3 '[/\\]pkg[/\\]' + +-- go.mod -- +module example.com/pkg + +go 1.17 + +-- pkg.go -- +package pkg + +import "runtime" + +func PrintFile() { + _, file, _, _ := runtime.Caller(0) + println(file) +} + +-- pkg_test.go -- +package pkg + +import "runtime" + +func PrintFileForTest() { + _, file, _, _ := runtime.Caller(0) + println(file) +} + +-- pkg_x_test.go -- +package pkg_test + +import ( + "runtime" + "testing" + + "example.com/pkg" +) + +func TestMain(m *testing.M) { + pkg.PrintFile() + pkg.PrintFileForTest() + PrintFileInXTest() +} + +func PrintFileInXTest() { + _, file, _, _ := runtime.Caller(0) + println(file) +} diff --git a/libgo/go/cmd/go/testdata/script/test_trimpath_main.txt b/libgo/go/cmd/go/testdata/script/test_trimpath_main.txt new file mode 100644 index 0000000..c076212 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_trimpath_main.txt @@ -0,0 +1,38 @@ +[short] skip + +go test -trimpath -v . +! stdout '[/\\]pkg_test[/\\]' +stdout -count=2 '[/\\]pkg[/\\]' + +-- go.mod -- +module example.com/pkg + +go 1.17 + +-- main.go -- +package main + +import "runtime" + +func PrintFile() { + _, file, _, _ := runtime.Caller(0) + println(file) +} + +-- main_test.go -- +package main + +import ( + "runtime" + "testing" +) + +func PrintFileForTest() { + _, file, _, _ := runtime.Caller(0) + println(file) +} + +func TestMain(m *testing.M) { + PrintFile() + PrintFileForTest() +} diff --git a/libgo/go/cmd/go/testdata/script/test_trimpath_test_suffix.txt b/libgo/go/cmd/go/testdata/script/test_trimpath_test_suffix.txt new file mode 100644 index 0000000..6cbad83 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_trimpath_test_suffix.txt @@ -0,0 +1,40 @@ +[short] skip + +go test -trimpath -v . +! stdout '[/\\]pkg_test_test[/\\]' +stdout -count=2 '[/\\]pkg_test[/\\]' + +-- go.mod -- +module example.com/pkg_test + +go 1.17 + +-- pkg.go -- +package pkg_test + +import "runtime" + +func PrintFile() { + _, file, _, _ := runtime.Caller(0) + println(file) +} + +-- pkg_x_test.go -- +package pkg_test_test + +import ( + "runtime" + "testing" + + "example.com/pkg_test" +) + +func PrintFileForTest() { + _, file, _, _ := runtime.Caller(0) + println(file) +} + +func TestMain(m *testing.M) { + pkg_test.PrintFile() + PrintFileForTest() +} diff --git a/libgo/go/cmd/go/testdata/script/test_vendor.txt b/libgo/go/cmd/go/testdata/script/test_vendor.txt new file mode 100644 index 0000000..c67c847 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_vendor.txt @@ -0,0 +1,57 @@ +# In GOPATH mode, vendored packages can replace std packages. +env GO111MODULE=off +cd vend/hello +go test -v +stdout TestMsgInternal +stdout TestMsgExternal + +# In module mode, they cannot. +env GO111MODULE=on +! go test -mod=vendor +stderr 'undefined.*strings.Msg' + +-- vend/hello/go.mod -- +module vend/hello + +go 1.16 +-- vend/hello/hello.go -- +package main + +import ( + "fmt" + "strings" // really ../vendor/strings +) + +func main() { + fmt.Printf("%s\n", strings.Msg) +} +-- vend/hello/hello_test.go -- +package main + +import ( + "strings" // really ../vendor/strings + "testing" +) + +func TestMsgInternal(t *testing.T) { + if strings.Msg != "hello, world" { + t.Fatalf("unexpected msg: %v", strings.Msg) + } +} +-- vend/hello/hellox_test.go -- +package main_test + +import ( + "strings" // really ../vendor/strings + "testing" +) + +func TestMsgExternal(t *testing.T) { + if strings.Msg != "hello, world" { + t.Fatalf("unexpected msg: %v", strings.Msg) + } +} +-- vend/vendor/strings/msg.go -- +package strings + +var Msg = "hello, world" diff --git a/libgo/go/cmd/go/testdata/script/test_vet.txt b/libgo/go/cmd/go/testdata/script/test_vet.txt new file mode 100644 index 0000000..5af26b5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_vet.txt @@ -0,0 +1,92 @@ +[short] skip + +# Test file +! go test p1_test.go +stderr 'Logf format %d' +go test -vet=off +stdout '^ok' + +# Non-test file +! go test p1.go +stderr 'Printf format %d' +go test -x -vet=shift p1.go +stderr '[\\/]vet.*-shift' +stdout '\[no test files\]' +go test -vet=off p1.go +! stderr '[\\/]vet.*-shift' +stdout '\[no test files\]' + +# Test issue #22890 +go test m/vetcycle +stdout 'm/vetcycle.*\[no test files\]' + +# Test with ... +! go test ./vetfail/... +stderr 'Printf format %d' +stdout 'ok\s+m/vetfail/p2' + +# Check there's no diagnosis of a bad build constraint in vetxonly mode. +# Use -a so that we need to recompute the vet-specific export data for +# vetfail/p1. +go test -a m/vetfail/p2 +! stderr 'invalid.*constraint' + +-- go.mod -- +module m + +go 1.16 +-- p1_test.go -- +package p + +import "testing" + +func Test(t *testing.T) { + t.Logf("%d") // oops +} +-- p1.go -- +package p + +import "fmt" + +func F() { + fmt.Printf("%d") // oops +} +-- vetcycle/p.go -- +package p + +type ( + _ interface{ m(B1) } + A1 interface{ a(D1) } + B1 interface{ A1 } + C1 interface { + B1 /* ERROR issue #18395 */ + } + D1 interface{ C1 } +) + +var _ A1 = C1 /* ERROR cannot use C1 */ (nil) +-- vetfail/p1/p1.go -- +// +build !foo-bar + +package p1 + +import "fmt" + +func F() { + fmt.Printf("%d", "hello") // causes vet error +} +-- vetfail/p2/p2.go -- +package p2 + +import _ "m/vetfail/p1" + +func F() { +} +-- vetfail/p2/p2_test.go -- +package p2 + +import "testing" + +func TestF(t *testing.T) { + F() +} diff --git a/libgo/go/cmd/go/testdata/script/test_write_profiles_on_timeout.txt b/libgo/go/cmd/go/testdata/script/test_write_profiles_on_timeout.txt new file mode 100644 index 0000000..0db183f --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_write_profiles_on_timeout.txt @@ -0,0 +1,26 @@ +# Tests issue 19394 + +[short] skip + +! go test -cpuprofile cpu.pprof -memprofile mem.pprof -timeout 1ms +stdout '^panic: test timed out' +grep . cpu.pprof +grep . mem.pprof + +-- go.mod -- +module profiling + +go 1.16 +-- timeout_test.go -- +package timeouttest_test + +import ( + "testing" + "time" +) + +func TestSleep(t *testing.T) { + for { + time.Sleep(1 * time.Second) + } +} diff --git a/libgo/go/cmd/go/testdata/script/test_xtestonly_works.txt b/libgo/go/cmd/go/testdata/script/test_xtestonly_works.txt new file mode 100644 index 0000000..8e150db --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_xtestonly_works.txt @@ -0,0 +1,27 @@ +[short] skip + +go test xtestonly +! stdout '^ok.*\[no tests to run\]' +stdout '^ok' + +-- go.mod -- +module xtestonly + +go 1.16 +-- f.go -- +package xtestonly + +func F() int { return 42 } +-- f_test.go -- +package xtestonly_test + +import ( + "testing" + "xtestonly" +) + +func TestF(t *testing.T) { + if x := xtestonly.F(); x != 42 { + t.Errorf("f.F() = %d, want 42", x) + } +} diff --git a/libgo/go/cmd/go/testdata/script/testing_issue40908.txt b/libgo/go/cmd/go/testdata/script/testing_issue40908.txt new file mode 100644 index 0000000..839320e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/testing_issue40908.txt @@ -0,0 +1,25 @@ +[short] skip +[!race] skip + +go test -race testrace + +-- go.mod -- +module testrace + +go 1.16 +-- race_test.go -- +package testrace + +import "testing" + +func TestRace(t *testing.T) { + helperDone := make(chan struct{}) + go func() { + t.Logf("Something happened before cleanup.") + close(helperDone) + }() + + t.Cleanup(func() { + <-helperDone + }) +} diff --git a/libgo/go/cmd/go/testdata/script/toolexec.txt b/libgo/go/cmd/go/testdata/script/toolexec.txt new file mode 100644 index 0000000..bb86467 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/toolexec.txt @@ -0,0 +1,128 @@ +[short] skip + +# Build our simple toolexec program. +go build ./cmd/mytool + +# Use an ephemeral build cache so that our toolexec output is not cached +# for any stale standard-library dependencies. +# +# TODO(#27628): This should not be necessary. +env GOCACHE=$WORK/gocache + +# Build the main package with our toolexec program. For each action, it will +# print the tool's name and the TOOLEXEC_IMPORTPATH value. We expect to compile +# each package once, and link the main package once. +# Don't check the entire output at once, because the order in which the tools +# are run is irrelevant here. +# Finally, note that asm and cgo are run twice. + +go build -toolexec=$PWD/mytool +[amd64] stderr -count=2 '^asm'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main/withasm"$' +stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main/withasm"$' +[cgo] stderr -count=2 '^cgo'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main/withcgo"$' +[cgo] stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main/withcgo"$' +stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main"$' +stderr -count=1 '^link'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main"$' + +# Test packages are a little bit trickier. +# We have four variants of test/main, as reported by 'go list -test': +# +# test/main - the regular non-test package +# test/main.test - the generated test program +# test/main [test/main.test] - the test package for foo_test.go +# test/main_test [test/main.test] - the test package for foo_separate_test.go +# +# As such, TOOLEXEC_IMPORTPATH must see the same strings, to be able to uniquely +# identify each package being built as reported by 'go list -f {{.ImportPath}}'. +# Note that these are not really "import paths" anymore, but that naming is +# consistent with 'go list -json' at least. + +go test -toolexec=$PWD/mytool + +stderr -count=2 '^# test/main\.test$' +stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main\.test"$' +stderr -count=1 '^link'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main\.test"$' + +stderr -count=1 '^# test/main \[test/main\.test\]$' +stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main \[test/main\.test\]"$' + +stderr -count=1 '^# test/main_test \[test/main\.test\]$' +stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main_test \[test/main\.test\]"$' + +-- go.mod -- +module test/main +-- foo.go -- +// Simple package so we can test a program build with -toolexec. +// With a dummy import, to test different TOOLEXEC_IMPORTPATH values. +// Includes dummy uses of cgo and asm, to cover those tools as well. +package main + +import ( + _ "test/main/withasm" + _ "test/main/withcgo" +) + +func main() {} +-- foo_test.go -- +package main + +import "testing" + +func TestFoo(t *testing.T) {} +-- foo_separate_test.go -- +package main_test + +import "testing" + +func TestSeparateFoo(t *testing.T) {} +-- withcgo/withcgo.go -- +package withcgo + +// int fortytwo() +// { +// return 42; +// } +import "C" +-- withcgo/stub.go -- +package withcgo + +// Stub file to ensure we build without cgo too. +-- withasm/withasm.go -- +package withasm + +// Note that we don't need to declare the Add func at all. +-- withasm/withasm_amd64.s -- +TEXT ·Add(SB),$0-24 + MOVQ a+0(FP), AX + ADDQ b+8(FP), AX + MOVQ AX, ret+16(FP) + RET +-- cmd/mytool/main.go -- +package main + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" +) + +func main() { + tool, args := os.Args[1], os.Args[2:] + toolName := filepath.Base(tool) + if len(args) > 0 && args[0] == "-V=full" { + // We can't alter the version output. + } else { + // Print which tool we're running, and on what package. + fmt.Fprintf(os.Stdout, "%s TOOLEXEC_IMPORTPATH=%q\n", toolName, os.Getenv("TOOLEXEC_IMPORTPATH")) + } + + // Simply run the tool. + cmd := exec.Command(tool, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/libgo/go/cmd/go/testdata/script/vendor_gopath_issue11409.txt b/libgo/go/cmd/go/testdata/script/vendor_gopath_issue11409.txt new file mode 100644 index 0000000..da52f9a --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/vendor_gopath_issue11409.txt @@ -0,0 +1,52 @@ +[!windows] [short] stop 'this test only applies to Windows' +env GO111MODULE=off + +go build run_go.go +exec ./run_go$GOEXE $GOPATH $GOPATH/src/vend/hello +stdout 'hello, world' + +-- run_go.go -- +package main + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" +) + +func changeVolume(s string, f func(s string) string) string { + vol := filepath.VolumeName(s) + return f(vol) + s[len(vol):] +} + +func main() { + gopath := changeVolume(os.Args[1], strings.ToLower) + dir := changeVolume(os.Args[2], strings.ToUpper) + cmd := exec.Command("go", "run", "hello.go") + cmd.Dir = dir + cmd.Env = append(os.Environ(), "GOPATH="+gopath) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + +-- vend/hello/hello.go -- +package main + +import ( + "fmt" + "strings" // really ../vendor/strings +) + +func main() { + fmt.Printf("%s\n", strings.Msg) +} +-- vend/vendor/strings/msg.go -- +package strings + +var Msg = "hello, world" diff --git a/libgo/go/cmd/go/testdata/script/vendor_import.txt b/libgo/go/cmd/go/testdata/script/vendor_import.txt new file mode 100644 index 0000000..df4c27d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/vendor_import.txt @@ -0,0 +1,104 @@ +# Imports +env GO111MODULE=off +go list -f '{{.ImportPath}} {{.Imports}}' 'vend/...' 'vend/vendor/...' 'vend/x/vendor/...' +cmp stdout want_vendor_imports.txt + +-- want_vendor_imports.txt -- +vend [vend/vendor/p r] +vend/dir1 [] +vend/hello [fmt vend/vendor/strings] +vend/subdir [vend/vendor/p r] +vend/x [vend/x/vendor/p vend/vendor/q vend/x/vendor/r vend/dir1 vend/vendor/vend/dir1/dir2] +vend/x/invalid [vend/x/invalid/vendor/foo] +vend/vendor/p [] +vend/vendor/q [] +vend/vendor/strings [] +vend/vendor/vend/dir1/dir2 [] +vend/x/vendor/p [] +vend/x/vendor/p/p [notfound] +vend/x/vendor/r [] +-- vend/bad.go -- +package vend + +import _ "r" +-- vend/dir1/dir1.go -- +package dir1 +-- vend/good.go -- +package vend + +import _ "p" +-- vend/hello/hello.go -- +package main + +import ( + "fmt" + "strings" // really ../vendor/strings +) + +func main() { + fmt.Printf("%s\n", strings.Msg) +} +-- vend/hello/hello_test.go -- +package main + +import ( + "strings" // really ../vendor/strings + "testing" +) + +func TestMsgInternal(t *testing.T) { + if strings.Msg != "hello, world" { + t.Fatalf("unexpected msg: %v", strings.Msg) + } +} +-- vend/hello/hellox_test.go -- +package main_test + +import ( + "strings" // really ../vendor/strings + "testing" +) + +func TestMsgExternal(t *testing.T) { + if strings.Msg != "hello, world" { + t.Fatalf("unexpected msg: %v", strings.Msg) + } +} +-- vend/subdir/bad.go -- +package subdir + +import _ "r" +-- vend/subdir/good.go -- +package subdir + +import _ "p" +-- vend/vendor/p/p.go -- +package p +-- vend/vendor/q/q.go -- +package q +-- vend/vendor/strings/msg.go -- +package strings + +var Msg = "hello, world" +-- vend/vendor/vend/dir1/dir2/dir2.go -- +package dir2 +-- vend/x/invalid/invalid.go -- +package invalid + +import "vend/x/invalid/vendor/foo" +-- vend/x/vendor/p/p/p.go -- +package p + +import _ "notfound" +-- vend/x/vendor/p/p.go -- +package p +-- vend/x/vendor/r/r.go -- +package r +-- vend/x/x.go -- +package x + +import _ "p" +import _ "q" +import _ "r" +import _ "vend/dir1" // not vendored +import _ "vend/dir1/dir2" // vendored diff --git a/libgo/go/cmd/go/testdata/script/vendor_import_missing.txt b/libgo/go/cmd/go/testdata/script/vendor_import_missing.txt new file mode 100644 index 0000000..8e50dfe --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/vendor_import_missing.txt @@ -0,0 +1,7 @@ +# Missing package error message +! go build vend/x/vendor/p/p + +-- vend/x/vendor/p/p/p.go -- +package p + +import _ "notfound" diff --git a/libgo/go/cmd/go/testdata/script/vendor_import_wrong.txt b/libgo/go/cmd/go/testdata/script/vendor_import_wrong.txt new file mode 100644 index 0000000..73bf595 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/vendor_import_wrong.txt @@ -0,0 +1,20 @@ +# Wrong import path +env GO111MODULE=off +! go build vend/x/invalid +stderr 'must be imported as foo' + +env GO111MODULE= +cd vend/x/invalid +! go build vend/x/invalid +stderr 'must be imported as foo' + +-- vend/x/invalid/go.mod -- +module vend/x/invalid + +go 1.16 + +-- vend/x/invalid/invalid.go -- +package invalid + +import "vend/x/invalid/vendor/foo" + diff --git a/libgo/go/cmd/go/testdata/script/vendor_issue12156.txt b/libgo/go/cmd/go/testdata/script/vendor_issue12156.txt new file mode 100644 index 0000000..ac95c6d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/vendor_issue12156.txt @@ -0,0 +1,16 @@ +# Tests issue #12156, a former index out of range panic. + +env GO111MODULE=off +env GOPATH=$WORK/gopath/src/testvendor2 # vendor/x is directly in $GOPATH, not in $GOPATH/src +cd $WORK/gopath/src/testvendor2/src/p + +! go build p.go +! stderr panic # Make sure it doesn't panic +stderr 'cannot find package "x"' + +-- testvendor2/src/p/p.go -- +package p + +import "x" +-- testvendor2/vendor/x/x.go -- +package x diff --git a/libgo/go/cmd/go/testdata/script/vendor_list_issue11977.txt b/libgo/go/cmd/go/testdata/script/vendor_list_issue11977.txt new file mode 100644 index 0000000..ce2e29f --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/vendor_list_issue11977.txt @@ -0,0 +1,17 @@ +[!net] skip +[!exec:git] skip +env GO111MODULE=off + +go get -d github.com/rsc/go-get-issue-11864 + +go list -f '{{join .TestImports "\n"}}' github.com/rsc/go-get-issue-11864/t +stdout 'go-get-issue-11864/vendor/vendor.org/p' + +go list -f '{{join .XTestImports "\n"}}' github.com/rsc/go-get-issue-11864/tx +stdout 'go-get-issue-11864/vendor/vendor.org/p' + +go list -f '{{join .XTestImports "\n"}}' github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2 +stdout 'go-get-issue-11864/vendor/vendor.org/tx2' + +go list -f '{{join .XTestImports "\n"}}' github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3 +stdout 'go-get-issue-11864/vendor/vendor.org/tx3' diff --git a/libgo/go/cmd/go/testdata/script/vendor_resolve.txt b/libgo/go/cmd/go/testdata/script/vendor_resolve.txt new file mode 100644 index 0000000..bc8cf0a --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/vendor_resolve.txt @@ -0,0 +1,21 @@ +env GO111MODULE=off +! go build p +stderr 'must be imported as x' + +-- p/p.go -- +package p + +import ( + _ "q/y" + _ "q/z" +) +-- q/vendor/x/x.go -- +package x +-- q/y/y.go -- +package y + +import _ "x" +-- q/z/z.go -- +package z + +import _ "q/vendor/x" diff --git a/libgo/go/cmd/go/testdata/script/vendor_test_issue11864.txt b/libgo/go/cmd/go/testdata/script/vendor_test_issue11864.txt new file mode 100644 index 0000000..cfb43bf --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/vendor_test_issue11864.txt @@ -0,0 +1,20 @@ +[!net] skip +[!exec:git] skip +env GO111MODULE=off + +go get github.com/rsc/go-get-issue-11864 + +# build -i should work +go build -i github.com/rsc/go-get-issue-11864 +go build -i github.com/rsc/go-get-issue-11864/t + +# test -i should work like build -i (golang.org/issue/11988) +go test -i github.com/rsc/go-get-issue-11864 +go test -i github.com/rsc/go-get-issue-11864/t + +# test should work too +go test github.com/rsc/go-get-issue-11864 +go test github.com/rsc/go-get-issue-11864/t + +# external tests should observe internal test exports (golang.org/issue/11977) +go test github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2 diff --git a/libgo/go/cmd/go/testdata/script/vendor_test_issue14613.txt b/libgo/go/cmd/go/testdata/script/vendor_test_issue14613.txt new file mode 100644 index 0000000..cfd7e58 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/vendor_test_issue14613.txt @@ -0,0 +1,22 @@ +[!net] skip +[!exec:git] skip +env GO111MODULE=off + +cd $GOPATH + +go get github.com/clsung/go-vendor-issue-14613 +go build -o $WORK/a.out -i github.com/clsung/go-vendor-issue-14613 + +# test folder should work +go test -i github.com/clsung/go-vendor-issue-14613 +go test github.com/clsung/go-vendor-issue-14613 + +# test with specified _test.go should work too +cd $GOPATH/src +go test -i github.com/clsung/go-vendor-issue-14613/vendor_test.go +go test github.com/clsung/go-vendor-issue-14613/vendor_test.go + +# test with imported and not used +go test -i github.com/clsung/go-vendor-issue-14613/vendor/mylibtesttest/myapp/myapp_test.go +! go test github.com/clsung/go-vendor-issue-14613/vendor/mylibtesttest/myapp/myapp_test.go +stderr 'imported and not used' diff --git a/libgo/go/cmd/go/testdata/script/version_goexperiment.txt b/libgo/go/cmd/go/testdata/script/version_goexperiment.txt new file mode 100644 index 0000000..4b165eb --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/version_goexperiment.txt @@ -0,0 +1,16 @@ +# Test that experiments appear in "go version <binary>" + +# This test requires rebuilding the runtime, which takes a while. +[short] skip + +env GOEXPERIMENT=fieldtrack +go build -o main$GOEXE version.go +go version main$GOEXE +stdout 'X:fieldtrack$' +exec ./main$GOEXE +stderr 'X:fieldtrack$' + +-- version.go -- +package main +import "runtime" +func main() { println(runtime.Version()) } diff --git a/libgo/go/cmd/go/testdata/script/version_replace.txt b/libgo/go/cmd/go/testdata/script/version_replace.txt new file mode 100644 index 0000000..ec98f4e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/version_replace.txt @@ -0,0 +1,33 @@ +[short] skip + +go mod download example.com/printversion@v0.1.0 example.com/printversion@v1.0.0 +go get -d example.com/printversion@v0.1.0 +go install example.com/printversion + +go run example.com/printversion +cmp stdout out.txt + +go version -m $GOPATH/bin/printversion$GOEXE +stdout '^.*[/\\]bin[/\\]printversion'$GOEXE': .*$' +stdout '^ path example.com/printversion$' +stdout '^ mod example.com/printversion v0.1.0$' +stdout '^ => example.com/printversion v1.0.0 h1:.*$' +stdout '^ dep example.com/version v1.0.0$' +stdout '^ => example.com/version v1.0.1 h1:.*$' + +-- go.mod -- +module golang.org/issue/37392 +go 1.14 +require ( + example.com/printversion v0.1.0 +) +replace ( + example.com/printversion => example.com/printversion v1.0.0 + example.com/version v1.0.0 => example.com/version v1.0.1 +) +-- out.txt -- +path is example.com/printversion +main is example.com/printversion v0.1.0 + (replaced by example.com/printversion v1.0.0) +using example.com/version v1.0.0 + (replaced by example.com/version v1.0.1) diff --git a/libgo/go/cmd/go/testdata/script/vet.txt b/libgo/go/cmd/go/testdata/script/vet.txt new file mode 100644 index 0000000..6573ae3 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/vet.txt @@ -0,0 +1,62 @@ +# Package with external tests +! go vet m/vetpkg +stderr 'Printf' + +# With tags +! go vet -tags tagtest m/vetpkg +stderr 'c\.go.*Printf' + +# With flags on +! go vet -printf m/vetpkg +stderr 'Printf' + +# With flags off +go vet -printf=false m/vetpkg +! stderr . + +# With only test files (tests issue #23395) +go vet m/onlytest +! stderr . + +# With only cgo files (tests issue #24193) +[!cgo] skip +[short] skip +go vet m/onlycgo +! stderr . + +-- go.mod -- +module m + +go 1.16 +-- vetpkg/a_test.go -- +package p_test +-- vetpkg/b.go -- +package p + +import "fmt" + +func f() { + fmt.Printf("%d") +} +-- vetpkg/c.go -- +// +build tagtest + +package p + +import "fmt" + +func g() { + fmt.Printf("%d", 3, 4) +} +-- onlytest/p_test.go -- +package p + +import "testing" + +func TestMe(*testing.T) {} +-- onlycgo/p.go -- +package p + +import "C" + +func F() {} diff --git a/libgo/go/cmd/go/testdata/script/vet_internal.txt b/libgo/go/cmd/go/testdata/script/vet_internal.txt new file mode 100644 index 0000000..85f7093 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/vet_internal.txt @@ -0,0 +1,71 @@ +env GO111MODULE=off + +# Issue 36173. Verify that "go vet" prints line numbers on load errors. + +! go vet a/a.go +stderr '^package command-line-arguments\n\ta[/\\]a.go:5:3: use of internal package' + +! go vet a/a_test.go +stderr '^package command-line-arguments \(test\)\n\ta[/\\]a_test.go:4:3: use of internal package' + +! go vet a +stderr '^package a\n\ta[/\\]a.go:5:3: use of internal package' + +go vet b/b.go +! stderr 'use of internal package' + +! go vet b/b_test.go +stderr '^package command-line-arguments \(test\)\n\tb[/\\]b_test.go:4:3: use of internal package' + +! go vet depends-on-a/depends-on-a.go +stderr '^package command-line-arguments\n\timports a\n\ta[/\\]a.go:5:3: use of internal package' + +! go vet depends-on-a/depends-on-a_test.go +stderr '^package command-line-arguments \(test\)\n\timports a\n\ta[/\\]a.go:5:3: use of internal package a/x/internal/y not allowed' + +! go vet depends-on-a +stderr '^package depends-on-a\n\timports a\n\ta[/\\]a.go:5:3: use of internal package' + +-- a/a.go -- +// A package with bad imports in both src and test +package a + +import ( + _ "a/x/internal/y" +) + +-- a/a_test.go -- +package a + +import ( + _ "a/x/internal/y" +) + +-- b/b.go -- +// A package with a bad import in test only +package b + +-- b/b_test.go -- +package b + +import ( + _ "a/x/internal/y" +) + +-- depends-on-a/depends-on-a.go -- +// A package that depends on a package with a bad import +package depends + +import ( + _ "a" +) + +-- depends-on-a/depends-on-a_test.go -- +package depends + +import ( + _ "a" +) + +-- a/x/internal/y/y.go -- +package y diff --git a/libgo/go/cmd/gofmt/gofmt.go b/libgo/go/cmd/gofmt/gofmt.go index 2793c2c..b3c120d 100644 --- a/libgo/go/cmd/gofmt/gofmt.go +++ b/libgo/go/cmd/gofmt/gofmt.go @@ -151,7 +151,7 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error if err != nil { return fmt.Errorf("computing diff: %s", err) } - fmt.Printf("diff -u %s %s\n", filepath.ToSlash(filename+".orig"), filepath.ToSlash(filename)) + fmt.Fprintf(out, "diff -u %s %s\n", filepath.ToSlash(filename+".orig"), filepath.ToSlash(filename)) out.Write(data) } } @@ -164,21 +164,15 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error } func visitFile(path string, f fs.DirEntry, err error) error { - if err == nil && isGoFile(f) { - err = processFile(path, nil, os.Stdout, false) + if err != nil || !isGoFile(f) { + return err } - // Don't complain if a file was deleted in the meantime (i.e. - // the directory changed concurrently while running gofmt). - if err != nil && !os.IsNotExist(err) { + if err := processFile(path, nil, os.Stdout, false); err != nil { report(err) } return nil } -func walkDir(path string) { - filepath.WalkDir(path, visitFile) -} - func main() { // call gofmtMain in a separate function // so that it can use defer and have them @@ -206,7 +200,8 @@ func gofmtMain() { initParserMode() initRewrite() - if flag.NArg() == 0 { + args := flag.Args() + if len(args) == 0 { if *write { fmt.Fprintln(os.Stderr, "error: cannot use -w with standard input") exitCode = 2 @@ -218,15 +213,18 @@ func gofmtMain() { return } - for i := 0; i < flag.NArg(); i++ { - path := flag.Arg(i) - switch dir, err := os.Stat(path); { + for _, arg := range args { + switch info, err := os.Stat(arg); { case err != nil: report(err) - case dir.IsDir(): - walkDir(path) + case !info.IsDir(): + // Non-directory arguments are always formatted. + if err := processFile(arg, nil, os.Stdout, false); err != nil { + report(err) + } default: - if err := processFile(path, nil, os.Stdout, false); err != nil { + // Directories are walked, ignoring non-Go files. + if err := filepath.WalkDir(arg, visitFile); err != nil { report(err) } } diff --git a/libgo/go/cmd/gofmt/gofmt_test.go b/libgo/go/cmd/gofmt/gofmt_test.go index bf2adfe..f0d3f87 100644 --- a/libgo/go/cmd/gofmt/gofmt_test.go +++ b/libgo/go/cmd/gofmt/gofmt_test.go @@ -49,12 +49,13 @@ func gofmtFlags(filename string, maxLines int) string { case scanner.EOF: return "" } - } return "" } +var typeParamsEnabled = false + func runTest(t *testing.T, in, out string) { // process flags *simplifyAST = false @@ -77,6 +78,11 @@ func runTest(t *testing.T, in, out string) { case "-stdin": // fake flag - pretend input is from stdin stdin = true + case "-G": + // fake flag - test is for generic code + if !typeParamsEnabled { + return + } default: t.Errorf("unrecognized flag name: %s", name) } diff --git a/libgo/go/cmd/gofmt/gofmt_typeparams_test.go b/libgo/go/cmd/gofmt/gofmt_typeparams_test.go new file mode 100644 index 0000000..10641a7 --- /dev/null +++ b/libgo/go/cmd/gofmt/gofmt_typeparams_test.go @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build typeparams +// +build typeparams + +package main + +func init() { + typeParamsEnabled = true +} diff --git a/libgo/go/cmd/internal/objabi/flag.go b/libgo/go/cmd/internal/objabi/flag.go index 3fd73f3..e41fc57 100644 --- a/libgo/go/cmd/internal/objabi/flag.go +++ b/libgo/go/cmd/internal/objabi/flag.go @@ -8,6 +8,7 @@ import ( "bytes" "flag" "fmt" + "internal/buildcfg" "io" "io/ioutil" "log" @@ -91,16 +92,18 @@ func (versionFlag) Set(s string) error { name = name[strings.LastIndex(name, `\`)+1:] name = strings.TrimSuffix(name, ".exe") - // If there's an active experiment, include that, - // to distinguish go1.10.2 with an experiment - // from go1.10.2 without an experiment. - p := Expstring() - if p == DefaultExpstring() { - p = "" - } - sep := "" - if p != "" { - sep = " " + p := "" + + if s == "goexperiment" { + // test/run.go uses this to discover the full set of + // experiment tags. Report everything. + p = " X:" + strings.Join(buildcfg.AllExperiments(), ",") + } else { + // If the enabled experiments differ from the defaults, + // include that difference. + if goexperiment := buildcfg.GOEXPERIMENT(); goexperiment != "" { + p = " X:" + goexperiment + } } // The go command invokes -V=full to get a unique identifier @@ -109,12 +112,12 @@ func (versionFlag) Set(s string) error { // build ID of the binary, so that if the compiler is changed and // rebuilt, we notice and rebuild all packages. if s == "full" { - if strings.HasPrefix(Version, "devel") { + if strings.HasPrefix(buildcfg.Version, "devel") { p += " buildID=" + buildID } } - fmt.Printf("%s version %s%s%s\n", name, Version, sep, p) + fmt.Printf("%s version %s%s\n", name, buildcfg.Version, p) os.Exit(0) return nil } diff --git a/libgo/go/cmd/internal/objabi/funcdata.go b/libgo/go/cmd/internal/objabi/funcdata.go index faa2863..4ff0ebe 100644 --- a/libgo/go/cmd/internal/objabi/funcdata.go +++ b/libgo/go/cmd/internal/objabi/funcdata.go @@ -20,6 +20,7 @@ const ( FUNCDATA_StackObjects = 2 FUNCDATA_InlTree = 3 FUNCDATA_OpenCodedDeferInfo = 4 + FUNCDATA_ArgInfo = 5 // ArgsSizeUnknown is set in Func.argsize to mark all functions // whose argument size is unknown (C vararg functions, and diff --git a/libgo/go/cmd/internal/objabi/funcid.go b/libgo/go/cmd/internal/objabi/funcid.go index 1d098ee..93ebd7b 100644 --- a/libgo/go/cmd/internal/objabi/funcid.go +++ b/libgo/go/cmd/internal/objabi/funcid.go @@ -4,97 +4,90 @@ package objabi +import "strings" + +// A FuncFlag records bits about a function, passed to the runtime. +type FuncFlag uint8 + +// Note: This list must match the list in runtime/symtab.go. +const ( + FuncFlag_TOPFRAME = 1 << iota + FuncFlag_SPWRITE +) + // A FuncID identifies particular functions that need to be treated // specially by the runtime. // Note that in some situations involving plugins, there may be multiple // copies of a particular special runtime function. -// Note: this list must match the list in runtime/symtab.go. type FuncID uint8 +// Note: this list must match the list in runtime/symtab.go. const ( FuncID_normal FuncID = iota // not a special function - FuncID_runtime_main + FuncID_abort + FuncID_asmcgocall + FuncID_asyncPreempt + FuncID_cgocallback + FuncID_debugCallV2 + FuncID_gcBgMarkWorker FuncID_goexit + FuncID_gogo + FuncID_gopanic + FuncID_handleAsyncEvent FuncID_jmpdefer FuncID_mcall FuncID_morestack FuncID_mstart + FuncID_panicwrap FuncID_rt0_go - FuncID_asmcgocall - FuncID_sigpanic FuncID_runfinq - FuncID_gcBgMarkWorker - FuncID_systemstack_switch + FuncID_runtime_main + FuncID_sigpanic FuncID_systemstack - FuncID_cgocallback - FuncID_gogo - FuncID_externalthreadhandler - FuncID_debugCallV1 - FuncID_gopanic - FuncID_panicwrap - FuncID_handleAsyncEvent - FuncID_asyncPreempt + FuncID_systemstack_switch FuncID_wrapper // any autogenerated code (hash/eq algorithms, method wrappers, etc.) ) +var funcIDs = map[string]FuncID{ + "abort": FuncID_abort, + "asmcgocall": FuncID_asmcgocall, + "asyncPreempt": FuncID_asyncPreempt, + "cgocallback": FuncID_cgocallback, + "debugCallV2": FuncID_debugCallV2, + "gcBgMarkWorker": FuncID_gcBgMarkWorker, + "go": FuncID_rt0_go, + "goexit": FuncID_goexit, + "gogo": FuncID_gogo, + "gopanic": FuncID_gopanic, + "handleAsyncEvent": FuncID_handleAsyncEvent, + "jmpdefer": FuncID_jmpdefer, + "main": FuncID_runtime_main, + "mcall": FuncID_mcall, + "morestack": FuncID_morestack, + "mstart": FuncID_mstart, + "panicwrap": FuncID_panicwrap, + "runfinq": FuncID_runfinq, + "sigpanic": FuncID_sigpanic, + "switch": FuncID_systemstack_switch, + "systemstack": FuncID_systemstack, + + // Don't show in call stack but otherwise not special. + "deferreturn": FuncID_wrapper, + "runOpenDeferFrame": FuncID_wrapper, + "reflectcallSave": FuncID_wrapper, + "deferCallSave": FuncID_wrapper, +} + // Get the function ID for the named function in the named file. // The function should be package-qualified. func GetFuncID(name string, isWrapper bool) FuncID { if isWrapper { return FuncID_wrapper } - switch name { - case "runtime.main": - return FuncID_runtime_main - case "runtime.goexit": - return FuncID_goexit - case "runtime.jmpdefer": - return FuncID_jmpdefer - case "runtime.mcall": - return FuncID_mcall - case "runtime.morestack": - return FuncID_morestack - case "runtime.mstart": - return FuncID_mstart - case "runtime.rt0_go": - return FuncID_rt0_go - case "runtime.asmcgocall": - return FuncID_asmcgocall - case "runtime.sigpanic": - return FuncID_sigpanic - case "runtime.runfinq": - return FuncID_runfinq - case "runtime.gcBgMarkWorker": - return FuncID_gcBgMarkWorker - case "runtime.systemstack_switch": - return FuncID_systemstack_switch - case "runtime.systemstack": - return FuncID_systemstack - case "runtime.cgocallback": - return FuncID_cgocallback - case "runtime.gogo": - return FuncID_gogo - case "runtime.externalthreadhandler": - return FuncID_externalthreadhandler - case "runtime.debugCallV1": - return FuncID_debugCallV1 - case "runtime.gopanic": - return FuncID_gopanic - case "runtime.panicwrap": - return FuncID_panicwrap - case "runtime.handleAsyncEvent": - return FuncID_handleAsyncEvent - case "runtime.asyncPreempt": - return FuncID_asyncPreempt - case "runtime.deferreturn": - // Don't show in the call stack (used when invoking defer functions) - return FuncID_wrapper - case "runtime.runOpenDeferFrame": - // Don't show in the call stack (used when invoking defer functions) - return FuncID_wrapper - case "runtime.reflectcallSave": - // Don't show in the call stack (used when invoking defer functions) - return FuncID_wrapper + if strings.HasPrefix(name, "runtime.") { + if id, ok := funcIDs[name[len("runtime."):]]; ok { + return id + } } return FuncID_normal } diff --git a/libgo/go/cmd/internal/objabi/line.go b/libgo/go/cmd/internal/objabi/line.go index 0733b65..0b1e0bb 100644 --- a/libgo/go/cmd/internal/objabi/line.go +++ b/libgo/go/cmd/internal/objabi/line.go @@ -5,6 +5,7 @@ package objabi import ( + "internal/buildcfg" "os" "path/filepath" "strings" @@ -38,8 +39,8 @@ func AbsFile(dir, file, rewrites string) string { } abs, rewritten := ApplyRewrites(abs, rewrites) - if !rewritten && hasPathPrefix(abs, GOROOT) { - abs = "$GOROOT" + abs[len(GOROOT):] + if !rewritten && hasPathPrefix(abs, buildcfg.GOROOT) { + abs = "$GOROOT" + abs[len(buildcfg.GOROOT):] } if abs == "" { diff --git a/libgo/go/cmd/internal/objabi/path.go b/libgo/go/cmd/internal/objabi/path.go index fd1c998..aacab9a 100644 --- a/libgo/go/cmd/internal/objabi/path.go +++ b/libgo/go/cmd/internal/objabi/path.go @@ -47,6 +47,8 @@ func PathToPrefix(s string) string { // some cases need to be aware of when they are building such a // package, for example to enable features such as ABI selectors in // assembly sources. +// +// Keep in sync with cmd/dist/build.go:IsRuntimePackagePath. func IsRuntimePackagePath(pkgpath string) bool { rval := false switch pkgpath { @@ -56,6 +58,8 @@ func IsRuntimePackagePath(pkgpath string) bool { rval = true case "syscall": rval = true + case "internal/bytealg": + rval = true default: rval = strings.HasPrefix(pkgpath, "runtime/internal") } diff --git a/libgo/go/cmd/internal/objabi/reloctype.go b/libgo/go/cmd/internal/objabi/reloctype.go index 649f690..52827a6 100644 --- a/libgo/go/cmd/internal/objabi/reloctype.go +++ b/libgo/go/cmd/internal/objabi/reloctype.go @@ -50,11 +50,6 @@ const ( // R_ADDROFF resolves to a 32-bit offset from the beginning of the section // holding the data being relocated to the referenced symbol. R_ADDROFF - // R_WEAKADDROFF resolves just like R_ADDROFF but is a weak relocation. - // A weak relocation does not make the symbol it refers to reachable, - // and is only honored by the linker if the symbol is in some other way - // reachable. - R_WEAKADDROFF R_SIZE R_CALL R_CALLARM @@ -106,6 +101,9 @@ const ( // *rtype, and may be set to zero by the linker if it determines the method // text is unreachable by the linked program. R_METHODOFF + // R_KEEP tells the linker to keep the referred-to symbol in the final binary + // if the symbol containing the R_KEEP relocation is in the final binary. + R_KEEP R_POWER_TOC R_GOTPCREL // R_JMPMIPS (only used on mips64) resolves to non-PC-relative target address @@ -172,8 +170,8 @@ const ( // R_POWER_TLS_LE is used to implement the "local exec" model for tls // access. It resolves to the offset of the thread-local symbol from the - // thread pointer (R13) and inserts this value into the low 16 bits of an - // instruction word. + // thread pointer (R13) and is split against a pair of instructions to + // support a 32 bit displacement. R_POWER_TLS_LE // R_POWER_TLS_IE is used to implement the "initial exec" model for tls access. It @@ -183,10 +181,12 @@ const ( // symbol from the thread pointer (R13)). R_POWER_TLS_IE - // R_POWER_TLS marks an X-form instruction such as "MOVD 0(R13)(R31*1), g" as - // accessing a particular thread-local symbol. It does not affect code generation - // but is used by the system linker when relaxing "initial exec" model code to - // "local exec" model code. + // R_POWER_TLS marks an X-form instruction such as "ADD R3,R13,R4" as completing + // a sequence of GOT-relative relocations to compute a TLS address. This can be + // used by the system linker to to rewrite the GOT-relative TLS relocation into a + // simpler thread-pointer relative relocation. See table 3.26 and 3.28 in the + // ppc64 elfv2 1.4 ABI on this transformation. Likewise, the second argument + // (usually called RB in X-form instructions) is assumed to be R13. R_POWER_TLS // R_ADDRPOWER_DS is similar to R_ADDRPOWER above, but assumes the second @@ -256,6 +256,15 @@ const ( // of a symbol. This isn't a real relocation, it can be placed in anywhere // in a symbol and target any symbols. R_XCOFFREF + + // R_WEAK marks the relocation as a weak reference. + // A weak relocation does not make the symbol it refers to reachable, + // and is only honored by the linker if the symbol is in some other way + // reachable. + R_WEAK = -1 << 15 + + R_WEAKADDR = R_WEAK | R_ADDR + R_WEAKADDROFF = R_WEAK | R_ADDROFF ) // IsDirectCall reports whether r is a relocation for a direct call. diff --git a/libgo/go/cmd/internal/objabi/reloctype_string.go b/libgo/go/cmd/internal/objabi/reloctype_string.go index 658a44f..4638ef1 100644 --- a/libgo/go/cmd/internal/objabi/reloctype_string.go +++ b/libgo/go/cmd/internal/objabi/reloctype_string.go @@ -13,28 +13,28 @@ func _() { _ = x[R_ADDRARM64-3] _ = x[R_ADDRMIPS-4] _ = x[R_ADDROFF-5] - _ = x[R_WEAKADDROFF-6] - _ = x[R_SIZE-7] - _ = x[R_CALL-8] - _ = x[R_CALLARM-9] - _ = x[R_CALLARM64-10] - _ = x[R_CALLIND-11] - _ = x[R_CALLPOWER-12] - _ = x[R_CALLMIPS-13] - _ = x[R_CALLRISCV-14] - _ = x[R_CONST-15] - _ = x[R_PCREL-16] - _ = x[R_TLS_LE-17] - _ = x[R_TLS_IE-18] - _ = x[R_GOTOFF-19] - _ = x[R_PLT0-20] - _ = x[R_PLT1-21] - _ = x[R_PLT2-22] - _ = x[R_USEFIELD-23] - _ = x[R_USETYPE-24] - _ = x[R_USEIFACE-25] - _ = x[R_USEIFACEMETHOD-26] - _ = x[R_METHODOFF-27] + _ = x[R_SIZE-6] + _ = x[R_CALL-7] + _ = x[R_CALLARM-8] + _ = x[R_CALLARM64-9] + _ = x[R_CALLIND-10] + _ = x[R_CALLPOWER-11] + _ = x[R_CALLMIPS-12] + _ = x[R_CALLRISCV-13] + _ = x[R_CONST-14] + _ = x[R_PCREL-15] + _ = x[R_TLS_LE-16] + _ = x[R_TLS_IE-17] + _ = x[R_GOTOFF-18] + _ = x[R_PLT0-19] + _ = x[R_PLT1-20] + _ = x[R_PLT2-21] + _ = x[R_USEFIELD-22] + _ = x[R_USETYPE-23] + _ = x[R_USEIFACE-24] + _ = x[R_USEIFACEMETHOD-25] + _ = x[R_METHODOFF-26] + _ = x[R_KEEP-27] _ = x[R_POWER_TOC-28] _ = x[R_GOTPCREL-29] _ = x[R_JMPMIPS-30] @@ -70,9 +70,9 @@ func _() { _ = x[R_XCOFFREF-60] } -const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_WEAKADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CALLRISCVR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_METHODOFFR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF" +const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CALLRISCVR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF" -var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 60, 66, 72, 81, 92, 101, 112, 122, 133, 140, 147, 155, 163, 171, 177, 183, 189, 199, 208, 218, 234, 245, 256, 266, 275, 288, 302, 316, 330, 346, 357, 370, 383, 397, 411, 425, 440, 454, 468, 479, 493, 508, 525, 543, 564, 583, 602, 622, 642, 652, 663, 676, 687, 699, 709} +var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 120, 127, 134, 142, 150, 158, 164, 170, 176, 186, 195, 205, 221, 232, 238, 249, 259, 268, 281, 295, 309, 323, 339, 350, 363, 376, 390, 404, 418, 433, 447, 461, 472, 486, 501, 518, 536, 557, 576, 595, 615, 635, 645, 656, 669, 680, 692, 702} func (i RelocType) String() string { i -= 1 diff --git a/libgo/go/cmd/internal/objabi/stack.go b/libgo/go/cmd/internal/objabi/stack.go index 05a1d4a..0c82a7c 100644 --- a/libgo/go/cmd/internal/objabi/stack.go +++ b/libgo/go/cmd/internal/objabi/stack.go @@ -4,6 +4,8 @@ package objabi +import "internal/buildcfg" + // For the linkers. Must match Go definitions. const ( @@ -13,10 +15,6 @@ const ( StackSmall = 128 ) -const ( - StackPreempt = -1314 // 0xfff...fade -) - // Initialize StackGuard and StackLimit according to target system. var StackGuard = 928*stackGuardMultiplier() + StackSystem var StackLimit = StackGuard - StackSystem - StackSmall @@ -26,7 +24,7 @@ var StackLimit = StackGuard - StackSystem - StackSmall // builds that have larger stack frames or for specific targets. func stackGuardMultiplier() int { // On AIX, a larger stack is needed for syscalls. - if GOOS == "aix" { + if buildcfg.GOOS == "aix" { return 2 } return stackGuardMultiplierDefault diff --git a/libgo/go/cmd/internal/objabi/util.go b/libgo/go/cmd/internal/objabi/util.go index d9cf495..fcda97d 100644 --- a/libgo/go/cmd/internal/objabi/util.go +++ b/libgo/go/cmd/internal/objabi/util.go @@ -6,196 +6,19 @@ package objabi import ( "fmt" - "log" - "os" + "internal/buildcfg" "strings" ) -func envOr(key, value string) string { - if x := os.Getenv(key); x != "" { - return x - } - return value -} - -var ( - defaultGOROOT = defaultGOROOTValue() - - GOROOT = envOr("GOROOT", defaultGOROOT) - GOARCH = envOr("GOARCH", defaultGOARCH) - GOOS = envOr("GOOS", defaultGOOS) - GO386 = envOr("GO386", defaultGO386) - GOARM = goarm() - GOMIPS = gomips() - GOMIPS64 = gomips64() - GOPPC64 = goppc64() - GOWASM = gowasm() - GO_LDSO = defaultGO_LDSO - Version = version -) - const ( ElfRelocOffset = 256 MachoRelocOffset = 2048 // reserve enough space for ELF relocations ) -func goarm() int { - def := defaultGOARM - if GOOS == "android" && GOARCH == "arm" { - // Android arm devices always support GOARM=7. - def = "7" - } - switch v := envOr("GOARM", def); v { - case "5": - return 5 - case "6": - return 6 - case "7": - return 7 - } - // Fail here, rather than validate at multiple call sites. - log.Fatalf("Invalid GOARM value. Must be 5, 6, or 7.") - panic("unreachable") -} - -func gomips() string { - switch v := envOr("GOMIPS", defaultGOMIPS); v { - case "hardfloat", "softfloat": - return v - } - log.Fatalf("Invalid GOMIPS value. Must be hardfloat or softfloat.") - panic("unreachable") -} - -func gomips64() string { - switch v := envOr("GOMIPS64", defaultGOMIPS64); v { - case "hardfloat", "softfloat": - return v - } - log.Fatalf("Invalid GOMIPS64 value. Must be hardfloat or softfloat.") - panic("unreachable") -} - -func goppc64() int { - switch v := envOr("GOPPC64", defaultGOPPC64); v { - case "power8": - return 8 - case "power9": - return 9 - } - log.Fatalf("Invalid GOPPC64 value. Must be power8 or power9.") - panic("unreachable") -} - -type gowasmFeatures struct { - SignExt bool - SatConv bool -} - -func (f gowasmFeatures) String() string { - var flags []string - if f.SatConv { - flags = append(flags, "satconv") - } - if f.SignExt { - flags = append(flags, "signext") - } - return strings.Join(flags, ",") -} - -func gowasm() (f gowasmFeatures) { - for _, opt := range strings.Split(envOr("GOWASM", ""), ",") { - switch opt { - case "satconv": - f.SatConv = true - case "signext": - f.SignExt = true - case "": - // ignore - default: - log.Fatalf("Invalid GOWASM value. No such feature: " + opt) - } - } - return -} - -func Getgoextlinkenabled() string { - return envOr("GO_EXTLINK_ENABLED", defaultGO_EXTLINK_ENABLED) -} - -func init() { - for _, f := range strings.Split(goexperiment, ",") { - if f != "" { - addexp(f) - } - } - - // regabi is only supported on amd64. - if GOARCH != "amd64" { - Regabi_enabled = 0 - } -} - -// Note: must agree with runtime.framepointer_enabled. -var Framepointer_enabled = GOARCH == "amd64" || GOARCH == "arm64" && (GOOS == "linux" || GOOS == "darwin" || GOOS == "ios") - -func addexp(s string) { - // Could do general integer parsing here, but the runtime copy doesn't yet. - v := 1 - name := s - if len(name) > 2 && name[:2] == "no" { - v = 0 - name = name[2:] - } - for i := 0; i < len(exper); i++ { - if exper[i].name == name { - if exper[i].val != nil { - *exper[i].val = v - } - return - } - } - - fmt.Printf("unknown experiment %s\n", s) - os.Exit(2) -} - -var ( - Fieldtrack_enabled int - Preemptibleloops_enabled int - Staticlockranking_enabled int - Regabi_enabled int -) - -// Toolchain experiments. -// These are controlled by the GOEXPERIMENT environment -// variable recorded when the toolchain is built. -// This list is also known to cmd/gc. -var exper = []struct { - name string - val *int -}{ - {"fieldtrack", &Fieldtrack_enabled}, - {"preemptibleloops", &Preemptibleloops_enabled}, - {"staticlockranking", &Staticlockranking_enabled}, - {"regabi", &Regabi_enabled}, -} - -var defaultExpstring = Expstring() - -func DefaultExpstring() string { - return defaultExpstring -} - -func Expstring() string { - buf := "X" - for i := range exper { - if *exper[i].val != 0 { - buf += "," + exper[i].name - } - } - if buf == "X" { - buf += ",none" - } - return "X:" + buf[2:] +// HeaderString returns the toolchain configuration string written in +// Go object headers. This string ensures we don't attempt to import +// or link object files that are incompatible with each other. This +// string always starts with "go object ". +func HeaderString() string { + return fmt.Sprintf("go object %s %s %s X:%s\n", buildcfg.GOOS, buildcfg.GOARCH, buildcfg.Version, strings.Join(buildcfg.EnabledExperiments(), ",")) } diff --git a/libgo/go/cmd/internal/sys/arch.go b/libgo/go/cmd/internal/sys/arch.go index 60a3b3c..2029b7d 100644 --- a/libgo/go/cmd/internal/sys/arch.go +++ b/libgo/go/cmd/internal/sys/arch.go @@ -41,6 +41,12 @@ type Arch struct { // MinLC is the minimum length of an instruction code. MinLC int + + // Alignment is maximum alignment required by the architecture + // for any (compiler-generated) load or store instruction. + // Loads or stores smaller than Alignment must be naturally aligned. + // Loads or stores larger than Alignment need only be Alignment-aligned. + Alignment int8 } // InFamily reports whether a is a member of any of the specified @@ -61,6 +67,7 @@ var Arch386 = &Arch{ PtrSize: 4, RegSize: 4, MinLC: 1, + Alignment: 1, } var ArchAMD64 = &Arch{ @@ -70,6 +77,7 @@ var ArchAMD64 = &Arch{ PtrSize: 8, RegSize: 8, MinLC: 1, + Alignment: 1, } var ArchARM = &Arch{ @@ -79,6 +87,7 @@ var ArchARM = &Arch{ PtrSize: 4, RegSize: 4, MinLC: 4, + Alignment: 4, // TODO: just for arm5? } var ArchARM64 = &Arch{ @@ -88,6 +97,7 @@ var ArchARM64 = &Arch{ PtrSize: 8, RegSize: 8, MinLC: 4, + Alignment: 1, } var ArchMIPS = &Arch{ @@ -97,6 +107,7 @@ var ArchMIPS = &Arch{ PtrSize: 4, RegSize: 4, MinLC: 4, + Alignment: 4, } var ArchMIPSLE = &Arch{ @@ -106,6 +117,7 @@ var ArchMIPSLE = &Arch{ PtrSize: 4, RegSize: 4, MinLC: 4, + Alignment: 4, } var ArchMIPS64 = &Arch{ @@ -115,6 +127,7 @@ var ArchMIPS64 = &Arch{ PtrSize: 8, RegSize: 8, MinLC: 4, + Alignment: 8, } var ArchMIPS64LE = &Arch{ @@ -124,6 +137,7 @@ var ArchMIPS64LE = &Arch{ PtrSize: 8, RegSize: 8, MinLC: 4, + Alignment: 8, } var ArchPPC64 = &Arch{ @@ -133,6 +147,7 @@ var ArchPPC64 = &Arch{ PtrSize: 8, RegSize: 8, MinLC: 4, + Alignment: 1, } var ArchPPC64LE = &Arch{ @@ -142,6 +157,7 @@ var ArchPPC64LE = &Arch{ PtrSize: 8, RegSize: 8, MinLC: 4, + Alignment: 1, } var ArchRISCV = &Arch{ @@ -160,6 +176,7 @@ var ArchRISCV64 = &Arch{ PtrSize: 8, RegSize: 8, MinLC: 4, + Alignment: 8, // riscv unaligned loads work, but are really slow (trap + simulated by OS) } var ArchS390X = &Arch{ @@ -169,6 +186,7 @@ var ArchS390X = &Arch{ PtrSize: 8, RegSize: 8, MinLC: 2, + Alignment: 1, } var ArchWasm = &Arch{ @@ -178,6 +196,7 @@ var ArchWasm = &Arch{ PtrSize: 8, RegSize: 8, MinLC: 1, + Alignment: 1, } var Archs = [...]*Arch{ diff --git a/libgo/go/cmd/internal/sys/supported.go b/libgo/go/cmd/internal/sys/supported.go index ef7c017..0d2bad9 100644 --- a/libgo/go/cmd/internal/sys/supported.go +++ b/libgo/go/cmd/internal/sys/supported.go @@ -15,7 +15,7 @@ func RaceDetectorSupported(goos, goarch string) bool { return goarch == "amd64" || goarch == "ppc64le" || goarch == "arm64" case "darwin": return goarch == "amd64" || goarch == "arm64" - case "freebsd", "netbsd", "windows": + case "freebsd", "netbsd", "openbsd", "windows": return goarch == "amd64" default: return false @@ -23,7 +23,8 @@ func RaceDetectorSupported(goos, goarch string) bool { } // MSanSupported reports whether goos/goarch supports the memory -// sanitizer option. There is a copy of this function in cmd/dist/test.go. +// sanitizer option. +// There is a copy of this function in misc/cgo/testsanitizers/cc_test.go. func MSanSupported(goos, goarch string) bool { switch goos { case "linux": @@ -73,7 +74,7 @@ func BuildModeSupported(compiler, buildmode, goos, goarch string) bool { "android/amd64", "android/arm", "android/arm64", "android/386", "freebsd/amd64", "darwin/amd64", "darwin/arm64", - "windows/amd64", "windows/386": + "windows/amd64", "windows/386", "windows/arm64": return true } return false diff --git a/libgo/go/cmd/vendor/modules.txt b/libgo/go/cmd/vendor/modules.txt index ae2c0a0..34dbdaf 100644 --- a/libgo/go/cmd/vendor/modules.txt +++ b/libgo/go/cmd/vendor/modules.txt @@ -1,5 +1,5 @@ -# github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2 -## explicit +# github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a +## explicit; go 1.14 github.com/google/pprof/driver github.com/google/pprof/internal/binutils github.com/google/pprof/internal/driver @@ -16,20 +16,20 @@ github.com/google/pprof/third_party/d3 github.com/google/pprof/third_party/d3flamegraph github.com/google/pprof/third_party/svgpan # github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 -github.com/ianlancetaylor/demangle -# golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff ## explicit +github.com/ianlancetaylor/demangle +# golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e +## explicit; go 1.17 golang.org/x/arch/arm/armasm golang.org/x/arch/arm64/arm64asm golang.org/x/arch/ppc64/ppc64asm golang.org/x/arch/x86/x86asm -# golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 -## explicit +# golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e +## explicit; go 1.17 golang.org/x/crypto/ed25519 golang.org/x/crypto/ed25519/internal/edwards25519 -golang.org/x/crypto/ssh/terminal -# golang.org/x/mod v0.4.2-0.20210325185522-dbbbf8a3c6ea -## explicit +# golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a +## explicit; go 1.17 golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile golang.org/x/mod/module @@ -39,13 +39,18 @@ golang.org/x/mod/sumdb/dirhash golang.org/x/mod/sumdb/note golang.org/x/mod/sumdb/tlog golang.org/x/mod/zip -# golang.org/x/sys v0.0.0-20201204225414-ed752295db88 -## explicit +# golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 +## explicit; go 1.17 golang.org/x/sys/internal/unsafeheader +golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/tools v0.0.0-20210107193943-4ed967dd8eff -## explicit +# golang.org/x/term v0.0.0-20210503060354-a79de5458b56 +## explicit; go 1.17 +golang.org/x/term +# golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9 +## explicit; go 1.17 +golang.org/x/tools/cover golang.org/x/tools/go/analysis golang.org/x/tools/go/analysis/internal/analysisflags golang.org/x/tools/go/analysis/internal/facts @@ -69,6 +74,7 @@ golang.org/x/tools/go/analysis/passes/lostcancel golang.org/x/tools/go/analysis/passes/nilfunc golang.org/x/tools/go/analysis/passes/printf golang.org/x/tools/go/analysis/passes/shift +golang.org/x/tools/go/analysis/passes/sigchanyzer golang.org/x/tools/go/analysis/passes/stdmethods golang.org/x/tools/go/analysis/passes/stringintconv golang.org/x/tools/go/analysis/passes/structtag @@ -87,5 +93,6 @@ golang.org/x/tools/go/types/typeutil golang.org/x/tools/internal/analysisinternal golang.org/x/tools/internal/lsp/fuzzy # golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 +## explicit; go 1.11 golang.org/x/xerrors golang.org/x/xerrors/internal diff --git a/libgo/go/cmd/vet/main.go b/libgo/go/cmd/vet/main.go index d50c45d..7da8606 100644 --- a/libgo/go/cmd/vet/main.go +++ b/libgo/go/cmd/vet/main.go @@ -1,3 +1,7 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package main import ( @@ -22,6 +26,7 @@ import ( "golang.org/x/tools/go/analysis/passes/nilfunc" "golang.org/x/tools/go/analysis/passes/printf" "golang.org/x/tools/go/analysis/passes/shift" + "golang.org/x/tools/go/analysis/passes/sigchanyzer" "golang.org/x/tools/go/analysis/passes/stdmethods" "golang.org/x/tools/go/analysis/passes/stringintconv" "golang.org/x/tools/go/analysis/passes/structtag" @@ -54,6 +59,7 @@ func main() { nilfunc.Analyzer, printf.Analyzer, shift.Analyzer, + sigchanyzer.Analyzer, stdmethods.Analyzer, stringintconv.Analyzer, structtag.Analyzer, diff --git a/libgo/go/cmd/vet/testdata/asm/asm1.s b/libgo/go/cmd/vet/testdata/asm/asm1.s index a5bb6dd..050c498 100644 --- a/libgo/go/cmd/vet/testdata/asm/asm1.s +++ b/libgo/go/cmd/vet/testdata/asm/asm1.s @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build amd64 // +build amd64 TEXT ·arg1(SB),0,$0-2 diff --git a/libgo/go/cmd/vet/testdata/buildtag/buildtag.go b/libgo/go/cmd/vet/testdata/buildtag/buildtag.go index c2fd6aa..7371e6e 100644 --- a/libgo/go/cmd/vet/testdata/buildtag/buildtag.go +++ b/libgo/go/cmd/vet/testdata/buildtag/buildtag.go @@ -4,12 +4,14 @@ // This file contains tests for the buildtag checker. -// +builder // ERROR "possible malformed \+build comment" +// ERRORNEXT "possible malformed [+]build comment" +// +builder // +build !ignore package testdata -// +build toolate // ERROR "build comment must appear before package clause and be followed by a blank line$" +// ERRORNEXT "misplaced \+build comment" +// +build toolate var _ = 3 diff --git a/libgo/go/cmd/vet/testdata/buildtag/buildtag2.go b/libgo/go/cmd/vet/testdata/buildtag/buildtag2.go new file mode 100644 index 0000000..d8808dd --- /dev/null +++ b/libgo/go/cmd/vet/testdata/buildtag/buildtag2.go @@ -0,0 +1,22 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains tests for the buildtag checker. + +// ERRORNEXT "possible malformed [+]build comment" +// +builder +// +build !ignore + +package testdata + +// ERRORNEXT "misplaced \+build comment" +// +build toolate +// ERRORNEXT "misplaced //go:build comment" +//go:build toolate + +var _ = 3 + +var _ = ` +// +build notacomment +` diff --git a/libgo/go/cmd/vet/testdata/buildtag/buildtag3.go b/libgo/go/cmd/vet/testdata/buildtag/buildtag3.go new file mode 100644 index 0000000..241a7db --- /dev/null +++ b/libgo/go/cmd/vet/testdata/buildtag/buildtag3.go @@ -0,0 +1,15 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains tests for the buildtag checker. + +//go:build good +// ERRORNEXT "[+]build lines do not match //go:build condition" +// +build bad + +package testdata + +var _ = ` +// +build notacomment +` diff --git a/libgo/go/cmd/vet/testdata/buildtag/buildtag4.go b/libgo/go/cmd/vet/testdata/buildtag/buildtag4.go new file mode 100644 index 0000000..5b40d695 --- /dev/null +++ b/libgo/go/cmd/vet/testdata/buildtag/buildtag4.go @@ -0,0 +1,11 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains tests for the buildtag checker. + +//go:build !(bad || worse) +// +build !bad +// +build !worse + +package testdata diff --git a/libgo/go/cmd/vet/testdata/buildtag/buildtag5.go b/libgo/go/cmd/vet/testdata/buildtag/buildtag5.go new file mode 100644 index 0000000..12aeb82 --- /dev/null +++ b/libgo/go/cmd/vet/testdata/buildtag/buildtag5.go @@ -0,0 +1,11 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains tests for the buildtag checker. + +//go:build !(bad || worse) + +package testdata + +// +build other // ERROR "misplaced \+build comment" diff --git a/libgo/go/io/ioutil/export_test.go b/libgo/go/cmd/vet/testdata/buildtag/buildtag6.s index dff55f0..40fe14c 100644 --- a/libgo/go/io/ioutil/export_test.go +++ b/libgo/go/cmd/vet/testdata/buildtag/buildtag6.s @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package ioutil +#include "go_asm.h" + +// ok because we cannot parse assembly files. +// +build no -var ErrPatternHasSeparator = errPatternHasSeparator diff --git a/libgo/go/cmd/vet/testdata/buildtag/buildtag7.s b/libgo/go/cmd/vet/testdata/buildtag/buildtag7.s new file mode 100644 index 0000000..b622d48 --- /dev/null +++ b/libgo/go/cmd/vet/testdata/buildtag/buildtag7.s @@ -0,0 +1,11 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +#include "go_asm.h" + +// ok because we cannot parse assembly files +// the assembler would complain if we did assemble this file. +//go:build no diff --git a/libgo/go/cmd/vet/testdata/copylock/copylock.go b/libgo/go/cmd/vet/testdata/copylock/copylock.go index 8079cf3..7cfafe6 100644 --- a/libgo/go/cmd/vet/testdata/copylock/copylock.go +++ b/libgo/go/cmd/vet/testdata/copylock/copylock.go @@ -1,3 +1,7 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package copylock import "sync" diff --git a/libgo/go/cmd/vet/testdata/httpresponse/httpresponse.go b/libgo/go/cmd/vet/testdata/httpresponse/httpresponse.go index 6141f6e..98e394a 100644 --- a/libgo/go/cmd/vet/testdata/httpresponse/httpresponse.go +++ b/libgo/go/cmd/vet/testdata/httpresponse/httpresponse.go @@ -1,3 +1,7 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package httpresponse import ( diff --git a/libgo/go/cmd/vet/testdata/tagtest/file1.go b/libgo/go/cmd/vet/testdata/tagtest/file1.go index 47fe3c8..2204524 100644 --- a/libgo/go/cmd/vet/testdata/tagtest/file1.go +++ b/libgo/go/cmd/vet/testdata/tagtest/file1.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build testtag // +build testtag package main diff --git a/libgo/go/cmd/vet/testdata/tagtest/file2.go b/libgo/go/cmd/vet/testdata/tagtest/file2.go index 1f45efc..979b0d4 100644 --- a/libgo/go/cmd/vet/testdata/tagtest/file2.go +++ b/libgo/go/cmd/vet/testdata/tagtest/file2.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !testtag // +build !testtag package main diff --git a/libgo/go/cmd/vet/testdata/testingpkg/tests.go b/libgo/go/cmd/vet/testdata/testingpkg/tests.go index 69d29d3..8f4674d 100644 --- a/libgo/go/cmd/vet/testdata/testingpkg/tests.go +++ b/libgo/go/cmd/vet/testdata/testingpkg/tests.go @@ -1 +1,5 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package testdata diff --git a/libgo/go/cmd/vet/testdata/testingpkg/tests_test.go b/libgo/go/cmd/vet/testdata/testingpkg/tests_test.go index 09bb98d..815dcc8 100644 --- a/libgo/go/cmd/vet/testdata/testingpkg/tests_test.go +++ b/libgo/go/cmd/vet/testdata/testingpkg/tests_test.go @@ -1,3 +1,7 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package testdata func Example_BadSuffix() {} // ERROR "Example_BadSuffix has malformed example suffix: BadSuffix" diff --git a/libgo/go/cmd/vet/vet_test.go b/libgo/go/cmd/vet/vet_test.go index 4c8dd3c..4726da2 100644 --- a/libgo/go/cmd/vet/vet_test.go +++ b/libgo/go/cmd/vet/vet_test.go @@ -338,8 +338,8 @@ type wantedError struct { } var ( - errRx = regexp.MustCompile(`// (?:GC_)?ERROR (.*)`) - errAutoRx = regexp.MustCompile(`// (?:GC_)?ERRORAUTO (.*)`) + errRx = regexp.MustCompile(`// (?:GC_)?ERROR(NEXT)? (.*)`) + errAutoRx = regexp.MustCompile(`// (?:GC_)?ERRORAUTO(NEXT)? (.*)`) errQuotesRx = regexp.MustCompile(`"([^"]*)"`) lineRx = regexp.MustCompile(`LINE(([+-])([0-9]+))?`) ) @@ -368,7 +368,10 @@ func wantedErrors(file, short string) (errs []wantedError) { if m == nil { continue } - all := m[1] + if m[1] == "NEXT" { + lineNum++ + } + all := m[2] mm := errQuotesRx.FindAllStringSubmatch(all, -1) if mm == nil { log.Fatalf("%s:%d: invalid errchk line: %s", file, lineNum, line) diff --git a/libgo/go/compress/lzw/reader.go b/libgo/go/compress/lzw/reader.go index f0802119..952870a 100644 --- a/libgo/go/compress/lzw/reader.go +++ b/libgo/go/compress/lzw/reader.go @@ -42,15 +42,15 @@ const ( flushBuffer = 1 << maxWidth ) -// decoder is the state from which the readXxx method converts a byte -// stream into a code stream. -type decoder struct { +// Reader is an io.Reader which can be used to read compressed data in the +// LZW format. +type Reader struct { r io.ByteReader bits uint32 nBits uint width uint - read func(*decoder) (uint16, error) // readLSB or readMSB - litWidth int // width in bits of literal codes + read func(*Reader) (uint16, error) // readLSB or readMSB + litWidth int // width in bits of literal codes err error // The first 1<<litWidth codes are literal codes. @@ -87,148 +87,158 @@ type decoder struct { } // readLSB returns the next code for "Least Significant Bits first" data. -func (d *decoder) readLSB() (uint16, error) { - for d.nBits < d.width { - x, err := d.r.ReadByte() +func (r *Reader) readLSB() (uint16, error) { + for r.nBits < r.width { + x, err := r.r.ReadByte() if err != nil { return 0, err } - d.bits |= uint32(x) << d.nBits - d.nBits += 8 + r.bits |= uint32(x) << r.nBits + r.nBits += 8 } - code := uint16(d.bits & (1<<d.width - 1)) - d.bits >>= d.width - d.nBits -= d.width + code := uint16(r.bits & (1<<r.width - 1)) + r.bits >>= r.width + r.nBits -= r.width return code, nil } // readMSB returns the next code for "Most Significant Bits first" data. -func (d *decoder) readMSB() (uint16, error) { - for d.nBits < d.width { - x, err := d.r.ReadByte() +func (r *Reader) readMSB() (uint16, error) { + for r.nBits < r.width { + x, err := r.r.ReadByte() if err != nil { return 0, err } - d.bits |= uint32(x) << (24 - d.nBits) - d.nBits += 8 + r.bits |= uint32(x) << (24 - r.nBits) + r.nBits += 8 } - code := uint16(d.bits >> (32 - d.width)) - d.bits <<= d.width - d.nBits -= d.width + code := uint16(r.bits >> (32 - r.width)) + r.bits <<= r.width + r.nBits -= r.width return code, nil } -func (d *decoder) Read(b []byte) (int, error) { +// Read implements io.Reader, reading uncompressed bytes from its underlying Reader. +func (r *Reader) Read(b []byte) (int, error) { for { - if len(d.toRead) > 0 { - n := copy(b, d.toRead) - d.toRead = d.toRead[n:] + if len(r.toRead) > 0 { + n := copy(b, r.toRead) + r.toRead = r.toRead[n:] return n, nil } - if d.err != nil { - return 0, d.err + if r.err != nil { + return 0, r.err } - d.decode() + r.decode() } } // decode decompresses bytes from r and leaves them in d.toRead. // read specifies how to decode bytes into codes. // litWidth is the width in bits of literal codes. -func (d *decoder) decode() { +func (r *Reader) decode() { // Loop over the code stream, converting codes into decompressed bytes. loop: for { - code, err := d.read(d) + code, err := r.read(r) if err != nil { if err == io.EOF { err = io.ErrUnexpectedEOF } - d.err = err + r.err = err break } switch { - case code < d.clear: + case code < r.clear: // We have a literal code. - d.output[d.o] = uint8(code) - d.o++ - if d.last != decoderInvalidCode { + r.output[r.o] = uint8(code) + r.o++ + if r.last != decoderInvalidCode { // Save what the hi code expands to. - d.suffix[d.hi] = uint8(code) - d.prefix[d.hi] = d.last + r.suffix[r.hi] = uint8(code) + r.prefix[r.hi] = r.last } - case code == d.clear: - d.width = 1 + uint(d.litWidth) - d.hi = d.eof - d.overflow = 1 << d.width - d.last = decoderInvalidCode + case code == r.clear: + r.width = 1 + uint(r.litWidth) + r.hi = r.eof + r.overflow = 1 << r.width + r.last = decoderInvalidCode continue - case code == d.eof: - d.err = io.EOF + case code == r.eof: + r.err = io.EOF break loop - case code <= d.hi: - c, i := code, len(d.output)-1 - if code == d.hi && d.last != decoderInvalidCode { + case code <= r.hi: + c, i := code, len(r.output)-1 + if code == r.hi && r.last != decoderInvalidCode { // code == hi is a special case which expands to the last expansion // followed by the head of the last expansion. To find the head, we walk // the prefix chain until we find a literal code. - c = d.last - for c >= d.clear { - c = d.prefix[c] + c = r.last + for c >= r.clear { + c = r.prefix[c] } - d.output[i] = uint8(c) + r.output[i] = uint8(c) i-- - c = d.last + c = r.last } // Copy the suffix chain into output and then write that to w. - for c >= d.clear { - d.output[i] = d.suffix[c] + for c >= r.clear { + r.output[i] = r.suffix[c] i-- - c = d.prefix[c] + c = r.prefix[c] } - d.output[i] = uint8(c) - d.o += copy(d.output[d.o:], d.output[i:]) - if d.last != decoderInvalidCode { + r.output[i] = uint8(c) + r.o += copy(r.output[r.o:], r.output[i:]) + if r.last != decoderInvalidCode { // Save what the hi code expands to. - d.suffix[d.hi] = uint8(c) - d.prefix[d.hi] = d.last + r.suffix[r.hi] = uint8(c) + r.prefix[r.hi] = r.last } default: - d.err = errors.New("lzw: invalid code") + r.err = errors.New("lzw: invalid code") break loop } - d.last, d.hi = code, d.hi+1 - if d.hi >= d.overflow { - if d.hi > d.overflow { + r.last, r.hi = code, r.hi+1 + if r.hi >= r.overflow { + if r.hi > r.overflow { panic("unreachable") } - if d.width == maxWidth { - d.last = decoderInvalidCode + if r.width == maxWidth { + r.last = decoderInvalidCode // Undo the d.hi++ a few lines above, so that (1) we maintain // the invariant that d.hi < d.overflow, and (2) d.hi does not // eventually overflow a uint16. - d.hi-- + r.hi-- } else { - d.width++ - d.overflow = 1 << d.width + r.width++ + r.overflow = 1 << r.width } } - if d.o >= flushBuffer { + if r.o >= flushBuffer { break } } // Flush pending output. - d.toRead = d.output[:d.o] - d.o = 0 + r.toRead = r.output[:r.o] + r.o = 0 } var errClosed = errors.New("lzw: reader/writer is closed") -func (d *decoder) Close() error { - d.err = errClosed // in case any Reads come along +// Close closes the Reader and returns an error for any future read operation. +// It does not close the underlying io.Reader. +func (r *Reader) Close() error { + r.err = errClosed // in case any Reads come along return nil } +// Reset clears the Reader's state and allows it to be reused again +// as a new Reader. +func (r *Reader) Reset(src io.Reader, order Order, litWidth int) { + *r = Reader{} + r.init(src, order, litWidth) +} + // NewReader creates a new io.ReadCloser. // Reads from the returned io.ReadCloser read and decompress data from r. // If r does not also implement io.ByteReader, @@ -238,32 +248,43 @@ func (d *decoder) Close() error { // The number of bits to use for literal codes, litWidth, must be in the // range [2,8] and is typically 8. It must equal the litWidth // used during compression. +// +// It is guaranteed that the underlying type of the returned io.ReadCloser +// is a *Reader. func NewReader(r io.Reader, order Order, litWidth int) io.ReadCloser { - d := new(decoder) + return newReader(r, order, litWidth) +} + +func newReader(src io.Reader, order Order, litWidth int) *Reader { + r := new(Reader) + r.init(src, order, litWidth) + return r +} + +func (r *Reader) init(src io.Reader, order Order, litWidth int) { switch order { case LSB: - d.read = (*decoder).readLSB + r.read = (*Reader).readLSB case MSB: - d.read = (*decoder).readMSB + r.read = (*Reader).readMSB default: - d.err = errors.New("lzw: unknown order") - return d + r.err = errors.New("lzw: unknown order") + return } if litWidth < 2 || 8 < litWidth { - d.err = fmt.Errorf("lzw: litWidth %d out of range", litWidth) - return d + r.err = fmt.Errorf("lzw: litWidth %d out of range", litWidth) + return } - if br, ok := r.(io.ByteReader); ok { - d.r = br - } else { - d.r = bufio.NewReader(r) - } - d.litWidth = litWidth - d.width = 1 + uint(litWidth) - d.clear = uint16(1) << uint(litWidth) - d.eof, d.hi = d.clear+1, d.clear+1 - d.overflow = uint16(1) << d.width - d.last = decoderInvalidCode - return d + br, ok := src.(io.ByteReader) + if !ok && src != nil { + br = bufio.NewReader(src) + } + r.r = br + r.litWidth = litWidth + r.width = 1 + uint(litWidth) + r.clear = uint16(1) << uint(litWidth) + r.eof, r.hi = r.clear+1, r.clear+1 + r.overflow = uint16(1) << r.width + r.last = decoderInvalidCode } diff --git a/libgo/go/compress/lzw/reader_test.go b/libgo/go/compress/lzw/reader_test.go index d1eb76d..9a2a477 100644 --- a/libgo/go/compress/lzw/reader_test.go +++ b/libgo/go/compress/lzw/reader_test.go @@ -120,6 +120,53 @@ func TestReader(t *testing.T) { } } +func TestReaderReset(t *testing.T) { + var b bytes.Buffer + for _, tt := range lzwTests { + d := strings.Split(tt.desc, ";") + var order Order + switch d[1] { + case "LSB": + order = LSB + case "MSB": + order = MSB + default: + t.Errorf("%s: bad order %q", tt.desc, d[1]) + } + litWidth, _ := strconv.Atoi(d[2]) + rc := NewReader(strings.NewReader(tt.compressed), order, litWidth) + defer rc.Close() + b.Reset() + n, err := io.Copy(&b, rc) + b1 := b.Bytes() + if err != nil { + if err != tt.err { + t.Errorf("%s: io.Copy: %v want %v", tt.desc, err, tt.err) + } + if err == io.ErrUnexpectedEOF { + // Even if the input is truncated, we should still return the + // partial decoded result. + if n == 0 || !strings.HasPrefix(tt.raw, b.String()) { + t.Errorf("got %d bytes (%q), want a non-empty prefix of %q", n, b.String(), tt.raw) + } + } + continue + } + + b.Reset() + rc.(*Reader).Reset(strings.NewReader(tt.compressed), order, litWidth) + n, err = io.Copy(&b, rc) + b2 := b.Bytes() + if err != nil { + t.Errorf("%s: io.Copy: %v want %v", tt.desc, err, nil) + continue + } + if !bytes.Equal(b1, b2) { + t.Errorf("bytes read were not the same") + } + } +} + type devZero struct{} func (devZero) Read(p []byte) (int, error) { @@ -131,7 +178,7 @@ func (devZero) Read(p []byte) (int, error) { func TestHiCodeDoesNotOverflow(t *testing.T) { r := NewReader(devZero{}, LSB, 8) - d := r.(*decoder) + d := r.(*Reader) buf := make([]byte, 1024) oldHi := uint16(0) for i := 0; i < 100; i++ { @@ -226,28 +273,43 @@ func BenchmarkDecoder(b *testing.B) { b.Fatalf("test file has no data") } + getInputBuf := func(buf []byte, n int) []byte { + compressed := new(bytes.Buffer) + w := NewWriter(compressed, LSB, 8) + for i := 0; i < n; i += len(buf) { + if len(buf) > n-i { + buf = buf[:n-i] + } + w.Write(buf) + } + w.Close() + return compressed.Bytes() + } + for e := 4; e <= 6; e++ { n := int(math.Pow10(e)) b.Run(fmt.Sprint("1e", e), func(b *testing.B) { b.StopTimer() b.SetBytes(int64(n)) - buf0 := buf - compressed := new(bytes.Buffer) - w := NewWriter(compressed, LSB, 8) - for i := 0; i < n; i += len(buf0) { - if len(buf0) > n-i { - buf0 = buf0[:n-i] - } - w.Write(buf0) - } - w.Close() - buf1 := compressed.Bytes() - buf0, compressed, w = nil, nil, nil + buf1 := getInputBuf(buf, n) runtime.GC() b.StartTimer() for i := 0; i < b.N; i++ { io.Copy(io.Discard, NewReader(bytes.NewReader(buf1), LSB, 8)) } }) + b.Run(fmt.Sprint("1e-Reuse", e), func(b *testing.B) { + b.StopTimer() + b.SetBytes(int64(n)) + buf1 := getInputBuf(buf, n) + runtime.GC() + b.StartTimer() + r := NewReader(bytes.NewReader(buf1), LSB, 8) + for i := 0; i < b.N; i++ { + io.Copy(io.Discard, r) + r.Close() + r.(*Reader).Reset(bytes.NewReader(buf1), LSB, 8) + } + }) } } diff --git a/libgo/go/compress/lzw/writer.go b/libgo/go/compress/lzw/writer.go index 6ddb335..552bdc2 100644 --- a/libgo/go/compress/lzw/writer.go +++ b/libgo/go/compress/lzw/writer.go @@ -17,19 +17,6 @@ type writer interface { Flush() error } -// An errWriteCloser is an io.WriteCloser that always returns a given error. -type errWriteCloser struct { - err error -} - -func (e *errWriteCloser) Write([]byte) (int, error) { - return 0, e.err -} - -func (e *errWriteCloser) Close() error { - return e.err -} - const ( // A code is a 12 bit value, stored as a uint32 when encoding to avoid // type conversions when shifting bits. @@ -44,14 +31,15 @@ const ( invalidEntry = 0 ) -// encoder is LZW compressor. -type encoder struct { +// Writer is an LZW compressor. It writes the compressed form of the data +// to an underlying writer (see NewWriter). +type Writer struct { // w is the writer that compressed bytes are written to. w writer // order, write, bits, nBits and width are the state for // converting a code stream into a byte stream. order Order - write func(*encoder, uint32) error + write func(*Writer, uint32) error bits uint32 nBits uint width uint @@ -63,7 +51,7 @@ type encoder struct { // savedCode is the accumulated code at the end of the most recent Write // call. It is equal to invalidCode if there was no such call. savedCode uint32 - // err is the first error encountered during writing. Closing the encoder + // err is the first error encountered during writing. Closing the writer // will make any future Write calls return errClosed err error // table is the hash table from 20-bit keys to 12-bit values. Each table @@ -74,80 +62,80 @@ type encoder struct { } // writeLSB writes the code c for "Least Significant Bits first" data. -func (e *encoder) writeLSB(c uint32) error { - e.bits |= c << e.nBits - e.nBits += e.width - for e.nBits >= 8 { - if err := e.w.WriteByte(uint8(e.bits)); err != nil { +func (w *Writer) writeLSB(c uint32) error { + w.bits |= c << w.nBits + w.nBits += w.width + for w.nBits >= 8 { + if err := w.w.WriteByte(uint8(w.bits)); err != nil { return err } - e.bits >>= 8 - e.nBits -= 8 + w.bits >>= 8 + w.nBits -= 8 } return nil } // writeMSB writes the code c for "Most Significant Bits first" data. -func (e *encoder) writeMSB(c uint32) error { - e.bits |= c << (32 - e.width - e.nBits) - e.nBits += e.width - for e.nBits >= 8 { - if err := e.w.WriteByte(uint8(e.bits >> 24)); err != nil { +func (w *Writer) writeMSB(c uint32) error { + w.bits |= c << (32 - w.width - w.nBits) + w.nBits += w.width + for w.nBits >= 8 { + if err := w.w.WriteByte(uint8(w.bits >> 24)); err != nil { return err } - e.bits <<= 8 - e.nBits -= 8 + w.bits <<= 8 + w.nBits -= 8 } return nil } -// errOutOfCodes is an internal error that means that the encoder has run out +// errOutOfCodes is an internal error that means that the writer has run out // of unused codes and a clear code needs to be sent next. var errOutOfCodes = errors.New("lzw: out of codes") // incHi increments e.hi and checks for both overflow and running out of // unused codes. In the latter case, incHi sends a clear code, resets the -// encoder state and returns errOutOfCodes. -func (e *encoder) incHi() error { - e.hi++ - if e.hi == e.overflow { - e.width++ - e.overflow <<= 1 +// writer state and returns errOutOfCodes. +func (w *Writer) incHi() error { + w.hi++ + if w.hi == w.overflow { + w.width++ + w.overflow <<= 1 } - if e.hi == maxCode { - clear := uint32(1) << e.litWidth - if err := e.write(e, clear); err != nil { + if w.hi == maxCode { + clear := uint32(1) << w.litWidth + if err := w.write(w, clear); err != nil { return err } - e.width = e.litWidth + 1 - e.hi = clear + 1 - e.overflow = clear << 1 - for i := range e.table { - e.table[i] = invalidEntry + w.width = w.litWidth + 1 + w.hi = clear + 1 + w.overflow = clear << 1 + for i := range w.table { + w.table[i] = invalidEntry } return errOutOfCodes } return nil } -// Write writes a compressed representation of p to e's underlying writer. -func (e *encoder) Write(p []byte) (n int, err error) { - if e.err != nil { - return 0, e.err +// Write writes a compressed representation of p to w's underlying writer. +func (w *Writer) Write(p []byte) (n int, err error) { + if w.err != nil { + return 0, w.err } if len(p) == 0 { return 0, nil } - if maxLit := uint8(1<<e.litWidth - 1); maxLit != 0xff { + if maxLit := uint8(1<<w.litWidth - 1); maxLit != 0xff { for _, x := range p { if x > maxLit { - e.err = errors.New("lzw: input byte too large for the litWidth") - return 0, e.err + w.err = errors.New("lzw: input byte too large for the litWidth") + return 0, w.err } } } n = len(p) - code := e.savedCode + code := w.savedCode if code == invalidCode { // The first code sent is always a literal code. code, p = uint32(p[0]), p[1:] @@ -159,77 +147,84 @@ loop: // If there is a hash table hit for this key then we continue the loop // and do not emit a code yet. hash := (key>>12 ^ key) & tableMask - for h, t := hash, e.table[hash]; t != invalidEntry; { + for h, t := hash, w.table[hash]; t != invalidEntry; { if key == t>>12 { code = t & maxCode continue loop } h = (h + 1) & tableMask - t = e.table[h] + t = w.table[h] } // Otherwise, write the current code, and literal becomes the start of // the next emitted code. - if e.err = e.write(e, code); e.err != nil { - return 0, e.err + if w.err = w.write(w, code); w.err != nil { + return 0, w.err } code = literal // Increment e.hi, the next implied code. If we run out of codes, reset - // the encoder state (including clearing the hash table) and continue. - if err1 := e.incHi(); err1 != nil { + // the writer state (including clearing the hash table) and continue. + if err1 := w.incHi(); err1 != nil { if err1 == errOutOfCodes { continue } - e.err = err1 - return 0, e.err + w.err = err1 + return 0, w.err } // Otherwise, insert key -> e.hi into the map that e.table represents. for { - if e.table[hash] == invalidEntry { - e.table[hash] = (key << 12) | e.hi + if w.table[hash] == invalidEntry { + w.table[hash] = (key << 12) | w.hi break } hash = (hash + 1) & tableMask } } - e.savedCode = code + w.savedCode = code return n, nil } -// Close closes the encoder, flushing any pending output. It does not close or -// flush e's underlying writer. -func (e *encoder) Close() error { - if e.err != nil { - if e.err == errClosed { +// Close closes the Writer, flushing any pending output. It does not close +// w's underlying writer. +func (w *Writer) Close() error { + if w.err != nil { + if w.err == errClosed { return nil } - return e.err + return w.err } // Make any future calls to Write return errClosed. - e.err = errClosed + w.err = errClosed // Write the savedCode if valid. - if e.savedCode != invalidCode { - if err := e.write(e, e.savedCode); err != nil { + if w.savedCode != invalidCode { + if err := w.write(w, w.savedCode); err != nil { return err } - if err := e.incHi(); err != nil && err != errOutOfCodes { + if err := w.incHi(); err != nil && err != errOutOfCodes { return err } } // Write the eof code. - eof := uint32(1)<<e.litWidth + 1 - if err := e.write(e, eof); err != nil { + eof := uint32(1)<<w.litWidth + 1 + if err := w.write(w, eof); err != nil { return err } // Write the final bits. - if e.nBits > 0 { - if e.order == MSB { - e.bits >>= 24 + if w.nBits > 0 { + if w.order == MSB { + w.bits >>= 24 } - if err := e.w.WriteByte(uint8(e.bits)); err != nil { + if err := w.w.WriteByte(uint8(w.bits)); err != nil { return err } } - return e.w.Flush() + return w.w.Flush() +} + +// Reset clears the Writer's state and allows it to be reused again +// as a new Writer. +func (w *Writer) Reset(dst io.Writer, order Order, litWidth int) { + *w = Writer{} + w.init(dst, order, litWidth) } // NewWriter creates a new io.WriteCloser. @@ -238,32 +233,43 @@ func (e *encoder) Close() error { // finished writing. // The number of bits to use for literal codes, litWidth, must be in the // range [2,8] and is typically 8. Input bytes must be less than 1<<litWidth. +// +// It is guaranteed that the underlying type of the returned io.WriteCloser +// is a *Writer. func NewWriter(w io.Writer, order Order, litWidth int) io.WriteCloser { - var write func(*encoder, uint32) error + return newWriter(w, order, litWidth) +} + +func newWriter(dst io.Writer, order Order, litWidth int) *Writer { + w := new(Writer) + w.init(dst, order, litWidth) + return w +} + +func (w *Writer) init(dst io.Writer, order Order, litWidth int) { switch order { case LSB: - write = (*encoder).writeLSB + w.write = (*Writer).writeLSB case MSB: - write = (*encoder).writeMSB + w.write = (*Writer).writeMSB default: - return &errWriteCloser{errors.New("lzw: unknown order")} + w.err = errors.New("lzw: unknown order") + return } if litWidth < 2 || 8 < litWidth { - return &errWriteCloser{fmt.Errorf("lzw: litWidth %d out of range", litWidth)} + w.err = fmt.Errorf("lzw: litWidth %d out of range", litWidth) + return } - bw, ok := w.(writer) - if !ok { - bw = bufio.NewWriter(w) + bw, ok := dst.(writer) + if !ok && dst != nil { + bw = bufio.NewWriter(dst) } + w.w = bw lw := uint(litWidth) - return &encoder{ - w: bw, - order: order, - write: write, - width: 1 + lw, - litWidth: lw, - hi: 1<<lw + 1, - overflow: 1 << (lw + 1), - savedCode: invalidCode, - } + w.order = order + w.width = 1 + lw + w.litWidth = lw + w.hi = 1<<lw + 1 + w.overflow = 1 << (lw + 1) + w.savedCode = invalidCode } diff --git a/libgo/go/compress/lzw/writer_test.go b/libgo/go/compress/lzw/writer_test.go index 1a5dbca..9f59c8b 100644 --- a/libgo/go/compress/lzw/writer_test.go +++ b/libgo/go/compress/lzw/writer_test.go @@ -5,6 +5,7 @@ package lzw import ( + "bytes" "fmt" "internal/testenv" "io" @@ -105,6 +106,50 @@ func TestWriter(t *testing.T) { } } +func TestWriterReset(t *testing.T) { + for _, order := range [...]Order{LSB, MSB} { + t.Run(fmt.Sprintf("Order %d", order), func(t *testing.T) { + for litWidth := 6; litWidth <= 8; litWidth++ { + t.Run(fmt.Sprintf("LitWidth %d", litWidth), func(t *testing.T) { + var data []byte + if litWidth == 6 { + data = []byte{1, 2, 3} + } else { + data = []byte(`lorem ipsum dolor sit amet`) + } + var buf bytes.Buffer + w := NewWriter(&buf, order, litWidth) + if _, err := w.Write(data); err != nil { + t.Errorf("write: %v: %v", string(data), err) + } + + if err := w.Close(); err != nil { + t.Errorf("close: %v", err) + } + + b1 := buf.Bytes() + buf.Reset() + + w.(*Writer).Reset(&buf, order, litWidth) + + if _, err := w.Write(data); err != nil { + t.Errorf("write: %v: %v", string(data), err) + } + + if err := w.Close(); err != nil { + t.Errorf("close: %v", err) + } + b2 := buf.Bytes() + + if !bytes.Equal(b1, b2) { + t.Errorf("bytes written were not same") + } + }) + } + }) + } +} + func TestWriterReturnValues(t *testing.T) { w := NewWriter(io.Discard, LSB, 8) n, err := w.Write([]byte("asdf")) @@ -152,5 +197,14 @@ func BenchmarkEncoder(b *testing.B) { w.Close() } }) + b.Run(fmt.Sprint("1e-Reuse", e), func(b *testing.B) { + b.SetBytes(int64(n)) + w := NewWriter(io.Discard, LSB, 8) + for i := 0; i < b.N; i++ { + w.Write(buf1) + w.Close() + w.(*Writer).Reset(io.Discard, LSB, 8) + } + }) } } diff --git a/libgo/go/context/benchmark_test.go b/libgo/go/context/benchmark_test.go index 5d56863..69d75ff 100644 --- a/libgo/go/context/benchmark_test.go +++ b/libgo/go/context/benchmark_test.go @@ -138,3 +138,17 @@ func BenchmarkCheckCanceled(b *testing.B) { } }) } + +func BenchmarkContextCancelDone(b *testing.B) { + ctx, cancel := WithCancel(Background()) + defer cancel() + + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + select { + case <-ctx.Done(): + default: + } + } + }) +} diff --git a/libgo/go/context/context.go b/libgo/go/context/context.go index b3fdb82..733c5f5 100644 --- a/libgo/go/context/context.go +++ b/libgo/go/context/context.go @@ -303,10 +303,8 @@ func parentCancelCtx(parent Context) (*cancelCtx, bool) { if !ok { return nil, false } - p.mu.Lock() - ok = p.done == done - p.mu.Unlock() - if !ok { + pdone, _ := p.done.Load().(chan struct{}) + if pdone != done { return nil, false } return p, true @@ -345,7 +343,7 @@ type cancelCtx struct { Context mu sync.Mutex // protects following fields - done chan struct{} // created lazily, closed by first cancel call + done atomic.Value // of chan struct{}, created lazily, closed by first cancel call children map[canceler]struct{} // set to nil by the first cancel call err error // set to non-nil by the first cancel call } @@ -358,13 +356,18 @@ func (c *cancelCtx) Value(key interface{}) interface{} { } func (c *cancelCtx) Done() <-chan struct{} { + d := c.done.Load() + if d != nil { + return d.(chan struct{}) + } c.mu.Lock() - if c.done == nil { - c.done = make(chan struct{}) + defer c.mu.Unlock() + d = c.done.Load() + if d == nil { + d = make(chan struct{}) + c.done.Store(d) } - d := c.done - c.mu.Unlock() - return d + return d.(chan struct{}) } func (c *cancelCtx) Err() error { @@ -401,10 +404,11 @@ func (c *cancelCtx) cancel(removeFromParent bool, err error) { return // already canceled } c.err = err - if c.done == nil { - c.done = closedchan + d, _ := c.done.Load().(chan struct{}) + if d == nil { + c.done.Store(closedchan) } else { - close(c.done) + close(d) } for child := range c.children { // NOTE: acquiring the child's lock while holding parent's lock. diff --git a/libgo/go/context/context_test.go b/libgo/go/context/context_test.go index 6b392a2..a2e2324 100644 --- a/libgo/go/context/context_test.go +++ b/libgo/go/context/context_test.go @@ -525,7 +525,7 @@ func XTestInterlockedCancels(t testingT) { parent, cancelParent := WithCancel(Background()) child, cancelChild := WithCancel(parent) go func() { - parent.Done() + <-parent.Done() cancelChild() }() cancelParent() @@ -661,7 +661,7 @@ func XTestWithCancelCanceledParent(t testingT) { t.Errorf("child not done immediately upon construction") } if got, want := c.Err(), Canceled; got != want { - t.Errorf("child not cancelled; got = %v, want = %v", got, want) + t.Errorf("child not canceled; got = %v, want = %v", got, want) } } @@ -779,7 +779,7 @@ func XTestCustomContextGoroutines(t testingT) { defer cancel6() checkNoGoroutine() - // Check applied to cancelled context. + // Check applied to canceled context. cancel6() cancel1() _, cancel7 := WithCancel(ctx5) diff --git a/libgo/go/crypto/aes/aes_gcm.go b/libgo/go/crypto/aes/aes_gcm.go index 3888010..4b27615 100644 --- a/libgo/go/crypto/aes/aes_gcm.go +++ b/libgo/go/crypto/aes/aes_gcm.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore -// -build amd64 arm64 package aes diff --git a/libgo/go/crypto/aes/cipher_asm.go b/libgo/go/crypto/aes/cipher_asm.go index dc4251a..ee7df2b 100644 --- a/libgo/go/crypto/aes/cipher_asm.go +++ b/libgo/go/crypto/aes/cipher_asm.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build ignore_for_gccgo -// +build amd64 arm64 +//go:build ignore +// +build ignore package aes diff --git a/libgo/go/crypto/aes/cipher_generic.go b/libgo/go/crypto/aes/cipher_generic.go index 19a930f0..1630331 100644 --- a/libgo/go/crypto/aes/cipher_generic.go +++ b/libgo/go/crypto/aes/cipher_generic.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//-go:build !amd64 && !s390x && !ppc64le && !arm64 // -build !amd64,!s390x,!ppc64le,!arm64 package aes diff --git a/libgo/go/crypto/aes/gcm_ppc64le.go b/libgo/go/crypto/aes/gcm_ppc64le.go index 707478c..232eae1 100644 --- a/libgo/go/crypto/aes/gcm_ppc64le.go +++ b/libgo/go/crypto/aes/gcm_ppc64le.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore -// +build ppc64le package aes diff --git a/libgo/go/crypto/cipher/benchmark_test.go b/libgo/go/crypto/cipher/benchmark_test.go index 90d0cd7..eb02cd0 100644 --- a/libgo/go/crypto/cipher/benchmark_test.go +++ b/libgo/go/crypto/cipher/benchmark_test.go @@ -7,28 +7,15 @@ package cipher_test import ( "crypto/aes" "crypto/cipher" + "strconv" "testing" ) -func benchmarkAESGCMSign(b *testing.B, buf []byte) { +func benchmarkAESGCMSeal(b *testing.B, buf []byte, keySize int) { + b.ReportAllocs() b.SetBytes(int64(len(buf))) - var key [16]byte - var nonce [12]byte - aes, _ := aes.NewCipher(key[:]) - aesgcm, _ := cipher.NewGCM(aes) - var out []byte - - b.ResetTimer() - for i := 0; i < b.N; i++ { - out = aesgcm.Seal(out[:0], nonce[:], nil, buf) - } -} - -func benchmarkAESGCMSeal(b *testing.B, buf []byte) { - b.SetBytes(int64(len(buf))) - - var key [16]byte + var key = make([]byte, keySize) var nonce [12]byte var ad [13]byte aes, _ := aes.NewCipher(key[:]) @@ -41,44 +28,41 @@ func benchmarkAESGCMSeal(b *testing.B, buf []byte) { } } -func benchmarkAESGCMOpen(b *testing.B, buf []byte) { +func benchmarkAESGCMOpen(b *testing.B, buf []byte, keySize int) { + b.ReportAllocs() b.SetBytes(int64(len(buf))) - var key [16]byte + var key = make([]byte, keySize) var nonce [12]byte var ad [13]byte aes, _ := aes.NewCipher(key[:]) aesgcm, _ := cipher.NewGCM(aes) var out []byte - out = aesgcm.Seal(out[:0], nonce[:], buf, ad[:]) + + ct := aesgcm.Seal(nil, nonce[:], buf[:], ad[:]) b.ResetTimer() for i := 0; i < b.N; i++ { - _, err := aesgcm.Open(buf[:0], nonce[:], out, ad[:]) - if err != nil { - b.Errorf("Open: %v", err) - } + out, _ = aesgcm.Open(out[:0], nonce[:], ct, ad[:]) } } -func BenchmarkAESGCMSeal1K(b *testing.B) { - benchmarkAESGCMSeal(b, make([]byte, 1024)) -} - -func BenchmarkAESGCMOpen1K(b *testing.B) { - benchmarkAESGCMOpen(b, make([]byte, 1024)) -} - -func BenchmarkAESGCMSign8K(b *testing.B) { - benchmarkAESGCMSign(b, make([]byte, 8*1024)) -} - -func BenchmarkAESGCMSeal8K(b *testing.B) { - benchmarkAESGCMSeal(b, make([]byte, 8*1024)) -} - -func BenchmarkAESGCMOpen8K(b *testing.B) { - benchmarkAESGCMOpen(b, make([]byte, 8*1024)) +func BenchmarkAESGCM(b *testing.B) { + for _, length := range []int{64, 1350, 8 * 1024} { + b.Run("Open-128-"+strconv.Itoa(length), func(b *testing.B) { + benchmarkAESGCMOpen(b, make([]byte, length), 128/8) + }) + b.Run("Seal-128-"+strconv.Itoa(length), func(b *testing.B) { + benchmarkAESGCMSeal(b, make([]byte, length), 128/8) + }) + + b.Run("Open-256-"+strconv.Itoa(length), func(b *testing.B) { + benchmarkAESGCMOpen(b, make([]byte, length), 256/8) + }) + b.Run("Seal-256-"+strconv.Itoa(length), func(b *testing.B) { + benchmarkAESGCMSeal(b, make([]byte, length), 256/8) + }) + } } func benchmarkAESStream(b *testing.B, mode func(cipher.Block, []byte) cipher.Stream, buf []byte) { diff --git a/libgo/go/crypto/cipher/xor_generic.go b/libgo/go/crypto/cipher/xor_generic.go index b80a1b9..cddc842 100644 --- a/libgo/go/crypto/cipher/xor_generic.go +++ b/libgo/go/crypto/cipher/xor_generic.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//-go:build !amd64 && !ppc64 && !ppc64le && !arm64 // -build !amd64,!ppc64,!ppc64le,!arm64 package cipher diff --git a/libgo/go/crypto/cipher/xor_ppc64x.go b/libgo/go/crypto/cipher/xor_ppc64x.go index e7d67f4..097ea05 100644 --- a/libgo/go/crypto/cipher/xor_ppc64x.go +++ b/libgo/go/crypto/cipher/xor_ppc64x.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore -// +build ppc64 ppc64le package cipher diff --git a/libgo/go/crypto/ecdsa/ecdsa.go b/libgo/go/crypto/ecdsa/ecdsa.go index ccce873..2194369 100644 --- a/libgo/go/crypto/ecdsa/ecdsa.go +++ b/libgo/go/crypto/ecdsa/ecdsa.go @@ -17,7 +17,7 @@ // [Coron] // https://cs.nyu.edu/~dodis/ps/merkle.pdf // [Larsson] -// https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf +// https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf package ecdsa // Further references: diff --git a/libgo/go/crypto/ecdsa/ecdsa_noasm.go b/libgo/go/crypto/ecdsa/ecdsa_noasm.go index b7e7317..717e80d 100644 --- a/libgo/go/crypto/ecdsa/ecdsa_noasm.go +++ b/libgo/go/crypto/ecdsa/ecdsa_noasm.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//-go:build !s390x // -build !s390x package ecdsa diff --git a/libgo/go/crypto/ecdsa/ecdsa_s390x.go b/libgo/go/crypto/ecdsa/ecdsa_s390x.go index de51cab..b43b82b 100644 --- a/libgo/go/crypto/ecdsa/ecdsa_s390x.go +++ b/libgo/go/crypto/ecdsa/ecdsa_s390x.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore_for_gccgo // +build ignore_for_gccgo package ecdsa @@ -23,12 +24,18 @@ import ( //go:noescape func kdsa(fc uint64, params *[4096]byte) (errn uint64) +// testingDisableKDSA forces the generic fallback path. It must only be set in tests. +var testingDisableKDSA bool + // canUseKDSA checks if KDSA instruction is available, and if it is, it checks // the name of the curve to see if it matches the curves supported(P-256, P-384, P-521). // Then, based on the curve name, a function code and a block size will be assigned. // If KDSA instruction is not available or if the curve is not supported, canUseKDSA // will set ok to false. func canUseKDSA(c elliptic.Curve) (functionCode uint64, blockSize int, ok bool) { + if testingDisableKDSA { + return 0, 0, false + } if !cpu.S390X.HasECDSA { return 0, 0, false } diff --git a/libgo/go/crypto/ecdsa/ecdsa_s390x_test.go b/libgo/go/crypto/ecdsa/ecdsa_s390x_test.go index 4fc6dfb..6070afc 100644 --- a/libgo/go/crypto/ecdsa/ecdsa_s390x_test.go +++ b/libgo/go/crypto/ecdsa/ecdsa_s390x_test.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build ignore_for_gccgo -// +build s390x +//go:build ignore +// +build ignore package ecdsa @@ -13,6 +13,9 @@ import ( ) func TestNoAsm(t *testing.T) { + testingDisableKDSA = true + defer func() { testingDisableKDSA = false }() + curves := [...]elliptic.Curve{ elliptic.P256(), elliptic.P384(), @@ -20,15 +23,11 @@ func TestNoAsm(t *testing.T) { } for _, curve := range curves { - // override the name of the curve to stop the assembly path being taken - params := *curve.Params() - name := params.Name - params.Name = name + "_GENERIC_OVERRIDE" - - testKeyGeneration(t, ¶ms, name) - testSignAndVerify(t, ¶ms, name) - testNonceSafety(t, ¶ms, name) - testINDCCA(t, ¶ms, name) - testNegativeInputs(t, ¶ms, name) + name := curve.Params().Name + t.Run(name, func(t *testing.T) { testKeyGeneration(t, curve) }) + t.Run(name, func(t *testing.T) { testSignAndVerify(t, curve) }) + t.Run(name, func(t *testing.T) { testNonceSafety(t, curve) }) + t.Run(name, func(t *testing.T) { testINDCCA(t, curve) }) + t.Run(name, func(t *testing.T) { testNegativeInputs(t, curve) }) } } diff --git a/libgo/go/crypto/ecdsa/ecdsa_test.go b/libgo/go/crypto/ecdsa/ecdsa_test.go index 0c1ff6d..556818a 100644 --- a/libgo/go/crypto/ecdsa/ecdsa_test.go +++ b/libgo/go/crypto/ecdsa/ecdsa_test.go @@ -21,216 +21,148 @@ import ( "testing" ) -func testKeyGeneration(t *testing.T, c elliptic.Curve, tag string) { - priv, err := GenerateKey(c, rand.Reader) - if err != nil { - t.Errorf("%s: error: %s", tag, err) - return +func testAllCurves(t *testing.T, f func(*testing.T, elliptic.Curve)) { + tests := []struct { + name string + curve elliptic.Curve + }{ + {"P256", elliptic.P256()}, + {"P224", elliptic.P224()}, + {"P384", elliptic.P384()}, + {"P521", elliptic.P521()}, } - if !c.IsOnCurve(priv.PublicKey.X, priv.PublicKey.Y) { - t.Errorf("%s: public key invalid: %s", tag, err) - } -} - -func TestKeyGeneration(t *testing.T) { - testKeyGeneration(t, elliptic.P224(), "p224") if testing.Short() { - return + tests = tests[:1] + } + for _, test := range tests { + curve := test.curve + t.Run(test.name, func(t *testing.T) { + t.Parallel() + f(t, curve) + }) } - testKeyGeneration(t, elliptic.P256(), "p256") - testKeyGeneration(t, elliptic.P384(), "p384") - testKeyGeneration(t, elliptic.P521(), "p521") -} - -func BenchmarkSignP256(b *testing.B) { - b.ResetTimer() - p256 := elliptic.P256() - hashed := []byte("testing") - priv, _ := GenerateKey(p256, rand.Reader) - - b.ReportAllocs() - b.ResetTimer() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - _, _, _ = Sign(rand.Reader, priv, hashed) - } - }) } -func BenchmarkSignP384(b *testing.B) { - b.ResetTimer() - p384 := elliptic.P384() - hashed := []byte("testing") - priv, _ := GenerateKey(p384, rand.Reader) - - b.ReportAllocs() - b.ResetTimer() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - _, _, _ = Sign(rand.Reader, priv, hashed) - } - }) +func TestKeyGeneration(t *testing.T) { + testAllCurves(t, testKeyGeneration) } -func BenchmarkVerifyP256(b *testing.B) { - b.ResetTimer() - p256 := elliptic.P256() - hashed := []byte("testing") - priv, _ := GenerateKey(p256, rand.Reader) - r, s, _ := Sign(rand.Reader, priv, hashed) - - b.ReportAllocs() - b.ResetTimer() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - Verify(&priv.PublicKey, hashed, r, s) - } - }) +func testKeyGeneration(t *testing.T, c elliptic.Curve) { + priv, err := GenerateKey(c, rand.Reader) + if err != nil { + t.Fatal(err) + } + if !c.IsOnCurve(priv.PublicKey.X, priv.PublicKey.Y) { + t.Errorf("public key invalid: %s", err) + } } -func BenchmarkKeyGeneration(b *testing.B) { - b.ResetTimer() - p256 := elliptic.P256() - - b.ReportAllocs() - b.ResetTimer() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - GenerateKey(p256, rand.Reader) - } - }) +func TestSignAndVerify(t *testing.T) { + testAllCurves(t, testSignAndVerify) } -func testSignAndVerify(t *testing.T, c elliptic.Curve, tag string) { +func testSignAndVerify(t *testing.T, c elliptic.Curve) { priv, _ := GenerateKey(c, rand.Reader) hashed := []byte("testing") r, s, err := Sign(rand.Reader, priv, hashed) if err != nil { - t.Errorf("%s: error signing: %s", tag, err) + t.Errorf("error signing: %s", err) return } if !Verify(&priv.PublicKey, hashed, r, s) { - t.Errorf("%s: Verify failed", tag) + t.Errorf("Verify failed") } hashed[0] ^= 0xff if Verify(&priv.PublicKey, hashed, r, s) { - t.Errorf("%s: Verify always works!", tag) + t.Errorf("Verify always works!") } } -func TestSignAndVerify(t *testing.T) { - testSignAndVerify(t, elliptic.P224(), "p224") - if testing.Short() { - return - } - testSignAndVerify(t, elliptic.P256(), "p256") - testSignAndVerify(t, elliptic.P384(), "p384") - testSignAndVerify(t, elliptic.P521(), "p521") +func TestSignAndVerifyASN1(t *testing.T) { + testAllCurves(t, testSignAndVerifyASN1) } -func testSignAndVerifyASN1(t *testing.T, c elliptic.Curve, tag string) { +func testSignAndVerifyASN1(t *testing.T, c elliptic.Curve) { priv, _ := GenerateKey(c, rand.Reader) hashed := []byte("testing") sig, err := SignASN1(rand.Reader, priv, hashed) if err != nil { - t.Errorf("%s: error signing: %s", tag, err) + t.Errorf("error signing: %s", err) return } if !VerifyASN1(&priv.PublicKey, hashed, sig) { - t.Errorf("%s: VerifyASN1 failed", tag) + t.Errorf("VerifyASN1 failed") } hashed[0] ^= 0xff if VerifyASN1(&priv.PublicKey, hashed, sig) { - t.Errorf("%s: VerifyASN1 always works!", tag) + t.Errorf("VerifyASN1 always works!") } } -func TestSignAndVerifyASN1(t *testing.T) { - testSignAndVerifyASN1(t, elliptic.P224(), "p224") - if testing.Short() { - return - } - testSignAndVerifyASN1(t, elliptic.P256(), "p256") - testSignAndVerifyASN1(t, elliptic.P384(), "p384") - testSignAndVerifyASN1(t, elliptic.P521(), "p521") +func TestNonceSafety(t *testing.T) { + testAllCurves(t, testNonceSafety) } -func testNonceSafety(t *testing.T, c elliptic.Curve, tag string) { +func testNonceSafety(t *testing.T, c elliptic.Curve) { priv, _ := GenerateKey(c, rand.Reader) hashed := []byte("testing") r0, s0, err := Sign(zeroReader, priv, hashed) if err != nil { - t.Errorf("%s: error signing: %s", tag, err) + t.Errorf("error signing: %s", err) return } hashed = []byte("testing...") r1, s1, err := Sign(zeroReader, priv, hashed) if err != nil { - t.Errorf("%s: error signing: %s", tag, err) + t.Errorf("error signing: %s", err) return } if s0.Cmp(s1) == 0 { // This should never happen. - t.Errorf("%s: the signatures on two different messages were the same", tag) + t.Errorf("the signatures on two different messages were the same") } if r0.Cmp(r1) == 0 { - t.Errorf("%s: the nonce used for two different messages was the same", tag) + t.Errorf("the nonce used for two different messages was the same") } } -func TestNonceSafety(t *testing.T) { - testNonceSafety(t, elliptic.P224(), "p224") - if testing.Short() { - return - } - testNonceSafety(t, elliptic.P256(), "p256") - testNonceSafety(t, elliptic.P384(), "p384") - testNonceSafety(t, elliptic.P521(), "p521") +func TestINDCCA(t *testing.T) { + testAllCurves(t, testINDCCA) } -func testINDCCA(t *testing.T, c elliptic.Curve, tag string) { +func testINDCCA(t *testing.T, c elliptic.Curve) { priv, _ := GenerateKey(c, rand.Reader) hashed := []byte("testing") r0, s0, err := Sign(rand.Reader, priv, hashed) if err != nil { - t.Errorf("%s: error signing: %s", tag, err) + t.Errorf("error signing: %s", err) return } r1, s1, err := Sign(rand.Reader, priv, hashed) if err != nil { - t.Errorf("%s: error signing: %s", tag, err) + t.Errorf("error signing: %s", err) return } if s0.Cmp(s1) == 0 { - t.Errorf("%s: two signatures of the same message produced the same result", tag) + t.Errorf("two signatures of the same message produced the same result") } if r0.Cmp(r1) == 0 { - t.Errorf("%s: two signatures of the same message produced the same nonce", tag) - } -} - -func TestINDCCA(t *testing.T) { - testINDCCA(t, elliptic.P224(), "p224") - if testing.Short() { - return + t.Errorf("two signatures of the same message produced the same nonce") } - testINDCCA(t, elliptic.P256(), "p256") - testINDCCA(t, elliptic.P384(), "p384") - testINDCCA(t, elliptic.P521(), "p521") } func fromHex(s string) *big.Int { @@ -351,10 +283,14 @@ func TestVectors(t *testing.T) { } } -func testNegativeInputs(t *testing.T, curve elliptic.Curve, tag string) { +func TestNegativeInputs(t *testing.T) { + testAllCurves(t, testNegativeInputs) +} + +func testNegativeInputs(t *testing.T, curve elliptic.Curve) { key, err := GenerateKey(curve, rand.Reader) if err != nil { - t.Errorf("failed to generate key for %q", tag) + t.Errorf("failed to generate key") } var hash [32]byte @@ -363,35 +299,103 @@ func testNegativeInputs(t *testing.T, curve elliptic.Curve, tag string) { r.Neg(r) if Verify(&key.PublicKey, hash[:], r, r) { - t.Errorf("bogus signature accepted for %q", tag) + t.Errorf("bogus signature accepted") } } -func TestNegativeInputs(t *testing.T) { - testNegativeInputs(t, elliptic.P224(), "p224") - testNegativeInputs(t, elliptic.P256(), "p256") - testNegativeInputs(t, elliptic.P384(), "p384") - testNegativeInputs(t, elliptic.P521(), "p521") +func TestZeroHashSignature(t *testing.T) { + testAllCurves(t, testZeroHashSignature) } -func TestZeroHashSignature(t *testing.T) { +func testZeroHashSignature(t *testing.T, curve elliptic.Curve) { zeroHash := make([]byte, 64) - for _, curve := range []elliptic.Curve{elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521()} { - privKey, err := GenerateKey(curve, rand.Reader) + privKey, err := GenerateKey(curve, rand.Reader) + if err != nil { + panic(err) + } + + // Sign a hash consisting of all zeros. + r, s, err := Sign(rand.Reader, privKey, zeroHash) + if err != nil { + panic(err) + } + + // Confirm that it can be verified. + if !Verify(&privKey.PublicKey, zeroHash, r, s) { + t.Errorf("zero hash signature verify failed for %T", curve) + } +} + +func benchmarkAllCurves(t *testing.B, f func(*testing.B, elliptic.Curve)) { + tests := []struct { + name string + curve elliptic.Curve + }{ + {"P256", elliptic.P256()}, + {"P224", elliptic.P224()}, + {"P384", elliptic.P384()}, + {"P521", elliptic.P521()}, + } + for _, test := range tests { + curve := test.curve + t.Run(test.name, func(t *testing.B) { + f(t, curve) + }) + } +} + +func BenchmarkSign(b *testing.B) { + benchmarkAllCurves(b, func(b *testing.B, curve elliptic.Curve) { + priv, err := GenerateKey(curve, rand.Reader) if err != nil { - panic(err) + b.Fatal(err) } + hashed := []byte("testing") + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + sig, err := SignASN1(rand.Reader, priv, hashed) + if err != nil { + b.Fatal(err) + } + // Prevent the compiler from optimizing out the operation. + hashed[0] = sig[0] + } + }) +} - // Sign a hash consisting of all zeros. - r, s, err := Sign(rand.Reader, privKey, zeroHash) +func BenchmarkVerify(b *testing.B) { + benchmarkAllCurves(b, func(b *testing.B, curve elliptic.Curve) { + priv, err := GenerateKey(curve, rand.Reader) + if err != nil { + b.Fatal(err) + } + hashed := []byte("testing") + r, s, err := Sign(rand.Reader, priv, hashed) if err != nil { - panic(err) + b.Fatal(err) } - // Confirm that it can be verified. - if !Verify(&privKey.PublicKey, zeroHash, r, s) { - t.Errorf("zero hash signature verify failed for %T", curve) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + if !Verify(&priv.PublicKey, hashed, r, s) { + b.Fatal("verify failed") + } } - } + }) +} + +func BenchmarkGenerateKey(b *testing.B) { + benchmarkAllCurves(b, func(b *testing.B, curve elliptic.Curve) { + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + if _, err := GenerateKey(curve, rand.Reader); err != nil { + b.Fatal(err) + } + } + }) } diff --git a/libgo/go/crypto/ed25519/ed25519.go b/libgo/go/crypto/ed25519/ed25519.go index 6f59bb5..09c5269 100644 --- a/libgo/go/crypto/ed25519/ed25519.go +++ b/libgo/go/crypto/ed25519/ed25519.go @@ -12,9 +12,6 @@ // 8032 private key as the “seed”. package ed25519 -// This code is a port of the public domain, “ref10” implementation of ed25519 -// from SUPERCOP. - import ( "bytes" "crypto" @@ -128,20 +125,14 @@ func newKeyFromSeed(privateKey, seed []byte) { panic("ed25519: bad seed length: " + strconv.Itoa(l)) } - digest := sha512.Sum512(seed) - digest[0] &= 248 - digest[31] &= 127 - digest[31] |= 64 + h := sha512.Sum512(seed) + s := edwards25519.NewScalar().SetBytesWithClamping(h[:32]) + A := (&edwards25519.Point{}).ScalarBaseMult(s) - var A edwards25519.ExtendedGroupElement - var hBytes [32]byte - copy(hBytes[:], digest[:]) - edwards25519.GeScalarMultBase(&A, &hBytes) - var publicKeyBytes [32]byte - A.ToBytes(&publicKeyBytes) + publicKey := A.Bytes() copy(privateKey, seed) - copy(privateKey[32:], publicKeyBytes[:]) + copy(privateKey[32:], publicKey) } // Sign signs the message with privateKey and returns a signature. It will @@ -158,44 +149,33 @@ func sign(signature, privateKey, message []byte) { if l := len(privateKey); l != PrivateKeySize { panic("ed25519: bad private key length: " + strconv.Itoa(l)) } + seed, publicKey := privateKey[:SeedSize], privateKey[SeedSize:] + + h := sha512.Sum512(seed) + s := edwards25519.NewScalar().SetBytesWithClamping(h[:32]) + prefix := h[32:] + + mh := sha512.New() + mh.Write(prefix) + mh.Write(message) + messageDigest := make([]byte, 0, sha512.Size) + messageDigest = mh.Sum(messageDigest) + r := edwards25519.NewScalar().SetUniformBytes(messageDigest) + + R := (&edwards25519.Point{}).ScalarBaseMult(r) - h := sha512.New() - h.Write(privateKey[:32]) - - var digest1, messageDigest, hramDigest [64]byte - var expandedSecretKey [32]byte - h.Sum(digest1[:0]) - copy(expandedSecretKey[:], digest1[:]) - expandedSecretKey[0] &= 248 - expandedSecretKey[31] &= 63 - expandedSecretKey[31] |= 64 - - h.Reset() - h.Write(digest1[32:]) - h.Write(message) - h.Sum(messageDigest[:0]) - - var messageDigestReduced [32]byte - edwards25519.ScReduce(&messageDigestReduced, &messageDigest) - var R edwards25519.ExtendedGroupElement - edwards25519.GeScalarMultBase(&R, &messageDigestReduced) - - var encodedR [32]byte - R.ToBytes(&encodedR) - - h.Reset() - h.Write(encodedR[:]) - h.Write(privateKey[32:]) - h.Write(message) - h.Sum(hramDigest[:0]) - var hramDigestReduced [32]byte - edwards25519.ScReduce(&hramDigestReduced, &hramDigest) - - var s [32]byte - edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced) - - copy(signature[:], encodedR[:]) - copy(signature[32:], s[:]) + kh := sha512.New() + kh.Write(R.Bytes()) + kh.Write(publicKey) + kh.Write(message) + hramDigest := make([]byte, 0, sha512.Size) + hramDigest = kh.Sum(hramDigest) + k := edwards25519.NewScalar().SetUniformBytes(hramDigest) + + S := edwards25519.NewScalar().MultiplyAdd(k, s, r) + + copy(signature[:32], R.Bytes()) + copy(signature[32:], S.Bytes()) } // Verify reports whether sig is a valid signature of message by publicKey. It @@ -209,38 +189,27 @@ func Verify(publicKey PublicKey, message, sig []byte) bool { return false } - var A edwards25519.ExtendedGroupElement - var publicKeyBytes [32]byte - copy(publicKeyBytes[:], publicKey) - if !A.FromBytes(&publicKeyBytes) { + A, err := (&edwards25519.Point{}).SetBytes(publicKey) + if err != nil { return false } - edwards25519.FeNeg(&A.X, &A.X) - edwards25519.FeNeg(&A.T, &A.T) - - h := sha512.New() - h.Write(sig[:32]) - h.Write(publicKey[:]) - h.Write(message) - var digest [64]byte - h.Sum(digest[:0]) - - var hReduced [32]byte - edwards25519.ScReduce(&hReduced, &digest) - - var R edwards25519.ProjectiveGroupElement - var s [32]byte - copy(s[:], sig[32:]) - - // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in - // the range [0, order) in order to prevent signature malleability. - if !edwards25519.ScMinimal(&s) { + + kh := sha512.New() + kh.Write(sig[:32]) + kh.Write(publicKey) + kh.Write(message) + hramDigest := make([]byte, 0, sha512.Size) + hramDigest = kh.Sum(hramDigest) + k := edwards25519.NewScalar().SetUniformBytes(hramDigest) + + S, err := edwards25519.NewScalar().SetCanonicalBytes(sig[32:]) + if err != nil { return false } - edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s) + // [S]B = R + [k]A --> [k](-A) + [S]B = R + minusA := (&edwards25519.Point{}).Negate(A) + R := (&edwards25519.Point{}).VarTimeDoubleScalarBaseMult(k, minusA, S) - var checkR [32]byte - R.ToBytes(&checkR) - return bytes.Equal(sig[:32], checkR[:]) + return bytes.Equal(sig[:32], R.Bytes()) } diff --git a/libgo/go/crypto/ed25519/ed25519_test.go b/libgo/go/crypto/ed25519/ed25519_test.go index adb09e4..26e1b33 100644 --- a/libgo/go/crypto/ed25519/ed25519_test.go +++ b/libgo/go/crypto/ed25519/ed25519_test.go @@ -9,10 +9,10 @@ import ( "bytes" "compress/gzip" "crypto" - "crypto/ed25519/internal/edwards25519" "crypto/rand" "encoding/hex" "os" + "runtime" "strings" "testing" ) @@ -26,24 +26,6 @@ func (zeroReader) Read(buf []byte) (int, error) { return len(buf), nil } -func TestUnmarshalMarshal(t *testing.T) { - pub, _, _ := GenerateKey(rand.Reader) - - var A edwards25519.ExtendedGroupElement - var pubBytes [32]byte - copy(pubBytes[:], pub) - if !A.FromBytes(&pubBytes) { - t.Fatalf("ExtendedGroupElement.FromBytes failed") - } - - var pub2 [32]byte - A.ToBytes(&pub2) - - if pubBytes != pub2 { - t.Errorf("FromBytes(%v)->ToBytes does not round-trip, got %x\n", pubBytes, pub2) - } -} - func TestSignVerify(t *testing.T) { var zero zeroReader public, private, _ := GenerateKey(zero) @@ -204,6 +186,27 @@ func TestMalleability(t *testing.T) { } } +func TestAllocations(t *testing.T) { + if runtime.Compiler == "gccgo" { + t.Skip("gofronted escape analysis not good enough") + } + if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") { + t.Skip("skipping allocations test without relevant optimizations") + } + if allocs := testing.AllocsPerRun(100, func() { + seed := make([]byte, SeedSize) + message := []byte("Hello, world!") + priv := NewKeyFromSeed(seed) + pub := priv.Public().(PublicKey) + signature := Sign(priv, message) + if !Verify(pub, message, signature) { + t.Fatal("signature didn't verify") + } + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1v", allocs) + } +} + func BenchmarkKeyGeneration(b *testing.B) { var zero zeroReader for i := 0; i < b.N; i++ { @@ -215,7 +218,6 @@ func BenchmarkKeyGeneration(b *testing.B) { func BenchmarkNewKeyFromSeed(b *testing.B) { seed := make([]byte, SeedSize) - b.ReportAllocs() for i := 0; i < b.N; i++ { _ = NewKeyFromSeed(seed) } @@ -228,7 +230,6 @@ func BenchmarkSigning(b *testing.B) { b.Fatal(err) } message := []byte("Hello, world!") - b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { Sign(priv, message) diff --git a/libgo/go/crypto/ed25519/ed25519vectors_test.go b/libgo/go/crypto/ed25519/ed25519vectors_test.go new file mode 100644 index 0000000..74fcdcd --- /dev/null +++ b/libgo/go/crypto/ed25519/ed25519vectors_test.go @@ -0,0 +1,109 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ed25519_test + +import ( + "crypto/ed25519" + "encoding/hex" + "encoding/json" + "internal/testenv" + "os" + "os/exec" + "path/filepath" + "testing" +) + +// TestEd25519Vectors runs a very large set of test vectors that exercise all +// combinations of low-order points, low-order components, and non-canonical +// encodings. These vectors lock in unspecified and spec-divergent behaviors in +// edge cases that are not security relevant in most contexts, but that can +// cause issues in consensus applications if changed. +// +// Our behavior matches the "classic" unwritten verification rules of the +// "ref10" reference implementation. +// +// Note that although we test for these edge cases, they are not covered by the +// Go 1 Compatibility Promise. Applications that need stable verification rules +// should use github.com/hdevalence/ed25519consensus. +// +// See https://hdevalence.ca/blog/2020-10-04-its-25519am for more details. +func TestEd25519Vectors(t *testing.T) { + jsonVectors := downloadEd25519Vectors(t) + var vectors []struct { + A, R, S, M string + Flags []string + } + if err := json.Unmarshal(jsonVectors, &vectors); err != nil { + t.Fatal(err) + } + for i, v := range vectors { + expectedToVerify := true + for _, f := range v.Flags { + switch f { + // We use the simplified verification formula that doesn't multiply + // by the cofactor, so any low order residue will cause the + // signature not to verify. + // + // This is allowed, but not required, by RFC 8032. + case "LowOrderResidue": + expectedToVerify = false + // Our point decoding allows non-canonical encodings (in violation + // of RFC 8032) but R is not decoded: instead, R is recomputed and + // compared bytewise against the canonical encoding. + case "NonCanonicalR": + expectedToVerify = false + } + } + + publicKey := decodeHex(t, v.A) + signature := append(decodeHex(t, v.R), decodeHex(t, v.S)...) + message := []byte(v.M) + + didVerify := ed25519.Verify(publicKey, message, signature) + if didVerify && !expectedToVerify { + t.Errorf("#%d: vector with flags %s unexpectedly verified", i, v.Flags) + } + if !didVerify && expectedToVerify { + t.Errorf("#%d: vector with flags %s unexpectedly rejected", i, v.Flags) + } + } +} + +func downloadEd25519Vectors(t *testing.T) []byte { + testenv.MustHaveExternalNetwork(t) + + // Download the JSON test file from the GOPROXY with `go mod download`, + // pinning the version so test and module caching works as expected. + goTool := testenv.GoToolPath(t) + path := "filippo.io/mostly-harmless/ed25519vectors@v0.0.0-20210322192420-30a2d7243a94" + cmd := exec.Command(goTool, "mod", "download", "-json", path) + // TODO: enable the sumdb once the TryBots proxy supports it. + cmd.Env = append(os.Environ(), "GONOSUMDB=*") + output, err := cmd.Output() + if err != nil { + t.Fatalf("failed to run `go mod download -json %s`, output: %s", path, output) + } + var dm struct { + Dir string // absolute path to cached source root directory + } + if err := json.Unmarshal(output, &dm); err != nil { + t.Fatal(err) + } + + jsonVectors, err := os.ReadFile(filepath.Join(dm.Dir, "ed25519vectors.json")) + if err != nil { + t.Fatalf("failed to read ed25519vectors.json: %v", err) + } + return jsonVectors +} + +func decodeHex(t *testing.T, s string) []byte { + t.Helper() + b, err := hex.DecodeString(s) + if err != nil { + t.Errorf("invalid hex: %v", err) + } + return b +} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/const.go b/libgo/go/crypto/ed25519/internal/edwards25519/const.go deleted file mode 100644 index e39f086..0000000 --- a/libgo/go/crypto/ed25519/internal/edwards25519/const.go +++ /dev/null @@ -1,1422 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package edwards25519 - -// These values are from the public domain, “ref10” implementation of ed25519 -// from SUPERCOP. - -// d is a constant in the Edwards curve equation. -var d = FieldElement{ - -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116, -} - -// d2 is 2*d. -var d2 = FieldElement{ - -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199, -} - -// SqrtM1 is the square-root of -1 in the field. -var SqrtM1 = FieldElement{ - -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482, -} - -// A is a constant in the Montgomery-form of curve25519. -var A = FieldElement{ - 486662, 0, 0, 0, 0, 0, 0, 0, 0, 0, -} - -// bi contains precomputed multiples of the base-point. See the Ed25519 paper -// for a discussion about how these values are used. -var bi = [8]PreComputedGroupElement{ - { - FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605}, - FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378}, - FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}, - }, - { - FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024}, - FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574}, - FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}, - }, - { - FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380}, - FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306}, - FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}, - }, - { - FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766}, - FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701}, - FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}, - }, - { - FieldElement{-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877}, - FieldElement{-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951}, - FieldElement{4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784}, - }, - { - FieldElement{-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436}, - FieldElement{25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918}, - FieldElement{23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877}, - }, - { - FieldElement{-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800}, - FieldElement{-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305}, - FieldElement{-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300}, - }, - { - FieldElement{-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876}, - FieldElement{-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619}, - FieldElement{-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683}, - }, -} - -// base contains precomputed multiples of the base-point. See the Ed25519 paper -// for a discussion about how these values are used. -var base = [32][8]PreComputedGroupElement{ - { - { - FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605}, - FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378}, - FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}, - }, - { - FieldElement{-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303}, - FieldElement{-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081}, - FieldElement{26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697}, - }, - { - FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024}, - FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574}, - FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}, - }, - { - FieldElement{-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540}, - FieldElement{23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397}, - FieldElement{7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325}, - }, - { - FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380}, - FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306}, - FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}, - }, - { - FieldElement{-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777}, - FieldElement{-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737}, - FieldElement{-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652}, - }, - { - FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766}, - FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701}, - FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}, - }, - { - FieldElement{14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726}, - FieldElement{-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955}, - FieldElement{27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425}, - }, - }, - { - { - FieldElement{-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171}, - FieldElement{27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510}, - FieldElement{17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660}, - }, - { - FieldElement{-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639}, - FieldElement{29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963}, - FieldElement{5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950}, - }, - { - FieldElement{-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568}, - FieldElement{12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335}, - FieldElement{25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628}, - }, - { - FieldElement{-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007}, - FieldElement{-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772}, - FieldElement{-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653}, - }, - { - FieldElement{2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567}, - FieldElement{13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686}, - FieldElement{21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372}, - }, - { - FieldElement{-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887}, - FieldElement{-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954}, - FieldElement{-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953}, - }, - { - FieldElement{24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833}, - FieldElement{-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532}, - FieldElement{-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876}, - }, - { - FieldElement{2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268}, - FieldElement{33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214}, - FieldElement{1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038}, - }, - }, - { - { - FieldElement{6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800}, - FieldElement{4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645}, - FieldElement{-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664}, - }, - { - FieldElement{1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933}, - FieldElement{-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182}, - FieldElement{-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222}, - }, - { - FieldElement{-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991}, - FieldElement{20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880}, - FieldElement{9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092}, - }, - { - FieldElement{-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295}, - FieldElement{19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788}, - FieldElement{8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553}, - }, - { - FieldElement{-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026}, - FieldElement{11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347}, - FieldElement{-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033}, - }, - { - FieldElement{-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395}, - FieldElement{-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278}, - FieldElement{1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890}, - }, - { - FieldElement{32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995}, - FieldElement{-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596}, - FieldElement{-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891}, - }, - { - FieldElement{31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060}, - FieldElement{11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608}, - FieldElement{-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606}, - }, - }, - { - { - FieldElement{7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389}, - FieldElement{-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016}, - FieldElement{-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341}, - }, - { - FieldElement{-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505}, - FieldElement{14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553}, - FieldElement{-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655}, - }, - { - FieldElement{15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220}, - FieldElement{12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631}, - FieldElement{-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099}, - }, - { - FieldElement{26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556}, - FieldElement{14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749}, - FieldElement{236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930}, - }, - { - FieldElement{1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391}, - FieldElement{5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253}, - FieldElement{20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066}, - }, - { - FieldElement{24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958}, - FieldElement{-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082}, - FieldElement{-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383}, - }, - { - FieldElement{-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521}, - FieldElement{-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807}, - FieldElement{23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948}, - }, - { - FieldElement{9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134}, - FieldElement{-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455}, - FieldElement{27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629}, - }, - }, - { - { - FieldElement{-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069}, - FieldElement{-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746}, - FieldElement{24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919}, - }, - { - FieldElement{11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837}, - FieldElement{8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906}, - FieldElement{-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771}, - }, - { - FieldElement{-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817}, - FieldElement{10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098}, - FieldElement{10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409}, - }, - { - FieldElement{-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504}, - FieldElement{-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727}, - FieldElement{28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420}, - }, - { - FieldElement{-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003}, - FieldElement{-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605}, - FieldElement{-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384}, - }, - { - FieldElement{-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701}, - FieldElement{-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683}, - FieldElement{29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708}, - }, - { - FieldElement{-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563}, - FieldElement{-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260}, - FieldElement{-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387}, - }, - { - FieldElement{-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672}, - FieldElement{23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686}, - FieldElement{-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665}, - }, - }, - { - { - FieldElement{11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182}, - FieldElement{-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277}, - FieldElement{14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628}, - }, - { - FieldElement{-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474}, - FieldElement{-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539}, - FieldElement{-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822}, - }, - { - FieldElement{-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970}, - FieldElement{19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756}, - FieldElement{-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508}, - }, - { - FieldElement{-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683}, - FieldElement{-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655}, - FieldElement{-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158}, - }, - { - FieldElement{-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125}, - FieldElement{-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839}, - FieldElement{-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664}, - }, - { - FieldElement{27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294}, - FieldElement{-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899}, - FieldElement{-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070}, - }, - { - FieldElement{3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294}, - FieldElement{-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949}, - FieldElement{-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083}, - }, - { - FieldElement{31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420}, - FieldElement{-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940}, - FieldElement{29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396}, - }, - }, - { - { - FieldElement{-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567}, - FieldElement{20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127}, - FieldElement{-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294}, - }, - { - FieldElement{-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887}, - FieldElement{22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964}, - FieldElement{16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195}, - }, - { - FieldElement{9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244}, - FieldElement{24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999}, - FieldElement{-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762}, - }, - { - FieldElement{-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274}, - FieldElement{-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236}, - FieldElement{-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605}, - }, - { - FieldElement{-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761}, - FieldElement{-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884}, - FieldElement{-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482}, - }, - { - FieldElement{-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638}, - FieldElement{-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490}, - FieldElement{-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170}, - }, - { - FieldElement{5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736}, - FieldElement{10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124}, - FieldElement{-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392}, - }, - { - FieldElement{8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029}, - FieldElement{6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048}, - FieldElement{28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958}, - }, - }, - { - { - FieldElement{24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593}, - FieldElement{26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071}, - FieldElement{-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692}, - }, - { - FieldElement{11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687}, - FieldElement{-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441}, - FieldElement{-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001}, - }, - { - FieldElement{-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460}, - FieldElement{-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007}, - FieldElement{-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762}, - }, - { - FieldElement{15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005}, - FieldElement{-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674}, - FieldElement{4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035}, - }, - { - FieldElement{7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590}, - FieldElement{-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957}, - FieldElement{-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812}, - }, - { - FieldElement{33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740}, - FieldElement{-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122}, - FieldElement{-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158}, - }, - { - FieldElement{8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885}, - FieldElement{26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140}, - FieldElement{19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857}, - }, - { - FieldElement{801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155}, - FieldElement{19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260}, - FieldElement{19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483}, - }, - }, - { - { - FieldElement{-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677}, - FieldElement{32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815}, - FieldElement{22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751}, - }, - { - FieldElement{-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203}, - FieldElement{-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208}, - FieldElement{1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230}, - }, - { - FieldElement{16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850}, - FieldElement{-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389}, - FieldElement{-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968}, - }, - { - FieldElement{-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689}, - FieldElement{14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880}, - FieldElement{5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304}, - }, - { - FieldElement{30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632}, - FieldElement{-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412}, - FieldElement{20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566}, - }, - { - FieldElement{-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038}, - FieldElement{-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232}, - FieldElement{-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943}, - }, - { - FieldElement{17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856}, - FieldElement{23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738}, - FieldElement{15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971}, - }, - { - FieldElement{-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718}, - FieldElement{-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697}, - FieldElement{-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883}, - }, - }, - { - { - FieldElement{5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912}, - FieldElement{-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358}, - FieldElement{3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849}, - }, - { - FieldElement{29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307}, - FieldElement{-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977}, - FieldElement{-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335}, - }, - { - FieldElement{-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644}, - FieldElement{-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616}, - FieldElement{-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735}, - }, - { - FieldElement{-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099}, - FieldElement{29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341}, - FieldElement{-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336}, - }, - { - FieldElement{-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646}, - FieldElement{31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425}, - FieldElement{-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388}, - }, - { - FieldElement{-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743}, - FieldElement{-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822}, - FieldElement{-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462}, - }, - { - FieldElement{18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985}, - FieldElement{9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702}, - FieldElement{-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797}, - }, - { - FieldElement{21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293}, - FieldElement{27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100}, - FieldElement{19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688}, - }, - }, - { - { - FieldElement{12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186}, - FieldElement{2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610}, - FieldElement{-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707}, - }, - { - FieldElement{7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220}, - FieldElement{915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025}, - FieldElement{32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044}, - }, - { - FieldElement{32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992}, - FieldElement{-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027}, - FieldElement{21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197}, - }, - { - FieldElement{8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901}, - FieldElement{31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952}, - FieldElement{19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878}, - }, - { - FieldElement{-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390}, - FieldElement{32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730}, - FieldElement{2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730}, - }, - { - FieldElement{-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180}, - FieldElement{-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272}, - FieldElement{-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715}, - }, - { - FieldElement{-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970}, - FieldElement{-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772}, - FieldElement{-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865}, - }, - { - FieldElement{15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750}, - FieldElement{20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373}, - FieldElement{32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348}, - }, - }, - { - { - FieldElement{9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144}, - FieldElement{-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195}, - FieldElement{5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086}, - }, - { - FieldElement{-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684}, - FieldElement{-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518}, - FieldElement{-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233}, - }, - { - FieldElement{-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793}, - FieldElement{-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794}, - FieldElement{580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435}, - }, - { - FieldElement{23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921}, - FieldElement{13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518}, - FieldElement{2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563}, - }, - { - FieldElement{14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278}, - FieldElement{-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024}, - FieldElement{4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030}, - }, - { - FieldElement{10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783}, - FieldElement{27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717}, - FieldElement{6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844}, - }, - { - FieldElement{14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333}, - FieldElement{16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048}, - FieldElement{22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760}, - }, - { - FieldElement{-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760}, - FieldElement{-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757}, - FieldElement{-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112}, - }, - }, - { - { - FieldElement{-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468}, - FieldElement{3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184}, - FieldElement{10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289}, - }, - { - FieldElement{15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066}, - FieldElement{24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882}, - FieldElement{13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226}, - }, - { - FieldElement{16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101}, - FieldElement{29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279}, - FieldElement{-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811}, - }, - { - FieldElement{27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709}, - FieldElement{20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714}, - FieldElement{-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121}, - }, - { - FieldElement{9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464}, - FieldElement{12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847}, - FieldElement{13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400}, - }, - { - FieldElement{4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414}, - FieldElement{-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158}, - FieldElement{17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045}, - }, - { - FieldElement{-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415}, - FieldElement{-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459}, - FieldElement{-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079}, - }, - { - FieldElement{21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412}, - FieldElement{-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743}, - FieldElement{-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836}, - }, - }, - { - { - FieldElement{12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022}, - FieldElement{18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429}, - FieldElement{-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065}, - }, - { - FieldElement{30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861}, - FieldElement{10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000}, - FieldElement{-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101}, - }, - { - FieldElement{32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815}, - FieldElement{29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642}, - FieldElement{10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966}, - }, - { - FieldElement{25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574}, - FieldElement{-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742}, - FieldElement{-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689}, - }, - { - FieldElement{12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020}, - FieldElement{-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772}, - FieldElement{3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982}, - }, - { - FieldElement{-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953}, - FieldElement{-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218}, - FieldElement{-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265}, - }, - { - FieldElement{29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073}, - FieldElement{-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325}, - FieldElement{-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798}, - }, - { - FieldElement{-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870}, - FieldElement{-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863}, - FieldElement{-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927}, - }, - }, - { - { - FieldElement{-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267}, - FieldElement{-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663}, - FieldElement{22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862}, - }, - { - FieldElement{-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673}, - FieldElement{15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943}, - FieldElement{15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020}, - }, - { - FieldElement{-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238}, - FieldElement{11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064}, - FieldElement{14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795}, - }, - { - FieldElement{15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052}, - FieldElement{-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904}, - FieldElement{29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531}, - }, - { - FieldElement{-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979}, - FieldElement{-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841}, - FieldElement{10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431}, - }, - { - FieldElement{10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324}, - FieldElement{-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940}, - FieldElement{10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320}, - }, - { - FieldElement{-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184}, - FieldElement{14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114}, - FieldElement{30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878}, - }, - { - FieldElement{12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784}, - FieldElement{-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091}, - FieldElement{-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585}, - }, - }, - { - { - FieldElement{-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208}, - FieldElement{10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864}, - FieldElement{17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661}, - }, - { - FieldElement{7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233}, - FieldElement{26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212}, - FieldElement{-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525}, - }, - { - FieldElement{-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068}, - FieldElement{9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397}, - FieldElement{-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988}, - }, - { - FieldElement{5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889}, - FieldElement{32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038}, - FieldElement{14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697}, - }, - { - FieldElement{20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875}, - FieldElement{-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905}, - FieldElement{-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656}, - }, - { - FieldElement{11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818}, - FieldElement{27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714}, - FieldElement{10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203}, - }, - { - FieldElement{20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931}, - FieldElement{-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024}, - FieldElement{-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084}, - }, - { - FieldElement{-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204}, - FieldElement{20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817}, - FieldElement{27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667}, - }, - }, - { - { - FieldElement{11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504}, - FieldElement{-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768}, - FieldElement{-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255}, - }, - { - FieldElement{6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790}, - FieldElement{1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438}, - FieldElement{-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333}, - }, - { - FieldElement{17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971}, - FieldElement{31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905}, - FieldElement{29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409}, - }, - { - FieldElement{12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409}, - FieldElement{6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499}, - FieldElement{-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363}, - }, - { - FieldElement{28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664}, - FieldElement{-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324}, - FieldElement{-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940}, - }, - { - FieldElement{13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990}, - FieldElement{-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914}, - FieldElement{-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290}, - }, - { - FieldElement{24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257}, - FieldElement{-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433}, - FieldElement{-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236}, - }, - { - FieldElement{-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045}, - FieldElement{11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093}, - FieldElement{-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347}, - }, - }, - { - { - FieldElement{-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191}, - FieldElement{-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507}, - FieldElement{-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906}, - }, - { - FieldElement{3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018}, - FieldElement{-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109}, - FieldElement{-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926}, - }, - { - FieldElement{-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528}, - FieldElement{8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625}, - FieldElement{-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286}, - }, - { - FieldElement{2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033}, - FieldElement{27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866}, - FieldElement{21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896}, - }, - { - FieldElement{30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075}, - FieldElement{26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347}, - FieldElement{-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437}, - }, - { - FieldElement{-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165}, - FieldElement{-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588}, - FieldElement{-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193}, - }, - { - FieldElement{-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017}, - FieldElement{-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883}, - FieldElement{21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961}, - }, - { - FieldElement{8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043}, - FieldElement{29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663}, - FieldElement{-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362}, - }, - }, - { - { - FieldElement{-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860}, - FieldElement{2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466}, - FieldElement{-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063}, - }, - { - FieldElement{-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997}, - FieldElement{-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295}, - FieldElement{-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369}, - }, - { - FieldElement{9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385}, - FieldElement{18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109}, - FieldElement{2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906}, - }, - { - FieldElement{4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424}, - FieldElement{-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185}, - FieldElement{7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962}, - }, - { - FieldElement{-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325}, - FieldElement{10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593}, - FieldElement{696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404}, - }, - { - FieldElement{-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644}, - FieldElement{17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801}, - FieldElement{26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804}, - }, - { - FieldElement{-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884}, - FieldElement{-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577}, - FieldElement{-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849}, - }, - { - FieldElement{32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473}, - FieldElement{-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644}, - FieldElement{-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319}, - }, - }, - { - { - FieldElement{-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599}, - FieldElement{-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768}, - FieldElement{-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084}, - }, - { - FieldElement{-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328}, - FieldElement{-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369}, - FieldElement{20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920}, - }, - { - FieldElement{12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815}, - FieldElement{-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025}, - FieldElement{-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397}, - }, - { - FieldElement{-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448}, - FieldElement{6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981}, - FieldElement{30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165}, - }, - { - FieldElement{32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501}, - FieldElement{17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073}, - FieldElement{-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861}, - }, - { - FieldElement{14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845}, - FieldElement{-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211}, - FieldElement{18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870}, - }, - { - FieldElement{10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096}, - FieldElement{33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803}, - FieldElement{-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168}, - }, - { - FieldElement{30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965}, - FieldElement{-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505}, - FieldElement{18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598}, - }, - }, - { - { - FieldElement{5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782}, - FieldElement{5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900}, - FieldElement{-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479}, - }, - { - FieldElement{-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208}, - FieldElement{8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232}, - FieldElement{17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719}, - }, - { - FieldElement{16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271}, - FieldElement{-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326}, - FieldElement{-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132}, - }, - { - FieldElement{14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300}, - FieldElement{8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570}, - FieldElement{15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670}, - }, - { - FieldElement{-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994}, - FieldElement{-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913}, - FieldElement{31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317}, - }, - { - FieldElement{-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730}, - FieldElement{842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096}, - FieldElement{-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078}, - }, - { - FieldElement{-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411}, - FieldElement{-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905}, - FieldElement{-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654}, - }, - { - FieldElement{-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870}, - FieldElement{-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498}, - FieldElement{12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579}, - }, - }, - { - { - FieldElement{14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677}, - FieldElement{10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647}, - FieldElement{-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743}, - }, - { - FieldElement{-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468}, - FieldElement{21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375}, - FieldElement{-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155}, - }, - { - FieldElement{6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725}, - FieldElement{-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612}, - FieldElement{-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943}, - }, - { - FieldElement{-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944}, - FieldElement{30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928}, - FieldElement{9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406}, - }, - { - FieldElement{22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139}, - FieldElement{-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963}, - FieldElement{-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693}, - }, - { - FieldElement{1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734}, - FieldElement{-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680}, - FieldElement{-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410}, - }, - { - FieldElement{-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931}, - FieldElement{-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654}, - FieldElement{22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710}, - }, - { - FieldElement{29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180}, - FieldElement{-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684}, - FieldElement{-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895}, - }, - }, - { - { - FieldElement{22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501}, - FieldElement{-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413}, - FieldElement{6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880}, - }, - { - FieldElement{-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874}, - FieldElement{22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962}, - FieldElement{-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899}, - }, - { - FieldElement{21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152}, - FieldElement{9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063}, - FieldElement{7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080}, - }, - { - FieldElement{-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146}, - FieldElement{-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183}, - FieldElement{-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133}, - }, - { - FieldElement{-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421}, - FieldElement{-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622}, - FieldElement{-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197}, - }, - { - FieldElement{2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663}, - FieldElement{31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753}, - FieldElement{4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755}, - }, - { - FieldElement{-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862}, - FieldElement{-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118}, - FieldElement{26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171}, - }, - { - FieldElement{15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380}, - FieldElement{16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824}, - FieldElement{28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270}, - }, - }, - { - { - FieldElement{-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438}, - FieldElement{-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584}, - FieldElement{-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562}, - }, - { - FieldElement{30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471}, - FieldElement{18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610}, - FieldElement{19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269}, - }, - { - FieldElement{-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650}, - FieldElement{14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369}, - FieldElement{19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461}, - }, - { - FieldElement{30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462}, - FieldElement{-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793}, - FieldElement{-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218}, - }, - { - FieldElement{-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226}, - FieldElement{18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019}, - FieldElement{-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037}, - }, - { - FieldElement{31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171}, - FieldElement{-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132}, - FieldElement{-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841}, - }, - { - FieldElement{21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181}, - FieldElement{-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210}, - FieldElement{-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040}, - }, - { - FieldElement{3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935}, - FieldElement{24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105}, - FieldElement{-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814}, - }, - }, - { - { - FieldElement{793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852}, - FieldElement{5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581}, - FieldElement{-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646}, - }, - { - FieldElement{10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844}, - FieldElement{10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025}, - FieldElement{27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453}, - }, - { - FieldElement{-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068}, - FieldElement{4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192}, - FieldElement{-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921}, - }, - { - FieldElement{-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259}, - FieldElement{-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426}, - FieldElement{-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072}, - }, - { - FieldElement{-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305}, - FieldElement{13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832}, - FieldElement{28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943}, - }, - { - FieldElement{-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011}, - FieldElement{24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447}, - FieldElement{17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494}, - }, - { - FieldElement{-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245}, - FieldElement{-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859}, - FieldElement{28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915}, - }, - { - FieldElement{16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707}, - FieldElement{10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848}, - FieldElement{-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224}, - }, - }, - { - { - FieldElement{-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391}, - FieldElement{15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215}, - FieldElement{-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101}, - }, - { - FieldElement{23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713}, - FieldElement{21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849}, - FieldElement{-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930}, - }, - { - FieldElement{-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940}, - FieldElement{-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031}, - FieldElement{-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404}, - }, - { - FieldElement{-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243}, - FieldElement{-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116}, - FieldElement{-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525}, - }, - { - FieldElement{-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509}, - FieldElement{-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883}, - FieldElement{15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865}, - }, - { - FieldElement{-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660}, - FieldElement{4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273}, - FieldElement{-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138}, - }, - { - FieldElement{-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560}, - FieldElement{-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135}, - FieldElement{2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941}, - }, - { - FieldElement{-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739}, - FieldElement{18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756}, - FieldElement{-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819}, - }, - }, - { - { - FieldElement{-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347}, - FieldElement{-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028}, - FieldElement{21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075}, - }, - { - FieldElement{16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799}, - FieldElement{-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609}, - FieldElement{-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817}, - }, - { - FieldElement{-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989}, - FieldElement{-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523}, - FieldElement{4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278}, - }, - { - FieldElement{31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045}, - FieldElement{19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377}, - FieldElement{24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480}, - }, - { - FieldElement{17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016}, - FieldElement{510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426}, - FieldElement{18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525}, - }, - { - FieldElement{13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396}, - FieldElement{9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080}, - FieldElement{12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892}, - }, - { - FieldElement{15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275}, - FieldElement{11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074}, - FieldElement{20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140}, - }, - { - FieldElement{-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717}, - FieldElement{-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101}, - FieldElement{24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127}, - }, - }, - { - { - FieldElement{-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632}, - FieldElement{-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415}, - FieldElement{-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160}, - }, - { - FieldElement{31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876}, - FieldElement{22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625}, - FieldElement{-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478}, - }, - { - FieldElement{27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164}, - FieldElement{26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595}, - FieldElement{-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248}, - }, - { - FieldElement{-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858}, - FieldElement{15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193}, - FieldElement{8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184}, - }, - { - FieldElement{-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942}, - FieldElement{-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635}, - FieldElement{21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948}, - }, - { - FieldElement{11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935}, - FieldElement{-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415}, - FieldElement{-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416}, - }, - { - FieldElement{-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018}, - FieldElement{4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778}, - FieldElement{366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659}, - }, - { - FieldElement{-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385}, - FieldElement{18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503}, - FieldElement{476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329}, - }, - }, - { - { - FieldElement{20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056}, - FieldElement{-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838}, - FieldElement{24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948}, - }, - { - FieldElement{-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691}, - FieldElement{-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118}, - FieldElement{-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517}, - }, - { - FieldElement{-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269}, - FieldElement{-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904}, - FieldElement{-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589}, - }, - { - FieldElement{-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193}, - FieldElement{-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910}, - FieldElement{-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930}, - }, - { - FieldElement{-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667}, - FieldElement{25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481}, - FieldElement{-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876}, - }, - { - FieldElement{22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640}, - FieldElement{-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278}, - FieldElement{-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112}, - }, - { - FieldElement{26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272}, - FieldElement{17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012}, - FieldElement{-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221}, - }, - { - FieldElement{30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046}, - FieldElement{13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345}, - FieldElement{-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310}, - }, - }, - { - { - FieldElement{19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937}, - FieldElement{31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636}, - FieldElement{-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008}, - }, - { - FieldElement{-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429}, - FieldElement{-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576}, - FieldElement{31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066}, - }, - { - FieldElement{-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490}, - FieldElement{-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104}, - FieldElement{33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053}, - }, - { - FieldElement{31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275}, - FieldElement{-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511}, - FieldElement{22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095}, - }, - { - FieldElement{-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439}, - FieldElement{23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939}, - FieldElement{-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424}, - }, - { - FieldElement{2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310}, - FieldElement{3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608}, - FieldElement{-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079}, - }, - { - FieldElement{-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101}, - FieldElement{21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418}, - FieldElement{18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576}, - }, - { - FieldElement{30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356}, - FieldElement{9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996}, - FieldElement{-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099}, - }, - }, - { - { - FieldElement{-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728}, - FieldElement{-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658}, - FieldElement{-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242}, - }, - { - FieldElement{-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001}, - FieldElement{-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766}, - FieldElement{18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373}, - }, - { - FieldElement{26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458}, - FieldElement{-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628}, - FieldElement{-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657}, - }, - { - FieldElement{-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062}, - FieldElement{25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616}, - FieldElement{31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014}, - }, - { - FieldElement{24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383}, - FieldElement{-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814}, - FieldElement{-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718}, - }, - { - FieldElement{30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417}, - FieldElement{2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222}, - FieldElement{33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444}, - }, - { - FieldElement{-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597}, - FieldElement{23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970}, - FieldElement{1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799}, - }, - { - FieldElement{-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647}, - FieldElement{13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511}, - FieldElement{-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032}, - }, - }, - { - { - FieldElement{9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834}, - FieldElement{-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461}, - FieldElement{29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062}, - }, - { - FieldElement{-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516}, - FieldElement{-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547}, - FieldElement{-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240}, - }, - { - FieldElement{-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038}, - FieldElement{-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741}, - FieldElement{16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103}, - }, - { - FieldElement{-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747}, - FieldElement{-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323}, - FieldElement{31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016}, - }, - { - FieldElement{-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373}, - FieldElement{15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228}, - FieldElement{-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141}, - }, - { - FieldElement{16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399}, - FieldElement{11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831}, - FieldElement{-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376}, - }, - { - FieldElement{-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313}, - FieldElement{-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958}, - FieldElement{-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577}, - }, - { - FieldElement{-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743}, - FieldElement{29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684}, - FieldElement{-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476}, - }, - }, -} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/doc.go b/libgo/go/crypto/ed25519/internal/edwards25519/doc.go new file mode 100644 index 0000000..ff31cd2 --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/doc.go @@ -0,0 +1,22 @@ +// Copyright (c) 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package edwards25519 implements group logic for the twisted Edwards curve +// +// -x^2 + y^2 = 1 + -(121665/121666)*x^2*y^2 +// +// This is better known as the Edwards curve equivalent to Curve25519, and is +// the curve used by the Ed25519 signature scheme. +// +// Most users don't need this package, and should instead use crypto/ed25519 for +// signatures, golang.org/x/crypto/curve25519 for Diffie-Hellman, or +// github.com/gtank/ristretto255 for prime order group logic. +// +// However, developers who do need to interact with low-level edwards25519 +// operations can use filippo.io/edwards25519, an extended version of this +// package repackaged as an importable module. +// +// (Note that filippo.io/edwards25519 and github.com/gtank/ristretto255 are not +// maintained by the Go team and are not covered by the Go 1 Compatibility Promise.) +package edwards25519 diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/edwards25519.go b/libgo/go/crypto/ed25519/internal/edwards25519/edwards25519.go index b091481..313e6c2 100644 --- a/libgo/go/crypto/ed25519/internal/edwards25519/edwards25519.go +++ b/libgo/go/crypto/ed25519/internal/edwards25519/edwards25519.go @@ -1,1793 +1,427 @@ -// Copyright 2016 The Go Authors. All rights reserved. +// Copyright (c) 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package edwards25519 -import "encoding/binary" +import ( + "crypto/ed25519/internal/edwards25519/field" + "errors" +) -// This code is a port of the public domain, “ref10” implementation of ed25519 -// from SUPERCOP. +// Point types. -// FieldElement represents an element of the field GF(2^255 - 19). An element -// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 -// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on -// context. -type FieldElement [10]int32 - -var zero FieldElement - -func FeZero(fe *FieldElement) { - copy(fe[:], zero[:]) +type projP1xP1 struct { + X, Y, Z, T field.Element } -func FeOne(fe *FieldElement) { - FeZero(fe) - fe[0] = 1 +type projP2 struct { + X, Y, Z field.Element } -func FeAdd(dst, a, b *FieldElement) { - dst[0] = a[0] + b[0] - dst[1] = a[1] + b[1] - dst[2] = a[2] + b[2] - dst[3] = a[3] + b[3] - dst[4] = a[4] + b[4] - dst[5] = a[5] + b[5] - dst[6] = a[6] + b[6] - dst[7] = a[7] + b[7] - dst[8] = a[8] + b[8] - dst[9] = a[9] + b[9] -} +// Point represents a point on the edwards25519 curve. +// +// This type works similarly to math/big.Int, and all arguments and receivers +// are allowed to alias. +// +// The zero value is NOT valid, and it may be used only as a receiver. +type Point struct { + // The point is internally represented in extended coordinates (X, Y, Z, T) + // where x = X/Z, y = Y/Z, and xy = T/Z per https://eprint.iacr.org/2008/522. + x, y, z, t field.Element -func FeSub(dst, a, b *FieldElement) { - dst[0] = a[0] - b[0] - dst[1] = a[1] - b[1] - dst[2] = a[2] - b[2] - dst[3] = a[3] - b[3] - dst[4] = a[4] - b[4] - dst[5] = a[5] - b[5] - dst[6] = a[6] - b[6] - dst[7] = a[7] - b[7] - dst[8] = a[8] - b[8] - dst[9] = a[9] - b[9] + // Make the type not comparable (i.e. used with == or as a map key), as + // equivalent points can be represented by different Go values. + _ incomparable } -func FeCopy(dst, src *FieldElement) { - copy(dst[:], src[:]) -} +type incomparable [0]func() -// Replace (f,g) with (g,g) if b == 1; -// replace (f,g) with (f,g) if b == 0. -// -// Preconditions: b in {0,1}. -func FeCMove(f, g *FieldElement, b int32) { - b = -b - f[0] ^= b & (f[0] ^ g[0]) - f[1] ^= b & (f[1] ^ g[1]) - f[2] ^= b & (f[2] ^ g[2]) - f[3] ^= b & (f[3] ^ g[3]) - f[4] ^= b & (f[4] ^ g[4]) - f[5] ^= b & (f[5] ^ g[5]) - f[6] ^= b & (f[6] ^ g[6]) - f[7] ^= b & (f[7] ^ g[7]) - f[8] ^= b & (f[8] ^ g[8]) - f[9] ^= b & (f[9] ^ g[9]) +func checkInitialized(points ...*Point) { + for _, p := range points { + if p.x == (field.Element{}) && p.y == (field.Element{}) { + panic("edwards25519: use of uninitialized Point") + } + } } -func load3(in []byte) int64 { - var r int64 - r = int64(in[0]) - r |= int64(in[1]) << 8 - r |= int64(in[2]) << 16 - return r +type projCached struct { + YplusX, YminusX, Z, T2d field.Element } -func load4(in []byte) int64 { - var r int64 - r = int64(in[0]) - r |= int64(in[1]) << 8 - r |= int64(in[2]) << 16 - r |= int64(in[3]) << 24 - return r +type affineCached struct { + YplusX, YminusX, T2d field.Element } -func FeFromBytes(dst *FieldElement, src *[32]byte) { - h0 := load4(src[:]) - h1 := load3(src[4:]) << 6 - h2 := load3(src[7:]) << 5 - h3 := load3(src[10:]) << 3 - h4 := load3(src[13:]) << 2 - h5 := load4(src[16:]) - h6 := load3(src[20:]) << 7 - h7 := load3(src[23:]) << 5 - h8 := load3(src[26:]) << 4 - h9 := (load3(src[29:]) & 8388607) << 2 - - FeCombine(dst, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) -} +// Constructors. -// FeToBytes marshals h to s. -// Preconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Write p=2^255-19; q=floor(h/p). -// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). -// -// Proof: -// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. -// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4. -// -// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). -// Then 0<y<1. -// -// Write r=h-pq. -// Have 0<=r<=p-1=2^255-20. -// Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1. -// -// Write x=r+19(2^-255)r+y. -// Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q. -// -// Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1)) -// so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q. -func FeToBytes(s *[32]byte, h *FieldElement) { - var carry [10]int32 - - q := (19*h[9] + (1 << 24)) >> 25 - q = (h[0] + q) >> 26 - q = (h[1] + q) >> 25 - q = (h[2] + q) >> 26 - q = (h[3] + q) >> 25 - q = (h[4] + q) >> 26 - q = (h[5] + q) >> 25 - q = (h[6] + q) >> 26 - q = (h[7] + q) >> 25 - q = (h[8] + q) >> 26 - q = (h[9] + q) >> 25 - - // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. - h[0] += 19 * q - // Goal: Output h-2^255 q, which is between 0 and 2^255-20. - - carry[0] = h[0] >> 26 - h[1] += carry[0] - h[0] -= carry[0] << 26 - carry[1] = h[1] >> 25 - h[2] += carry[1] - h[1] -= carry[1] << 25 - carry[2] = h[2] >> 26 - h[3] += carry[2] - h[2] -= carry[2] << 26 - carry[3] = h[3] >> 25 - h[4] += carry[3] - h[3] -= carry[3] << 25 - carry[4] = h[4] >> 26 - h[5] += carry[4] - h[4] -= carry[4] << 26 - carry[5] = h[5] >> 25 - h[6] += carry[5] - h[5] -= carry[5] << 25 - carry[6] = h[6] >> 26 - h[7] += carry[6] - h[6] -= carry[6] << 26 - carry[7] = h[7] >> 25 - h[8] += carry[7] - h[7] -= carry[7] << 25 - carry[8] = h[8] >> 26 - h[9] += carry[8] - h[8] -= carry[8] << 26 - carry[9] = h[9] >> 25 - h[9] -= carry[9] << 25 - // h10 = carry9 - - // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. - // Have h[0]+...+2^230 h[9] between 0 and 2^255-1; - // evidently 2^255 h10-2^255 q = 0. - // Goal: Output h[0]+...+2^230 h[9]. - - s[0] = byte(h[0] >> 0) - s[1] = byte(h[0] >> 8) - s[2] = byte(h[0] >> 16) - s[3] = byte((h[0] >> 24) | (h[1] << 2)) - s[4] = byte(h[1] >> 6) - s[5] = byte(h[1] >> 14) - s[6] = byte((h[1] >> 22) | (h[2] << 3)) - s[7] = byte(h[2] >> 5) - s[8] = byte(h[2] >> 13) - s[9] = byte((h[2] >> 21) | (h[3] << 5)) - s[10] = byte(h[3] >> 3) - s[11] = byte(h[3] >> 11) - s[12] = byte((h[3] >> 19) | (h[4] << 6)) - s[13] = byte(h[4] >> 2) - s[14] = byte(h[4] >> 10) - s[15] = byte(h[4] >> 18) - s[16] = byte(h[5] >> 0) - s[17] = byte(h[5] >> 8) - s[18] = byte(h[5] >> 16) - s[19] = byte((h[5] >> 24) | (h[6] << 1)) - s[20] = byte(h[6] >> 7) - s[21] = byte(h[6] >> 15) - s[22] = byte((h[6] >> 23) | (h[7] << 3)) - s[23] = byte(h[7] >> 5) - s[24] = byte(h[7] >> 13) - s[25] = byte((h[7] >> 21) | (h[8] << 4)) - s[26] = byte(h[8] >> 4) - s[27] = byte(h[8] >> 12) - s[28] = byte((h[8] >> 20) | (h[9] << 6)) - s[29] = byte(h[9] >> 2) - s[30] = byte(h[9] >> 10) - s[31] = byte(h[9] >> 18) +func (v *projP2) Zero() *projP2 { + v.X.Zero() + v.Y.One() + v.Z.One() + return v } -func FeIsNegative(f *FieldElement) byte { - var s [32]byte - FeToBytes(&s, f) - return s[0] & 1 -} +// identity is the point at infinity. +var identity, _ = new(Point).SetBytes([]byte{ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) -func FeIsNonZero(f *FieldElement) int32 { - var s [32]byte - FeToBytes(&s, f) - var x uint8 - for _, b := range s { - x |= b - } - x |= x >> 4 - x |= x >> 2 - x |= x >> 1 - return int32(x & 1) +// NewIdentityPoint returns a new Point set to the identity. +func NewIdentityPoint() *Point { + return new(Point).Set(identity) } -// FeNeg sets h = -f -// -// Preconditions: -// |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -func FeNeg(h, f *FieldElement) { - h[0] = -f[0] - h[1] = -f[1] - h[2] = -f[2] - h[3] = -f[3] - h[4] = -f[4] - h[5] = -f[5] - h[6] = -f[6] - h[7] = -f[7] - h[8] = -f[8] - h[9] = -f[9] -} +// generator is the canonical curve basepoint. See TestGenerator for the +// correspondence of this encoding with the values in RFC 8032. +var generator, _ = new(Point).SetBytes([]byte{ + 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}) -func FeCombine(h *FieldElement, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) { - var c0, c1, c2, c3, c4, c5, c6, c7, c8, c9 int64 - - /* - |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) - i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8 - |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19)) - i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9 - */ - - c0 = (h0 + (1 << 25)) >> 26 - h1 += c0 - h0 -= c0 << 26 - c4 = (h4 + (1 << 25)) >> 26 - h5 += c4 - h4 -= c4 << 26 - /* |h0| <= 2^25 */ - /* |h4| <= 2^25 */ - /* |h1| <= 1.51*2^58 */ - /* |h5| <= 1.51*2^58 */ - - c1 = (h1 + (1 << 24)) >> 25 - h2 += c1 - h1 -= c1 << 25 - c5 = (h5 + (1 << 24)) >> 25 - h6 += c5 - h5 -= c5 << 25 - /* |h1| <= 2^24; from now on fits into int32 */ - /* |h5| <= 2^24; from now on fits into int32 */ - /* |h2| <= 1.21*2^59 */ - /* |h6| <= 1.21*2^59 */ - - c2 = (h2 + (1 << 25)) >> 26 - h3 += c2 - h2 -= c2 << 26 - c6 = (h6 + (1 << 25)) >> 26 - h7 += c6 - h6 -= c6 << 26 - /* |h2| <= 2^25; from now on fits into int32 unchanged */ - /* |h6| <= 2^25; from now on fits into int32 unchanged */ - /* |h3| <= 1.51*2^58 */ - /* |h7| <= 1.51*2^58 */ - - c3 = (h3 + (1 << 24)) >> 25 - h4 += c3 - h3 -= c3 << 25 - c7 = (h7 + (1 << 24)) >> 25 - h8 += c7 - h7 -= c7 << 25 - /* |h3| <= 2^24; from now on fits into int32 unchanged */ - /* |h7| <= 2^24; from now on fits into int32 unchanged */ - /* |h4| <= 1.52*2^33 */ - /* |h8| <= 1.52*2^33 */ - - c4 = (h4 + (1 << 25)) >> 26 - h5 += c4 - h4 -= c4 << 26 - c8 = (h8 + (1 << 25)) >> 26 - h9 += c8 - h8 -= c8 << 26 - /* |h4| <= 2^25; from now on fits into int32 unchanged */ - /* |h8| <= 2^25; from now on fits into int32 unchanged */ - /* |h5| <= 1.01*2^24 */ - /* |h9| <= 1.51*2^58 */ - - c9 = (h9 + (1 << 24)) >> 25 - h0 += c9 * 19 - h9 -= c9 << 25 - /* |h9| <= 2^24; from now on fits into int32 unchanged */ - /* |h0| <= 1.8*2^37 */ - - c0 = (h0 + (1 << 25)) >> 26 - h1 += c0 - h0 -= c0 << 26 - /* |h0| <= 2^25; from now on fits into int32 unchanged */ - /* |h1| <= 1.01*2^24 */ - - h[0] = int32(h0) - h[1] = int32(h1) - h[2] = int32(h2) - h[3] = int32(h3) - h[4] = int32(h4) - h[5] = int32(h5) - h[6] = int32(h6) - h[7] = int32(h7) - h[8] = int32(h8) - h[9] = int32(h9) +// NewGeneratorPoint returns a new Point set to the canonical generator. +func NewGeneratorPoint() *Point { + return new(Point).Set(generator) } -// FeMul calculates h = f * g -// Can overlap h with f or g. -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -// -// Notes on implementation strategy: -// -// Using schoolbook multiplication. -// Karatsuba would save a little in some cost models. -// -// Most multiplications by 2 and 19 are 32-bit precomputations; -// cheaper than 64-bit postcomputations. -// -// There is one remaining multiplication by 19 in the carry chain; -// one *19 precomputation can be merged into this, -// but the resulting data flow is considerably less clean. -// -// There are 12 carries below. -// 10 of them are 2-way parallelizable and vectorizable. -// Can get away with 11 carries, but then data flow is much deeper. -// -// With tighter constraints on inputs, can squeeze carries into int32. -func FeMul(h, f, g *FieldElement) { - f0 := int64(f[0]) - f1 := int64(f[1]) - f2 := int64(f[2]) - f3 := int64(f[3]) - f4 := int64(f[4]) - f5 := int64(f[5]) - f6 := int64(f[6]) - f7 := int64(f[7]) - f8 := int64(f[8]) - f9 := int64(f[9]) - - f1_2 := int64(2 * f[1]) - f3_2 := int64(2 * f[3]) - f5_2 := int64(2 * f[5]) - f7_2 := int64(2 * f[7]) - f9_2 := int64(2 * f[9]) - - g0 := int64(g[0]) - g1 := int64(g[1]) - g2 := int64(g[2]) - g3 := int64(g[3]) - g4 := int64(g[4]) - g5 := int64(g[5]) - g6 := int64(g[6]) - g7 := int64(g[7]) - g8 := int64(g[8]) - g9 := int64(g[9]) - - g1_19 := int64(19 * g[1]) /* 1.4*2^29 */ - g2_19 := int64(19 * g[2]) /* 1.4*2^30; still ok */ - g3_19 := int64(19 * g[3]) - g4_19 := int64(19 * g[4]) - g5_19 := int64(19 * g[5]) - g6_19 := int64(19 * g[6]) - g7_19 := int64(19 * g[7]) - g8_19 := int64(19 * g[8]) - g9_19 := int64(19 * g[9]) - - h0 := f0*g0 + f1_2*g9_19 + f2*g8_19 + f3_2*g7_19 + f4*g6_19 + f5_2*g5_19 + f6*g4_19 + f7_2*g3_19 + f8*g2_19 + f9_2*g1_19 - h1 := f0*g1 + f1*g0 + f2*g9_19 + f3*g8_19 + f4*g7_19 + f5*g6_19 + f6*g5_19 + f7*g4_19 + f8*g3_19 + f9*g2_19 - h2 := f0*g2 + f1_2*g1 + f2*g0 + f3_2*g9_19 + f4*g8_19 + f5_2*g7_19 + f6*g6_19 + f7_2*g5_19 + f8*g4_19 + f9_2*g3_19 - h3 := f0*g3 + f1*g2 + f2*g1 + f3*g0 + f4*g9_19 + f5*g8_19 + f6*g7_19 + f7*g6_19 + f8*g5_19 + f9*g4_19 - h4 := f0*g4 + f1_2*g3 + f2*g2 + f3_2*g1 + f4*g0 + f5_2*g9_19 + f6*g8_19 + f7_2*g7_19 + f8*g6_19 + f9_2*g5_19 - h5 := f0*g5 + f1*g4 + f2*g3 + f3*g2 + f4*g1 + f5*g0 + f6*g9_19 + f7*g8_19 + f8*g7_19 + f9*g6_19 - h6 := f0*g6 + f1_2*g5 + f2*g4 + f3_2*g3 + f4*g2 + f5_2*g1 + f6*g0 + f7_2*g9_19 + f8*g8_19 + f9_2*g7_19 - h7 := f0*g7 + f1*g6 + f2*g5 + f3*g4 + f4*g3 + f5*g2 + f6*g1 + f7*g0 + f8*g9_19 + f9*g8_19 - h8 := f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19 - h9 := f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0 - - FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) +func (v *projCached) Zero() *projCached { + v.YplusX.One() + v.YminusX.One() + v.Z.One() + v.T2d.Zero() + return v } -func feSquare(f *FieldElement) (h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) { - f0 := int64(f[0]) - f1 := int64(f[1]) - f2 := int64(f[2]) - f3 := int64(f[3]) - f4 := int64(f[4]) - f5 := int64(f[5]) - f6 := int64(f[6]) - f7 := int64(f[7]) - f8 := int64(f[8]) - f9 := int64(f[9]) - f0_2 := int64(2 * f[0]) - f1_2 := int64(2 * f[1]) - f2_2 := int64(2 * f[2]) - f3_2 := int64(2 * f[3]) - f4_2 := int64(2 * f[4]) - f5_2 := int64(2 * f[5]) - f6_2 := int64(2 * f[6]) - f7_2 := int64(2 * f[7]) - f5_38 := 38 * f5 // 1.31*2^30 - f6_19 := 19 * f6 // 1.31*2^30 - f7_38 := 38 * f7 // 1.31*2^30 - f8_19 := 19 * f8 // 1.31*2^30 - f9_38 := 38 * f9 // 1.31*2^30 - - h0 = f0*f0 + f1_2*f9_38 + f2_2*f8_19 + f3_2*f7_38 + f4_2*f6_19 + f5*f5_38 - h1 = f0_2*f1 + f2*f9_38 + f3_2*f8_19 + f4*f7_38 + f5_2*f6_19 - h2 = f0_2*f2 + f1_2*f1 + f3_2*f9_38 + f4_2*f8_19 + f5_2*f7_38 + f6*f6_19 - h3 = f0_2*f3 + f1_2*f2 + f4*f9_38 + f5_2*f8_19 + f6*f7_38 - h4 = f0_2*f4 + f1_2*f3_2 + f2*f2 + f5_2*f9_38 + f6_2*f8_19 + f7*f7_38 - h5 = f0_2*f5 + f1_2*f4 + f2_2*f3 + f6*f9_38 + f7_2*f8_19 - h6 = f0_2*f6 + f1_2*f5_2 + f2_2*f4 + f3_2*f3 + f7_2*f9_38 + f8*f8_19 - h7 = f0_2*f7 + f1_2*f6 + f2_2*f5 + f3_2*f4 + f8*f9_38 - h8 = f0_2*f8 + f1_2*f7_2 + f2_2*f6 + f3_2*f5_2 + f4*f4 + f9*f9_38 - h9 = f0_2*f9 + f1_2*f8 + f2_2*f7 + f3_2*f6 + f4_2*f5 - - return +func (v *affineCached) Zero() *affineCached { + v.YplusX.One() + v.YminusX.One() + v.T2d.Zero() + return v } -// FeSquare calculates h = f*f. Can overlap h with f. -// -// Preconditions: -// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -func FeSquare(h, f *FieldElement) { - h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f) - FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) +// Assignments. + +// Set sets v = u, and returns v. +func (v *Point) Set(u *Point) *Point { + *v = *u + return v } -// FeSquare2 sets h = 2 * f * f -// -// Can overlap h with f. -// -// Preconditions: -// |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. -// -// Postconditions: -// |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. -// See fe_mul.c for discussion of implementation strategy. -func FeSquare2(h, f *FieldElement) { - h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f) - - h0 += h0 - h1 += h1 - h2 += h2 - h3 += h3 - h4 += h4 - h5 += h5 - h6 += h6 - h7 += h7 - h8 += h8 - h9 += h9 - - FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) +// Encoding. + +// Bytes returns the canonical 32-byte encoding of v, according to RFC 8032, +// Section 5.1.2. +func (v *Point) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var buf [32]byte + return v.bytes(&buf) } -func FeInvert(out, z *FieldElement) { - var t0, t1, t2, t3 FieldElement - var i int +func (v *Point) bytes(buf *[32]byte) []byte { + checkInitialized(v) - FeSquare(&t0, z) // 2^1 - FeSquare(&t1, &t0) // 2^2 - for i = 1; i < 2; i++ { // 2^3 - FeSquare(&t1, &t1) - } - FeMul(&t1, z, &t1) // 2^3 + 2^0 - FeMul(&t0, &t0, &t1) // 2^3 + 2^1 + 2^0 - FeSquare(&t2, &t0) // 2^4 + 2^2 + 2^1 - FeMul(&t1, &t1, &t2) // 2^4 + 2^3 + 2^2 + 2^1 + 2^0 - FeSquare(&t2, &t1) // 5,4,3,2,1 - for i = 1; i < 5; i++ { // 9,8,7,6,5 - FeSquare(&t2, &t2) - } - FeMul(&t1, &t2, &t1) // 9,8,7,6,5,4,3,2,1,0 - FeSquare(&t2, &t1) // 10..1 - for i = 1; i < 10; i++ { // 19..10 - FeSquare(&t2, &t2) - } - FeMul(&t2, &t2, &t1) // 19..0 - FeSquare(&t3, &t2) // 20..1 - for i = 1; i < 20; i++ { // 39..20 - FeSquare(&t3, &t3) - } - FeMul(&t2, &t3, &t2) // 39..0 - FeSquare(&t2, &t2) // 40..1 - for i = 1; i < 10; i++ { // 49..10 - FeSquare(&t2, &t2) - } - FeMul(&t1, &t2, &t1) // 49..0 - FeSquare(&t2, &t1) // 50..1 - for i = 1; i < 50; i++ { // 99..50 - FeSquare(&t2, &t2) - } - FeMul(&t2, &t2, &t1) // 99..0 - FeSquare(&t3, &t2) // 100..1 - for i = 1; i < 100; i++ { // 199..100 - FeSquare(&t3, &t3) - } - FeMul(&t2, &t3, &t2) // 199..0 - FeSquare(&t2, &t2) // 200..1 - for i = 1; i < 50; i++ { // 249..50 - FeSquare(&t2, &t2) - } - FeMul(&t1, &t2, &t1) // 249..0 - FeSquare(&t1, &t1) // 250..1 - for i = 1; i < 5; i++ { // 254..5 - FeSquare(&t1, &t1) - } - FeMul(out, &t1, &t0) // 254..5,3,1,0 + var zInv, x, y field.Element + zInv.Invert(&v.z) // zInv = 1 / Z + x.Multiply(&v.x, &zInv) // x = X / Z + y.Multiply(&v.y, &zInv) // y = Y / Z + + out := copyFieldElement(buf, &y) + out[31] |= byte(x.IsNegative() << 7) + return out } -func fePow22523(out, z *FieldElement) { - var t0, t1, t2 FieldElement - var i int +var feOne = new(field.Element).One() - FeSquare(&t0, z) - for i = 1; i < 1; i++ { - FeSquare(&t0, &t0) - } - FeSquare(&t1, &t0) - for i = 1; i < 2; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t1, z, &t1) - FeMul(&t0, &t0, &t1) - FeSquare(&t0, &t0) - for i = 1; i < 1; i++ { - FeSquare(&t0, &t0) - } - FeMul(&t0, &t1, &t0) - FeSquare(&t1, &t0) - for i = 1; i < 5; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t0, &t1, &t0) - FeSquare(&t1, &t0) - for i = 1; i < 10; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t1, &t1, &t0) - FeSquare(&t2, &t1) - for i = 1; i < 20; i++ { - FeSquare(&t2, &t2) - } - FeMul(&t1, &t2, &t1) - FeSquare(&t1, &t1) - for i = 1; i < 10; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t0, &t1, &t0) - FeSquare(&t1, &t0) - for i = 1; i < 50; i++ { - FeSquare(&t1, &t1) - } - FeMul(&t1, &t1, &t0) - FeSquare(&t2, &t1) - for i = 1; i < 100; i++ { - FeSquare(&t2, &t2) - } - FeMul(&t1, &t2, &t1) - FeSquare(&t1, &t1) - for i = 1; i < 50; i++ { - FeSquare(&t1, &t1) +// SetBytes sets v = x, where x is a 32-byte encoding of v. If x does not +// represent a valid point on the curve, SetBytes returns nil and an error and +// the receiver is unchanged. Otherwise, SetBytes returns v. +// +// Note that SetBytes accepts all non-canonical encodings of valid points. +// That is, it follows decoding rules that match most implementations in +// the ecosystem rather than RFC 8032. +func (v *Point) SetBytes(x []byte) (*Point, error) { + // Specifically, the non-canonical encodings that are accepted are + // 1) the ones where the field element is not reduced (see the + // (*field.Element).SetBytes docs) and + // 2) the ones where the x-coordinate is zero and the sign bit is set. + // + // This is consistent with crypto/ed25519/internal/edwards25519. Read more + // at https://hdevalence.ca/blog/2020-10-04-its-25519am, specifically the + // "Canonical A, R" section. + + if len(x) != 32 { + return nil, errors.New("edwards25519: invalid point encoding length") } - FeMul(&t0, &t1, &t0) - FeSquare(&t0, &t0) - for i = 1; i < 2; i++ { - FeSquare(&t0, &t0) + y := new(field.Element).SetBytes(x) + + // -x² + y² = 1 + dx²y² + // x² + dx²y² = x²(dy² + 1) = y² - 1 + // x² = (y² - 1) / (dy² + 1) + + // u = y² - 1 + y2 := new(field.Element).Square(y) + u := new(field.Element).Subtract(y2, feOne) + + // v = dy² + 1 + vv := new(field.Element).Multiply(y2, d) + vv = vv.Add(vv, feOne) + + // x = +√(u/v) + xx, wasSquare := new(field.Element).SqrtRatio(u, vv) + if wasSquare == 0 { + return nil, errors.New("edwards25519: invalid point encoding") } - FeMul(out, &t0, z) -} -// Group elements are members of the elliptic curve -x^2 + y^2 = 1 + d * x^2 * -// y^2 where d = -121665/121666. -// -// Several representations are used: -// ProjectiveGroupElement: (X:Y:Z) satisfying x=X/Z, y=Y/Z -// ExtendedGroupElement: (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT -// CompletedGroupElement: ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T -// PreComputedGroupElement: (y+x,y-x,2dxy) - -type ProjectiveGroupElement struct { - X, Y, Z FieldElement -} + // Select the negative square root if the sign bit is set. + xxNeg := new(field.Element).Negate(xx) + xx = xx.Select(xxNeg, xx, int(x[31]>>7)) -type ExtendedGroupElement struct { - X, Y, Z, T FieldElement + v.x.Set(xx) + v.y.Set(y) + v.z.One() + v.t.Multiply(xx, y) // xy = T / Z + + return v, nil } -type CompletedGroupElement struct { - X, Y, Z, T FieldElement +func copyFieldElement(buf *[32]byte, v *field.Element) []byte { + copy(buf[:], v.Bytes()) + return buf[:] } -type PreComputedGroupElement struct { - yPlusX, yMinusX, xy2d FieldElement +// Conversions. + +func (v *projP2) FromP1xP1(p *projP1xP1) *projP2 { + v.X.Multiply(&p.X, &p.T) + v.Y.Multiply(&p.Y, &p.Z) + v.Z.Multiply(&p.Z, &p.T) + return v } -type CachedGroupElement struct { - yPlusX, yMinusX, Z, T2d FieldElement +func (v *projP2) FromP3(p *Point) *projP2 { + v.X.Set(&p.x) + v.Y.Set(&p.y) + v.Z.Set(&p.z) + return v } -func (p *ProjectiveGroupElement) Zero() { - FeZero(&p.X) - FeOne(&p.Y) - FeOne(&p.Z) +func (v *Point) fromP1xP1(p *projP1xP1) *Point { + v.x.Multiply(&p.X, &p.T) + v.y.Multiply(&p.Y, &p.Z) + v.z.Multiply(&p.Z, &p.T) + v.t.Multiply(&p.X, &p.Y) + return v } -func (p *ProjectiveGroupElement) Double(r *CompletedGroupElement) { - var t0 FieldElement - - FeSquare(&r.X, &p.X) - FeSquare(&r.Z, &p.Y) - FeSquare2(&r.T, &p.Z) - FeAdd(&r.Y, &p.X, &p.Y) - FeSquare(&t0, &r.Y) - FeAdd(&r.Y, &r.Z, &r.X) - FeSub(&r.Z, &r.Z, &r.X) - FeSub(&r.X, &t0, &r.Y) - FeSub(&r.T, &r.T, &r.Z) +func (v *Point) fromP2(p *projP2) *Point { + v.x.Multiply(&p.X, &p.Z) + v.y.Multiply(&p.Y, &p.Z) + v.z.Square(&p.Z) + v.t.Multiply(&p.X, &p.Y) + return v } -func (p *ProjectiveGroupElement) ToBytes(s *[32]byte) { - var recip, x, y FieldElement +// d is a constant in the curve equation. +var d = new(field.Element).SetBytes([]byte{ + 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, + 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00, + 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, + 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52}) +var d2 = new(field.Element).Add(d, d) - FeInvert(&recip, &p.Z) - FeMul(&x, &p.X, &recip) - FeMul(&y, &p.Y, &recip) - FeToBytes(s, &y) - s[31] ^= FeIsNegative(&x) << 7 +func (v *projCached) FromP3(p *Point) *projCached { + v.YplusX.Add(&p.y, &p.x) + v.YminusX.Subtract(&p.y, &p.x) + v.Z.Set(&p.z) + v.T2d.Multiply(&p.t, d2) + return v } -func (p *ExtendedGroupElement) Zero() { - FeZero(&p.X) - FeOne(&p.Y) - FeOne(&p.Z) - FeZero(&p.T) -} +func (v *affineCached) FromP3(p *Point) *affineCached { + v.YplusX.Add(&p.y, &p.x) + v.YminusX.Subtract(&p.y, &p.x) + v.T2d.Multiply(&p.t, d2) -func (p *ExtendedGroupElement) Double(r *CompletedGroupElement) { - var q ProjectiveGroupElement - p.ToProjective(&q) - q.Double(r) + var invZ field.Element + invZ.Invert(&p.z) + v.YplusX.Multiply(&v.YplusX, &invZ) + v.YminusX.Multiply(&v.YminusX, &invZ) + v.T2d.Multiply(&v.T2d, &invZ) + return v } -func (p *ExtendedGroupElement) ToCached(r *CachedGroupElement) { - FeAdd(&r.yPlusX, &p.Y, &p.X) - FeSub(&r.yMinusX, &p.Y, &p.X) - FeCopy(&r.Z, &p.Z) - FeMul(&r.T2d, &p.T, &d2) -} +// (Re)addition and subtraction. -func (p *ExtendedGroupElement) ToProjective(r *ProjectiveGroupElement) { - FeCopy(&r.X, &p.X) - FeCopy(&r.Y, &p.Y) - FeCopy(&r.Z, &p.Z) +// Add sets v = p + q, and returns v. +func (v *Point) Add(p, q *Point) *Point { + checkInitialized(p, q) + qCached := new(projCached).FromP3(q) + result := new(projP1xP1).Add(p, qCached) + return v.fromP1xP1(result) } -func (p *ExtendedGroupElement) ToBytes(s *[32]byte) { - var recip, x, y FieldElement - - FeInvert(&recip, &p.Z) - FeMul(&x, &p.X, &recip) - FeMul(&y, &p.Y, &recip) - FeToBytes(s, &y) - s[31] ^= FeIsNegative(&x) << 7 +// Subtract sets v = p - q, and returns v. +func (v *Point) Subtract(p, q *Point) *Point { + checkInitialized(p, q) + qCached := new(projCached).FromP3(q) + result := new(projP1xP1).Sub(p, qCached) + return v.fromP1xP1(result) } -func (p *ExtendedGroupElement) FromBytes(s *[32]byte) bool { - var u, v, v3, vxx, check FieldElement - - FeFromBytes(&p.Y, s) - FeOne(&p.Z) - FeSquare(&u, &p.Y) - FeMul(&v, &u, &d) - FeSub(&u, &u, &p.Z) // u = y^2-1 - FeAdd(&v, &v, &p.Z) // v = dy^2+1 - - FeSquare(&v3, &v) - FeMul(&v3, &v3, &v) // v3 = v^3 - FeSquare(&p.X, &v3) - FeMul(&p.X, &p.X, &v) - FeMul(&p.X, &p.X, &u) // x = uv^7 - - fePow22523(&p.X, &p.X) // x = (uv^7)^((q-5)/8) - FeMul(&p.X, &p.X, &v3) - FeMul(&p.X, &p.X, &u) // x = uv^3(uv^7)^((q-5)/8) - - var tmpX, tmp2 [32]byte - - FeSquare(&vxx, &p.X) - FeMul(&vxx, &vxx, &v) - FeSub(&check, &vxx, &u) // vx^2-u - if FeIsNonZero(&check) == 1 { - FeAdd(&check, &vxx, &u) // vx^2+u - if FeIsNonZero(&check) == 1 { - return false - } - FeMul(&p.X, &p.X, &SqrtM1) +func (v *projP1xP1) Add(p *Point, q *projCached) *projP1xP1 { + var YplusX, YminusX, PP, MM, TT2d, ZZ2 field.Element - FeToBytes(&tmpX, &p.X) - for i, v := range tmpX { - tmp2[31-i] = v - } - } + YplusX.Add(&p.y, &p.x) + YminusX.Subtract(&p.y, &p.x) - if FeIsNegative(&p.X) != (s[31] >> 7) { - FeNeg(&p.X, &p.X) - } + PP.Multiply(&YplusX, &q.YplusX) + MM.Multiply(&YminusX, &q.YminusX) + TT2d.Multiply(&p.t, &q.T2d) + ZZ2.Multiply(&p.z, &q.Z) - FeMul(&p.T, &p.X, &p.Y) - return true -} + ZZ2.Add(&ZZ2, &ZZ2) -func (p *CompletedGroupElement) ToProjective(r *ProjectiveGroupElement) { - FeMul(&r.X, &p.X, &p.T) - FeMul(&r.Y, &p.Y, &p.Z) - FeMul(&r.Z, &p.Z, &p.T) + v.X.Subtract(&PP, &MM) + v.Y.Add(&PP, &MM) + v.Z.Add(&ZZ2, &TT2d) + v.T.Subtract(&ZZ2, &TT2d) + return v } -func (p *CompletedGroupElement) ToExtended(r *ExtendedGroupElement) { - FeMul(&r.X, &p.X, &p.T) - FeMul(&r.Y, &p.Y, &p.Z) - FeMul(&r.Z, &p.Z, &p.T) - FeMul(&r.T, &p.X, &p.Y) -} +func (v *projP1xP1) Sub(p *Point, q *projCached) *projP1xP1 { + var YplusX, YminusX, PP, MM, TT2d, ZZ2 field.Element -func (p *PreComputedGroupElement) Zero() { - FeOne(&p.yPlusX) - FeOne(&p.yMinusX) - FeZero(&p.xy2d) -} + YplusX.Add(&p.y, &p.x) + YminusX.Subtract(&p.y, &p.x) -func geAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) { - var t0 FieldElement - - FeAdd(&r.X, &p.Y, &p.X) - FeSub(&r.Y, &p.Y, &p.X) - FeMul(&r.Z, &r.X, &q.yPlusX) - FeMul(&r.Y, &r.Y, &q.yMinusX) - FeMul(&r.T, &q.T2d, &p.T) - FeMul(&r.X, &p.Z, &q.Z) - FeAdd(&t0, &r.X, &r.X) - FeSub(&r.X, &r.Z, &r.Y) - FeAdd(&r.Y, &r.Z, &r.Y) - FeAdd(&r.Z, &t0, &r.T) - FeSub(&r.T, &t0, &r.T) -} + PP.Multiply(&YplusX, &q.YminusX) // flipped sign + MM.Multiply(&YminusX, &q.YplusX) // flipped sign + TT2d.Multiply(&p.t, &q.T2d) + ZZ2.Multiply(&p.z, &q.Z) -func geSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) { - var t0 FieldElement - - FeAdd(&r.X, &p.Y, &p.X) - FeSub(&r.Y, &p.Y, &p.X) - FeMul(&r.Z, &r.X, &q.yMinusX) - FeMul(&r.Y, &r.Y, &q.yPlusX) - FeMul(&r.T, &q.T2d, &p.T) - FeMul(&r.X, &p.Z, &q.Z) - FeAdd(&t0, &r.X, &r.X) - FeSub(&r.X, &r.Z, &r.Y) - FeAdd(&r.Y, &r.Z, &r.Y) - FeSub(&r.Z, &t0, &r.T) - FeAdd(&r.T, &t0, &r.T) -} + ZZ2.Add(&ZZ2, &ZZ2) -func geMixedAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) { - var t0 FieldElement - - FeAdd(&r.X, &p.Y, &p.X) - FeSub(&r.Y, &p.Y, &p.X) - FeMul(&r.Z, &r.X, &q.yPlusX) - FeMul(&r.Y, &r.Y, &q.yMinusX) - FeMul(&r.T, &q.xy2d, &p.T) - FeAdd(&t0, &p.Z, &p.Z) - FeSub(&r.X, &r.Z, &r.Y) - FeAdd(&r.Y, &r.Z, &r.Y) - FeAdd(&r.Z, &t0, &r.T) - FeSub(&r.T, &t0, &r.T) + v.X.Subtract(&PP, &MM) + v.Y.Add(&PP, &MM) + v.Z.Subtract(&ZZ2, &TT2d) // flipped sign + v.T.Add(&ZZ2, &TT2d) // flipped sign + return v } -func geMixedSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) { - var t0 FieldElement - - FeAdd(&r.X, &p.Y, &p.X) - FeSub(&r.Y, &p.Y, &p.X) - FeMul(&r.Z, &r.X, &q.yMinusX) - FeMul(&r.Y, &r.Y, &q.yPlusX) - FeMul(&r.T, &q.xy2d, &p.T) - FeAdd(&t0, &p.Z, &p.Z) - FeSub(&r.X, &r.Z, &r.Y) - FeAdd(&r.Y, &r.Z, &r.Y) - FeSub(&r.Z, &t0, &r.T) - FeAdd(&r.T, &t0, &r.T) -} +func (v *projP1xP1) AddAffine(p *Point, q *affineCached) *projP1xP1 { + var YplusX, YminusX, PP, MM, TT2d, Z2 field.Element -func slide(r *[256]int8, a *[32]byte) { - for i := range r { - r[i] = int8(1 & (a[i>>3] >> uint(i&7))) - } + YplusX.Add(&p.y, &p.x) + YminusX.Subtract(&p.y, &p.x) - for i := range r { - if r[i] != 0 { - for b := 1; b <= 6 && i+b < 256; b++ { - if r[i+b] != 0 { - if r[i]+(r[i+b]<<uint(b)) <= 15 { - r[i] += r[i+b] << uint(b) - r[i+b] = 0 - } else if r[i]-(r[i+b]<<uint(b)) >= -15 { - r[i] -= r[i+b] << uint(b) - for k := i + b; k < 256; k++ { - if r[k] == 0 { - r[k] = 1 - break - } - r[k] = 0 - } - } else { - break - } - } - } - } - } -} + PP.Multiply(&YplusX, &q.YplusX) + MM.Multiply(&YminusX, &q.YminusX) + TT2d.Multiply(&p.t, &q.T2d) -// GeDoubleScalarMultVartime sets r = a*A + b*B -// where a = a[0]+256*a[1]+...+256^31 a[31]. -// and b = b[0]+256*b[1]+...+256^31 b[31]. -// B is the Ed25519 base point (x,4/5) with x positive. -func GeDoubleScalarMultVartime(r *ProjectiveGroupElement, a *[32]byte, A *ExtendedGroupElement, b *[32]byte) { - var aSlide, bSlide [256]int8 - var Ai [8]CachedGroupElement // A,3A,5A,7A,9A,11A,13A,15A - var t CompletedGroupElement - var u, A2 ExtendedGroupElement - var i int - - slide(&aSlide, a) - slide(&bSlide, b) - - A.ToCached(&Ai[0]) - A.Double(&t) - t.ToExtended(&A2) - - for i := 0; i < 7; i++ { - geAdd(&t, &A2, &Ai[i]) - t.ToExtended(&u) - u.ToCached(&Ai[i+1]) - } + Z2.Add(&p.z, &p.z) - r.Zero() + v.X.Subtract(&PP, &MM) + v.Y.Add(&PP, &MM) + v.Z.Add(&Z2, &TT2d) + v.T.Subtract(&Z2, &TT2d) + return v +} - for i = 255; i >= 0; i-- { - if aSlide[i] != 0 || bSlide[i] != 0 { - break - } - } +func (v *projP1xP1) SubAffine(p *Point, q *affineCached) *projP1xP1 { + var YplusX, YminusX, PP, MM, TT2d, Z2 field.Element - for ; i >= 0; i-- { - r.Double(&t) + YplusX.Add(&p.y, &p.x) + YminusX.Subtract(&p.y, &p.x) - if aSlide[i] > 0 { - t.ToExtended(&u) - geAdd(&t, &u, &Ai[aSlide[i]/2]) - } else if aSlide[i] < 0 { - t.ToExtended(&u) - geSub(&t, &u, &Ai[(-aSlide[i])/2]) - } + PP.Multiply(&YplusX, &q.YminusX) // flipped sign + MM.Multiply(&YminusX, &q.YplusX) // flipped sign + TT2d.Multiply(&p.t, &q.T2d) - if bSlide[i] > 0 { - t.ToExtended(&u) - geMixedAdd(&t, &u, &bi[bSlide[i]/2]) - } else if bSlide[i] < 0 { - t.ToExtended(&u) - geMixedSub(&t, &u, &bi[(-bSlide[i])/2]) - } + Z2.Add(&p.z, &p.z) - t.ToProjective(r) - } + v.X.Subtract(&PP, &MM) + v.Y.Add(&PP, &MM) + v.Z.Subtract(&Z2, &TT2d) // flipped sign + v.T.Add(&Z2, &TT2d) // flipped sign + return v } -// equal returns 1 if b == c and 0 otherwise, assuming that b and c are -// non-negative. -func equal(b, c int32) int32 { - x := uint32(b ^ c) - x-- - return int32(x >> 31) -} +// Doubling. -// negative returns 1 if b < 0 and 0 otherwise. -func negative(b int32) int32 { - return (b >> 31) & 1 -} +func (v *projP1xP1) Double(p *projP2) *projP1xP1 { + var XX, YY, ZZ2, XplusYsq field.Element -func PreComputedGroupElementCMove(t, u *PreComputedGroupElement, b int32) { - FeCMove(&t.yPlusX, &u.yPlusX, b) - FeCMove(&t.yMinusX, &u.yMinusX, b) - FeCMove(&t.xy2d, &u.xy2d, b) -} + XX.Square(&p.X) + YY.Square(&p.Y) + ZZ2.Square(&p.Z) + ZZ2.Add(&ZZ2, &ZZ2) + XplusYsq.Add(&p.X, &p.Y) + XplusYsq.Square(&XplusYsq) -func selectPoint(t *PreComputedGroupElement, pos int32, b int32) { - var minusT PreComputedGroupElement - bNegative := negative(b) - bAbs := b - (((-bNegative) & b) << 1) + v.Y.Add(&YY, &XX) + v.Z.Subtract(&YY, &XX) - t.Zero() - for i := int32(0); i < 8; i++ { - PreComputedGroupElementCMove(t, &base[pos][i], equal(bAbs, i+1)) - } - FeCopy(&minusT.yPlusX, &t.yMinusX) - FeCopy(&minusT.yMinusX, &t.yPlusX) - FeNeg(&minusT.xy2d, &t.xy2d) - PreComputedGroupElementCMove(t, &minusT, bNegative) + v.X.Subtract(&XplusYsq, &v.Y) + v.T.Subtract(&ZZ2, &v.Z) + return v } -// GeScalarMultBase computes h = a*B, where -// a = a[0]+256*a[1]+...+256^31 a[31] -// B is the Ed25519 base point (x,4/5) with x positive. -// -// Preconditions: -// a[31] <= 127 -func GeScalarMultBase(h *ExtendedGroupElement, a *[32]byte) { - var e [64]int8 - - for i, v := range a { - e[2*i] = int8(v & 15) - e[2*i+1] = int8((v >> 4) & 15) - } +// Negation. - // each e[i] is between 0 and 15 and e[63] is between 0 and 7. +// Negate sets v = -p, and returns v. +func (v *Point) Negate(p *Point) *Point { + checkInitialized(p) + v.x.Negate(&p.x) + v.y.Set(&p.y) + v.z.Set(&p.z) + v.t.Negate(&p.t) + return v +} - carry := int8(0) - for i := 0; i < 63; i++ { - e[i] += carry - carry = (e[i] + 8) >> 4 - e[i] -= carry << 4 - } - e[63] += carry - // each e[i] is between -8 and 8. - - h.Zero() - var t PreComputedGroupElement - var r CompletedGroupElement - for i := int32(1); i < 64; i += 2 { - selectPoint(&t, i/2, int32(e[i])) - geMixedAdd(&r, h, &t) - r.ToExtended(h) - } +// Equal returns 1 if v is equivalent to u, and 0 otherwise. +func (v *Point) Equal(u *Point) int { + checkInitialized(v, u) - var s ProjectiveGroupElement - - h.Double(&r) - r.ToProjective(&s) - s.Double(&r) - r.ToProjective(&s) - s.Double(&r) - r.ToProjective(&s) - s.Double(&r) - r.ToExtended(h) - - for i := int32(0); i < 64; i += 2 { - selectPoint(&t, i/2, int32(e[i])) - geMixedAdd(&r, h, &t) - r.ToExtended(h) - } + var t1, t2, t3, t4 field.Element + t1.Multiply(&v.x, &u.z) + t2.Multiply(&u.x, &v.z) + t3.Multiply(&v.y, &u.z) + t4.Multiply(&u.y, &v.z) + + return t1.Equal(&t2) & t3.Equal(&t4) } -// The scalars are GF(2^252 + 27742317777372353535851937790883648493). +// Constant-time operations -// Input: -// a[0]+256*a[1]+...+256^31*a[31] = a -// b[0]+256*b[1]+...+256^31*b[31] = b -// c[0]+256*c[1]+...+256^31*c[31] = c -// -// Output: -// s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l -// where l = 2^252 + 27742317777372353535851937790883648493. -func ScMulAdd(s, a, b, c *[32]byte) { - a0 := 2097151 & load3(a[:]) - a1 := 2097151 & (load4(a[2:]) >> 5) - a2 := 2097151 & (load3(a[5:]) >> 2) - a3 := 2097151 & (load4(a[7:]) >> 7) - a4 := 2097151 & (load4(a[10:]) >> 4) - a5 := 2097151 & (load3(a[13:]) >> 1) - a6 := 2097151 & (load4(a[15:]) >> 6) - a7 := 2097151 & (load3(a[18:]) >> 3) - a8 := 2097151 & load3(a[21:]) - a9 := 2097151 & (load4(a[23:]) >> 5) - a10 := 2097151 & (load3(a[26:]) >> 2) - a11 := (load4(a[28:]) >> 7) - b0 := 2097151 & load3(b[:]) - b1 := 2097151 & (load4(b[2:]) >> 5) - b2 := 2097151 & (load3(b[5:]) >> 2) - b3 := 2097151 & (load4(b[7:]) >> 7) - b4 := 2097151 & (load4(b[10:]) >> 4) - b5 := 2097151 & (load3(b[13:]) >> 1) - b6 := 2097151 & (load4(b[15:]) >> 6) - b7 := 2097151 & (load3(b[18:]) >> 3) - b8 := 2097151 & load3(b[21:]) - b9 := 2097151 & (load4(b[23:]) >> 5) - b10 := 2097151 & (load3(b[26:]) >> 2) - b11 := (load4(b[28:]) >> 7) - c0 := 2097151 & load3(c[:]) - c1 := 2097151 & (load4(c[2:]) >> 5) - c2 := 2097151 & (load3(c[5:]) >> 2) - c3 := 2097151 & (load4(c[7:]) >> 7) - c4 := 2097151 & (load4(c[10:]) >> 4) - c5 := 2097151 & (load3(c[13:]) >> 1) - c6 := 2097151 & (load4(c[15:]) >> 6) - c7 := 2097151 & (load3(c[18:]) >> 3) - c8 := 2097151 & load3(c[21:]) - c9 := 2097151 & (load4(c[23:]) >> 5) - c10 := 2097151 & (load3(c[26:]) >> 2) - c11 := (load4(c[28:]) >> 7) - var carry [23]int64 - - s0 := c0 + a0*b0 - s1 := c1 + a0*b1 + a1*b0 - s2 := c2 + a0*b2 + a1*b1 + a2*b0 - s3 := c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0 - s4 := c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0 - s5 := c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0 - s6 := c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0 - s7 := c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0 - s8 := c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0 - s9 := c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0 - s10 := c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0 - s11 := c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0 - s12 := a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1 - s13 := a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2 - s14 := a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3 - s15 := a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4 - s16 := a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5 - s17 := a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6 - s18 := a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7 - s19 := a8*b11 + a9*b10 + a10*b9 + a11*b8 - s20 := a9*b11 + a10*b10 + a11*b9 - s21 := a10*b11 + a11*b10 - s22 := a11 * b11 - s23 := int64(0) - - carry[0] = (s0 + (1 << 20)) >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[2] = (s2 + (1 << 20)) >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[4] = (s4 + (1 << 20)) >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[12] = (s12 + (1 << 20)) >> 21 - s13 += carry[12] - s12 -= carry[12] << 21 - carry[14] = (s14 + (1 << 20)) >> 21 - s15 += carry[14] - s14 -= carry[14] << 21 - carry[16] = (s16 + (1 << 20)) >> 21 - s17 += carry[16] - s16 -= carry[16] << 21 - carry[18] = (s18 + (1 << 20)) >> 21 - s19 += carry[18] - s18 -= carry[18] << 21 - carry[20] = (s20 + (1 << 20)) >> 21 - s21 += carry[20] - s20 -= carry[20] << 21 - carry[22] = (s22 + (1 << 20)) >> 21 - s23 += carry[22] - s22 -= carry[22] << 21 - - carry[1] = (s1 + (1 << 20)) >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[3] = (s3 + (1 << 20)) >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[5] = (s5 + (1 << 20)) >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - carry[13] = (s13 + (1 << 20)) >> 21 - s14 += carry[13] - s13 -= carry[13] << 21 - carry[15] = (s15 + (1 << 20)) >> 21 - s16 += carry[15] - s15 -= carry[15] << 21 - carry[17] = (s17 + (1 << 20)) >> 21 - s18 += carry[17] - s17 -= carry[17] << 21 - carry[19] = (s19 + (1 << 20)) >> 21 - s20 += carry[19] - s19 -= carry[19] << 21 - carry[21] = (s21 + (1 << 20)) >> 21 - s22 += carry[21] - s21 -= carry[21] << 21 - - s11 += s23 * 666643 - s12 += s23 * 470296 - s13 += s23 * 654183 - s14 -= s23 * 997805 - s15 += s23 * 136657 - s16 -= s23 * 683901 - s23 = 0 - - s10 += s22 * 666643 - s11 += s22 * 470296 - s12 += s22 * 654183 - s13 -= s22 * 997805 - s14 += s22 * 136657 - s15 -= s22 * 683901 - s22 = 0 - - s9 += s21 * 666643 - s10 += s21 * 470296 - s11 += s21 * 654183 - s12 -= s21 * 997805 - s13 += s21 * 136657 - s14 -= s21 * 683901 - s21 = 0 - - s8 += s20 * 666643 - s9 += s20 * 470296 - s10 += s20 * 654183 - s11 -= s20 * 997805 - s12 += s20 * 136657 - s13 -= s20 * 683901 - s20 = 0 - - s7 += s19 * 666643 - s8 += s19 * 470296 - s9 += s19 * 654183 - s10 -= s19 * 997805 - s11 += s19 * 136657 - s12 -= s19 * 683901 - s19 = 0 - - s6 += s18 * 666643 - s7 += s18 * 470296 - s8 += s18 * 654183 - s9 -= s18 * 997805 - s10 += s18 * 136657 - s11 -= s18 * 683901 - s18 = 0 - - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[12] = (s12 + (1 << 20)) >> 21 - s13 += carry[12] - s12 -= carry[12] << 21 - carry[14] = (s14 + (1 << 20)) >> 21 - s15 += carry[14] - s14 -= carry[14] << 21 - carry[16] = (s16 + (1 << 20)) >> 21 - s17 += carry[16] - s16 -= carry[16] << 21 - - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - carry[13] = (s13 + (1 << 20)) >> 21 - s14 += carry[13] - s13 -= carry[13] << 21 - carry[15] = (s15 + (1 << 20)) >> 21 - s16 += carry[15] - s15 -= carry[15] << 21 - - s5 += s17 * 666643 - s6 += s17 * 470296 - s7 += s17 * 654183 - s8 -= s17 * 997805 - s9 += s17 * 136657 - s10 -= s17 * 683901 - s17 = 0 - - s4 += s16 * 666643 - s5 += s16 * 470296 - s6 += s16 * 654183 - s7 -= s16 * 997805 - s8 += s16 * 136657 - s9 -= s16 * 683901 - s16 = 0 - - s3 += s15 * 666643 - s4 += s15 * 470296 - s5 += s15 * 654183 - s6 -= s15 * 997805 - s7 += s15 * 136657 - s8 -= s15 * 683901 - s15 = 0 - - s2 += s14 * 666643 - s3 += s14 * 470296 - s4 += s14 * 654183 - s5 -= s14 * 997805 - s6 += s14 * 136657 - s7 -= s14 * 683901 - s14 = 0 - - s1 += s13 * 666643 - s2 += s13 * 470296 - s3 += s13 * 654183 - s4 -= s13 * 997805 - s5 += s13 * 136657 - s6 -= s13 * 683901 - s13 = 0 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = (s0 + (1 << 20)) >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[2] = (s2 + (1 << 20)) >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[4] = (s4 + (1 << 20)) >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - - carry[1] = (s1 + (1 << 20)) >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[3] = (s3 + (1 << 20)) >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[5] = (s5 + (1 << 20)) >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = s0 >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[1] = s1 >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[2] = s2 >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[3] = s3 >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[4] = s4 >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[5] = s5 >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[6] = s6 >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[7] = s7 >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[8] = s8 >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[9] = s9 >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[10] = s10 >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[11] = s11 >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = s0 >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[1] = s1 >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[2] = s2 >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[3] = s3 >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[4] = s4 >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[5] = s5 >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[6] = s6 >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[7] = s7 >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[8] = s8 >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[9] = s9 >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[10] = s10 >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - - s[0] = byte(s0 >> 0) - s[1] = byte(s0 >> 8) - s[2] = byte((s0 >> 16) | (s1 << 5)) - s[3] = byte(s1 >> 3) - s[4] = byte(s1 >> 11) - s[5] = byte((s1 >> 19) | (s2 << 2)) - s[6] = byte(s2 >> 6) - s[7] = byte((s2 >> 14) | (s3 << 7)) - s[8] = byte(s3 >> 1) - s[9] = byte(s3 >> 9) - s[10] = byte((s3 >> 17) | (s4 << 4)) - s[11] = byte(s4 >> 4) - s[12] = byte(s4 >> 12) - s[13] = byte((s4 >> 20) | (s5 << 1)) - s[14] = byte(s5 >> 7) - s[15] = byte((s5 >> 15) | (s6 << 6)) - s[16] = byte(s6 >> 2) - s[17] = byte(s6 >> 10) - s[18] = byte((s6 >> 18) | (s7 << 3)) - s[19] = byte(s7 >> 5) - s[20] = byte(s7 >> 13) - s[21] = byte(s8 >> 0) - s[22] = byte(s8 >> 8) - s[23] = byte((s8 >> 16) | (s9 << 5)) - s[24] = byte(s9 >> 3) - s[25] = byte(s9 >> 11) - s[26] = byte((s9 >> 19) | (s10 << 2)) - s[27] = byte(s10 >> 6) - s[28] = byte((s10 >> 14) | (s11 << 7)) - s[29] = byte(s11 >> 1) - s[30] = byte(s11 >> 9) - s[31] = byte(s11 >> 17) +// Select sets v to a if cond == 1 and to b if cond == 0. +func (v *projCached) Select(a, b *projCached, cond int) *projCached { + v.YplusX.Select(&a.YplusX, &b.YplusX, cond) + v.YminusX.Select(&a.YminusX, &b.YminusX, cond) + v.Z.Select(&a.Z, &b.Z, cond) + v.T2d.Select(&a.T2d, &b.T2d, cond) + return v } -// Input: -// s[0]+256*s[1]+...+256^63*s[63] = s -// -// Output: -// s[0]+256*s[1]+...+256^31*s[31] = s mod l -// where l = 2^252 + 27742317777372353535851937790883648493. -func ScReduce(out *[32]byte, s *[64]byte) { - s0 := 2097151 & load3(s[:]) - s1 := 2097151 & (load4(s[2:]) >> 5) - s2 := 2097151 & (load3(s[5:]) >> 2) - s3 := 2097151 & (load4(s[7:]) >> 7) - s4 := 2097151 & (load4(s[10:]) >> 4) - s5 := 2097151 & (load3(s[13:]) >> 1) - s6 := 2097151 & (load4(s[15:]) >> 6) - s7 := 2097151 & (load3(s[18:]) >> 3) - s8 := 2097151 & load3(s[21:]) - s9 := 2097151 & (load4(s[23:]) >> 5) - s10 := 2097151 & (load3(s[26:]) >> 2) - s11 := 2097151 & (load4(s[28:]) >> 7) - s12 := 2097151 & (load4(s[31:]) >> 4) - s13 := 2097151 & (load3(s[34:]) >> 1) - s14 := 2097151 & (load4(s[36:]) >> 6) - s15 := 2097151 & (load3(s[39:]) >> 3) - s16 := 2097151 & load3(s[42:]) - s17 := 2097151 & (load4(s[44:]) >> 5) - s18 := 2097151 & (load3(s[47:]) >> 2) - s19 := 2097151 & (load4(s[49:]) >> 7) - s20 := 2097151 & (load4(s[52:]) >> 4) - s21 := 2097151 & (load3(s[55:]) >> 1) - s22 := 2097151 & (load4(s[57:]) >> 6) - s23 := (load4(s[60:]) >> 3) - - s11 += s23 * 666643 - s12 += s23 * 470296 - s13 += s23 * 654183 - s14 -= s23 * 997805 - s15 += s23 * 136657 - s16 -= s23 * 683901 - s23 = 0 - - s10 += s22 * 666643 - s11 += s22 * 470296 - s12 += s22 * 654183 - s13 -= s22 * 997805 - s14 += s22 * 136657 - s15 -= s22 * 683901 - s22 = 0 - - s9 += s21 * 666643 - s10 += s21 * 470296 - s11 += s21 * 654183 - s12 -= s21 * 997805 - s13 += s21 * 136657 - s14 -= s21 * 683901 - s21 = 0 - - s8 += s20 * 666643 - s9 += s20 * 470296 - s10 += s20 * 654183 - s11 -= s20 * 997805 - s12 += s20 * 136657 - s13 -= s20 * 683901 - s20 = 0 - - s7 += s19 * 666643 - s8 += s19 * 470296 - s9 += s19 * 654183 - s10 -= s19 * 997805 - s11 += s19 * 136657 - s12 -= s19 * 683901 - s19 = 0 - - s6 += s18 * 666643 - s7 += s18 * 470296 - s8 += s18 * 654183 - s9 -= s18 * 997805 - s10 += s18 * 136657 - s11 -= s18 * 683901 - s18 = 0 - - var carry [17]int64 - - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[12] = (s12 + (1 << 20)) >> 21 - s13 += carry[12] - s12 -= carry[12] << 21 - carry[14] = (s14 + (1 << 20)) >> 21 - s15 += carry[14] - s14 -= carry[14] << 21 - carry[16] = (s16 + (1 << 20)) >> 21 - s17 += carry[16] - s16 -= carry[16] << 21 - - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - carry[13] = (s13 + (1 << 20)) >> 21 - s14 += carry[13] - s13 -= carry[13] << 21 - carry[15] = (s15 + (1 << 20)) >> 21 - s16 += carry[15] - s15 -= carry[15] << 21 - - s5 += s17 * 666643 - s6 += s17 * 470296 - s7 += s17 * 654183 - s8 -= s17 * 997805 - s9 += s17 * 136657 - s10 -= s17 * 683901 - s17 = 0 - - s4 += s16 * 666643 - s5 += s16 * 470296 - s6 += s16 * 654183 - s7 -= s16 * 997805 - s8 += s16 * 136657 - s9 -= s16 * 683901 - s16 = 0 - - s3 += s15 * 666643 - s4 += s15 * 470296 - s5 += s15 * 654183 - s6 -= s15 * 997805 - s7 += s15 * 136657 - s8 -= s15 * 683901 - s15 = 0 - - s2 += s14 * 666643 - s3 += s14 * 470296 - s4 += s14 * 654183 - s5 -= s14 * 997805 - s6 += s14 * 136657 - s7 -= s14 * 683901 - s14 = 0 - - s1 += s13 * 666643 - s2 += s13 * 470296 - s3 += s13 * 654183 - s4 -= s13 * 997805 - s5 += s13 * 136657 - s6 -= s13 * 683901 - s13 = 0 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = (s0 + (1 << 20)) >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[2] = (s2 + (1 << 20)) >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[4] = (s4 + (1 << 20)) >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - - carry[1] = (s1 + (1 << 20)) >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[3] = (s3 + (1 << 20)) >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[5] = (s5 + (1 << 20)) >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = s0 >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[1] = s1 >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[2] = s2 >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[3] = s3 >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[4] = s4 >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[5] = s5 >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[6] = s6 >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[7] = s7 >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[8] = s8 >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[9] = s9 >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[10] = s10 >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[11] = s11 >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = s0 >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[1] = s1 >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[2] = s2 >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[3] = s3 >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[4] = s4 >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[5] = s5 >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[6] = s6 >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[7] = s7 >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[8] = s8 >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[9] = s9 >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[10] = s10 >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - - out[0] = byte(s0 >> 0) - out[1] = byte(s0 >> 8) - out[2] = byte((s0 >> 16) | (s1 << 5)) - out[3] = byte(s1 >> 3) - out[4] = byte(s1 >> 11) - out[5] = byte((s1 >> 19) | (s2 << 2)) - out[6] = byte(s2 >> 6) - out[7] = byte((s2 >> 14) | (s3 << 7)) - out[8] = byte(s3 >> 1) - out[9] = byte(s3 >> 9) - out[10] = byte((s3 >> 17) | (s4 << 4)) - out[11] = byte(s4 >> 4) - out[12] = byte(s4 >> 12) - out[13] = byte((s4 >> 20) | (s5 << 1)) - out[14] = byte(s5 >> 7) - out[15] = byte((s5 >> 15) | (s6 << 6)) - out[16] = byte(s6 >> 2) - out[17] = byte(s6 >> 10) - out[18] = byte((s6 >> 18) | (s7 << 3)) - out[19] = byte(s7 >> 5) - out[20] = byte(s7 >> 13) - out[21] = byte(s8 >> 0) - out[22] = byte(s8 >> 8) - out[23] = byte((s8 >> 16) | (s9 << 5)) - out[24] = byte(s9 >> 3) - out[25] = byte(s9 >> 11) - out[26] = byte((s9 >> 19) | (s10 << 2)) - out[27] = byte(s10 >> 6) - out[28] = byte((s10 >> 14) | (s11 << 7)) - out[29] = byte(s11 >> 1) - out[30] = byte(s11 >> 9) - out[31] = byte(s11 >> 17) +// Select sets v to a if cond == 1 and to b if cond == 0. +func (v *affineCached) Select(a, b *affineCached, cond int) *affineCached { + v.YplusX.Select(&a.YplusX, &b.YplusX, cond) + v.YminusX.Select(&a.YminusX, &b.YminusX, cond) + v.T2d.Select(&a.T2d, &b.T2d, cond) + return v } -// order is the order of Curve25519 in little-endian form. -var order = [4]uint64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0, 0x1000000000000000} - -// ScMinimal returns true if the given scalar is less than the order of the -// curve. -func ScMinimal(scalar *[32]byte) bool { - for i := 3; ; i-- { - v := binary.LittleEndian.Uint64(scalar[i*8:]) - if v > order[i] { - return false - } else if v < order[i] { - break - } else if i == 0 { - return false - } - } +// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0. +func (v *projCached) CondNeg(cond int) *projCached { + v.YplusX.Swap(&v.YminusX, cond) + v.T2d.Select(new(field.Element).Negate(&v.T2d), &v.T2d, cond) + return v +} - return true +// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0. +func (v *affineCached) CondNeg(cond int) *affineCached { + v.YplusX.Swap(&v.YminusX, cond) + v.T2d.Select(new(field.Element).Negate(&v.T2d), &v.T2d, cond) + return v } diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/edwards25519_test.go b/libgo/go/crypto/ed25519/internal/edwards25519/edwards25519_test.go new file mode 100644 index 0000000..7b01920 --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/edwards25519_test.go @@ -0,0 +1,308 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "crypto/ed25519/internal/edwards25519/field" + "encoding/hex" + "os" + "reflect" + "runtime" + "strings" + "testing" +) + +var B = NewGeneratorPoint() +var I = NewIdentityPoint() + +func checkOnCurve(t *testing.T, points ...*Point) { + t.Helper() + for i, p := range points { + var XX, YY, ZZ, ZZZZ field.Element + XX.Square(&p.x) + YY.Square(&p.y) + ZZ.Square(&p.z) + ZZZZ.Square(&ZZ) + // -x² + y² = 1 + dx²y² + // -(X/Z)² + (Y/Z)² = 1 + d(X/Z)²(Y/Z)² + // (-X² + Y²)/Z² = 1 + (dX²Y²)/Z⁴ + // (-X² + Y²)*Z² = Z⁴ + dX²Y² + var lhs, rhs field.Element + lhs.Subtract(&YY, &XX).Multiply(&lhs, &ZZ) + rhs.Multiply(d, &XX).Multiply(&rhs, &YY).Add(&rhs, &ZZZZ) + if lhs.Equal(&rhs) != 1 { + t.Errorf("X, Y, and Z do not specify a point on the curve\nX = %v\nY = %v\nZ = %v", p.x, p.y, p.z) + } + // xy = T/Z + lhs.Multiply(&p.x, &p.y) + rhs.Multiply(&p.z, &p.t) + if lhs.Equal(&rhs) != 1 { + t.Errorf("point %d is not valid\nX = %v\nY = %v\nZ = %v", i, p.x, p.y, p.z) + } + } +} + +func TestGenerator(t *testing.T) { + // These are the coordinates of B from RFC 8032, Section 5.1, converted to + // little endian hex. + x := "1ad5258f602d56c9b2a7259560c72c695cdcd6fd31e2a4c0fe536ecdd3366921" + y := "5866666666666666666666666666666666666666666666666666666666666666" + if got := hex.EncodeToString(B.x.Bytes()); got != x { + t.Errorf("wrong B.x: got %s, expected %s", got, x) + } + if got := hex.EncodeToString(B.y.Bytes()); got != y { + t.Errorf("wrong B.y: got %s, expected %s", got, y) + } + if B.z.Equal(feOne) != 1 { + t.Errorf("wrong B.z: got %v, expected 1", B.z) + } + // Check that t is correct. + checkOnCurve(t, B) +} + +func TestAddSubNegOnBasePoint(t *testing.T) { + checkLhs, checkRhs := &Point{}, &Point{} + + checkLhs.Add(B, B) + tmpP2 := new(projP2).FromP3(B) + tmpP1xP1 := new(projP1xP1).Double(tmpP2) + checkRhs.fromP1xP1(tmpP1xP1) + if checkLhs.Equal(checkRhs) != 1 { + t.Error("B + B != [2]B") + } + checkOnCurve(t, checkLhs, checkRhs) + + checkLhs.Subtract(B, B) + Bneg := new(Point).Negate(B) + checkRhs.Add(B, Bneg) + if checkLhs.Equal(checkRhs) != 1 { + t.Error("B - B != B + (-B)") + } + if I.Equal(checkLhs) != 1 { + t.Error("B - B != 0") + } + if I.Equal(checkRhs) != 1 { + t.Error("B + (-B) != 0") + } + checkOnCurve(t, checkLhs, checkRhs, Bneg) +} + +func TestComparable(t *testing.T) { + if reflect.TypeOf(Point{}).Comparable() { + t.Error("Point is unexpectedly comparable") + } +} + +func TestInvalidEncodings(t *testing.T) { + // An invalid point, that also happens to have y > p. + invalid := "efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f" + p := NewGeneratorPoint() + if out, err := p.SetBytes(decodeHex(invalid)); err == nil { + t.Error("expected error for invalid point") + } else if out != nil { + t.Error("SetBytes did not return nil on an invalid encoding") + } else if p.Equal(B) != 1 { + t.Error("the Point was modified while decoding an invalid encoding") + } + checkOnCurve(t, p) +} + +func TestNonCanonicalPoints(t *testing.T) { + type test struct { + name string + encoding, canonical string + } + tests := []test{ + // Points with x = 0 and the sign bit set. With x = 0 the curve equation + // gives y² = 1, so y = ±1. 1 has two valid encodings. + { + "y=1,sign-", + "0100000000000000000000000000000000000000000000000000000000000080", + "0100000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+1,sign-", + "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0100000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p-1,sign-", + "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + }, + + // Non-canonical y encodings with values 2²⁵⁵-19 (p) to 2²⁵⁵-1 (p+18). + { + "y=p,sign+", + "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0000000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p,sign-", + "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0000000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+1,sign+", + "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0100000000000000000000000000000000000000000000000000000000000000", + }, + // "y=p+1,sign-" is already tested above. + // p+2 is not a valid y-coordinate. + { + "y=p+3,sign+", + "f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0300000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+3,sign-", + "f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0300000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+4,sign+", + "f1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0400000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+4,sign-", + "f1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0400000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+5,sign+", + "f2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0500000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+5,sign-", + "f2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0500000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+6,sign+", + "f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0600000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+6,sign-", + "f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0600000000000000000000000000000000000000000000000000000000000080", + }, + // p+7 is not a valid y-coordinate. + // p+8 is not a valid y-coordinate. + { + "y=p+9,sign+", + "f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0900000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+9,sign-", + "f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0900000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+10,sign+", + "f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0a00000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+10,sign-", + "f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0a00000000000000000000000000000000000000000000000000000000000080", + }, + // p+11 is not a valid y-coordinate. + // p+12 is not a valid y-coordinate. + // p+13 is not a valid y-coordinate. + { + "y=p+14,sign+", + "fbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0e00000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+14,sign-", + "fbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0e00000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+15,sign+", + "fcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0f00000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+15,sign-", + "fcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0f00000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+16,sign+", + "fdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "1000000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+16,sign-", + "fdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "1000000000000000000000000000000000000000000000000000000000000080", + }, + // p+17 is not a valid y-coordinate. + { + "y=p+18,sign+", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "1200000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+18,sign-", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "1200000000000000000000000000000000000000000000000000000000000080", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p1, err := new(Point).SetBytes(decodeHex(tt.encoding)) + if err != nil { + t.Fatalf("error decoding non-canonical point: %v", err) + } + p2, err := new(Point).SetBytes(decodeHex(tt.canonical)) + if err != nil { + t.Fatalf("error decoding canonical point: %v", err) + } + if p1.Equal(p2) != 1 { + t.Errorf("equivalent points are not equal: %v, %v", p1, p2) + } + if encoding := hex.EncodeToString(p1.Bytes()); encoding != tt.canonical { + t.Errorf("re-encoding does not match canonical; got %q, expected %q", encoding, tt.canonical) + } + checkOnCurve(t, p1, p2) + }) + } +} + +var testAllocationsSink byte + +func TestAllocations(t *testing.T) { + if runtime.Compiler == "gccgo" { + t.Skip("gofronted escape analysis not good enough") + } + if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") { + t.Skip("skipping allocations test without relevant optimizations") + } + if allocs := testing.AllocsPerRun(100, func() { + p := NewIdentityPoint() + p.Add(p, NewGeneratorPoint()) + s := NewScalar() + testAllocationsSink ^= s.Bytes()[0] + testAllocationsSink ^= p.Bytes()[0] + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1v", allocs) + } +} + +func decodeHex(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b +} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/_asm/fe_amd64_asm.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/_asm/fe_amd64_asm.go new file mode 100644 index 0000000..fbc0cce --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/field/_asm/fe_amd64_asm.go @@ -0,0 +1,294 @@ +// Copyright (c) 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + + . "github.com/mmcloughlin/avo/build" + . "github.com/mmcloughlin/avo/gotypes" + . "github.com/mmcloughlin/avo/operand" + . "github.com/mmcloughlin/avo/reg" +) + +//go:generate go run . -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field + +func main() { + Package("crypto/ed25519/internal/edwards25519/field") + ConstraintExpr("amd64,gc,!purego") + feMul() + feSquare() + Generate() +} + +type namedComponent struct { + Component + name string +} + +func (c namedComponent) String() string { return c.name } + +type uint128 struct { + name string + hi, lo GPVirtual +} + +func (c uint128) String() string { return c.name } + +func feSquare() { + TEXT("feSquare", NOSPLIT, "func(out, a *Element)") + Doc("feSquare sets out = a * a. It works like feSquareGeneric.") + Pragma("noescape") + + a := Dereference(Param("a")) + l0 := namedComponent{a.Field("l0"), "l0"} + l1 := namedComponent{a.Field("l1"), "l1"} + l2 := namedComponent{a.Field("l2"), "l2"} + l3 := namedComponent{a.Field("l3"), "l3"} + l4 := namedComponent{a.Field("l4"), "l4"} + + // r0 = l0×l0 + 19×2×(l1×l4 + l2×l3) + r0 := uint128{"r0", GP64(), GP64()} + mul64(r0, 1, l0, l0) + addMul64(r0, 38, l1, l4) + addMul64(r0, 38, l2, l3) + + // r1 = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3 + r1 := uint128{"r1", GP64(), GP64()} + mul64(r1, 2, l0, l1) + addMul64(r1, 38, l2, l4) + addMul64(r1, 19, l3, l3) + + // r2 = = 2×l0×l2 + l1×l1 + 19×2×l3×l4 + r2 := uint128{"r2", GP64(), GP64()} + mul64(r2, 2, l0, l2) + addMul64(r2, 1, l1, l1) + addMul64(r2, 38, l3, l4) + + // r3 = = 2×l0×l3 + 2×l1×l2 + 19×l4×l4 + r3 := uint128{"r3", GP64(), GP64()} + mul64(r3, 2, l0, l3) + addMul64(r3, 2, l1, l2) + addMul64(r3, 19, l4, l4) + + // r4 = = 2×l0×l4 + 2×l1×l3 + l2×l2 + r4 := uint128{"r4", GP64(), GP64()} + mul64(r4, 2, l0, l4) + addMul64(r4, 2, l1, l3) + addMul64(r4, 1, l2, l2) + + Comment("First reduction chain") + maskLow51Bits := GP64() + MOVQ(Imm((1<<51)-1), maskLow51Bits) + c0, r0lo := shiftRightBy51(&r0) + c1, r1lo := shiftRightBy51(&r1) + c2, r2lo := shiftRightBy51(&r2) + c3, r3lo := shiftRightBy51(&r3) + c4, r4lo := shiftRightBy51(&r4) + maskAndAdd(r0lo, maskLow51Bits, c4, 19) + maskAndAdd(r1lo, maskLow51Bits, c0, 1) + maskAndAdd(r2lo, maskLow51Bits, c1, 1) + maskAndAdd(r3lo, maskLow51Bits, c2, 1) + maskAndAdd(r4lo, maskLow51Bits, c3, 1) + + Comment("Second reduction chain (carryPropagate)") + // c0 = r0 >> 51 + MOVQ(r0lo, c0) + SHRQ(Imm(51), c0) + // c1 = r1 >> 51 + MOVQ(r1lo, c1) + SHRQ(Imm(51), c1) + // c2 = r2 >> 51 + MOVQ(r2lo, c2) + SHRQ(Imm(51), c2) + // c3 = r3 >> 51 + MOVQ(r3lo, c3) + SHRQ(Imm(51), c3) + // c4 = r4 >> 51 + MOVQ(r4lo, c4) + SHRQ(Imm(51), c4) + maskAndAdd(r0lo, maskLow51Bits, c4, 19) + maskAndAdd(r1lo, maskLow51Bits, c0, 1) + maskAndAdd(r2lo, maskLow51Bits, c1, 1) + maskAndAdd(r3lo, maskLow51Bits, c2, 1) + maskAndAdd(r4lo, maskLow51Bits, c3, 1) + + Comment("Store output") + out := Dereference(Param("out")) + Store(r0lo, out.Field("l0")) + Store(r1lo, out.Field("l1")) + Store(r2lo, out.Field("l2")) + Store(r3lo, out.Field("l3")) + Store(r4lo, out.Field("l4")) + + RET() +} + +func feMul() { + TEXT("feMul", NOSPLIT, "func(out, a, b *Element)") + Doc("feMul sets out = a * b. It works like feMulGeneric.") + Pragma("noescape") + + a := Dereference(Param("a")) + a0 := namedComponent{a.Field("l0"), "a0"} + a1 := namedComponent{a.Field("l1"), "a1"} + a2 := namedComponent{a.Field("l2"), "a2"} + a3 := namedComponent{a.Field("l3"), "a3"} + a4 := namedComponent{a.Field("l4"), "a4"} + + b := Dereference(Param("b")) + b0 := namedComponent{b.Field("l0"), "b0"} + b1 := namedComponent{b.Field("l1"), "b1"} + b2 := namedComponent{b.Field("l2"), "b2"} + b3 := namedComponent{b.Field("l3"), "b3"} + b4 := namedComponent{b.Field("l4"), "b4"} + + // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) + r0 := uint128{"r0", GP64(), GP64()} + mul64(r0, 1, a0, b0) + addMul64(r0, 19, a1, b4) + addMul64(r0, 19, a2, b3) + addMul64(r0, 19, a3, b2) + addMul64(r0, 19, a4, b1) + + // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2) + r1 := uint128{"r1", GP64(), GP64()} + mul64(r1, 1, a0, b1) + addMul64(r1, 1, a1, b0) + addMul64(r1, 19, a2, b4) + addMul64(r1, 19, a3, b3) + addMul64(r1, 19, a4, b2) + + // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3) + r2 := uint128{"r2", GP64(), GP64()} + mul64(r2, 1, a0, b2) + addMul64(r2, 1, a1, b1) + addMul64(r2, 1, a2, b0) + addMul64(r2, 19, a3, b4) + addMul64(r2, 19, a4, b3) + + // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4 + r3 := uint128{"r3", GP64(), GP64()} + mul64(r3, 1, a0, b3) + addMul64(r3, 1, a1, b2) + addMul64(r3, 1, a2, b1) + addMul64(r3, 1, a3, b0) + addMul64(r3, 19, a4, b4) + + // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 + r4 := uint128{"r4", GP64(), GP64()} + mul64(r4, 1, a0, b4) + addMul64(r4, 1, a1, b3) + addMul64(r4, 1, a2, b2) + addMul64(r4, 1, a3, b1) + addMul64(r4, 1, a4, b0) + + Comment("First reduction chain") + maskLow51Bits := GP64() + MOVQ(Imm((1<<51)-1), maskLow51Bits) + c0, r0lo := shiftRightBy51(&r0) + c1, r1lo := shiftRightBy51(&r1) + c2, r2lo := shiftRightBy51(&r2) + c3, r3lo := shiftRightBy51(&r3) + c4, r4lo := shiftRightBy51(&r4) + maskAndAdd(r0lo, maskLow51Bits, c4, 19) + maskAndAdd(r1lo, maskLow51Bits, c0, 1) + maskAndAdd(r2lo, maskLow51Bits, c1, 1) + maskAndAdd(r3lo, maskLow51Bits, c2, 1) + maskAndAdd(r4lo, maskLow51Bits, c3, 1) + + Comment("Second reduction chain (carryPropagate)") + // c0 = r0 >> 51 + MOVQ(r0lo, c0) + SHRQ(Imm(51), c0) + // c1 = r1 >> 51 + MOVQ(r1lo, c1) + SHRQ(Imm(51), c1) + // c2 = r2 >> 51 + MOVQ(r2lo, c2) + SHRQ(Imm(51), c2) + // c3 = r3 >> 51 + MOVQ(r3lo, c3) + SHRQ(Imm(51), c3) + // c4 = r4 >> 51 + MOVQ(r4lo, c4) + SHRQ(Imm(51), c4) + maskAndAdd(r0lo, maskLow51Bits, c4, 19) + maskAndAdd(r1lo, maskLow51Bits, c0, 1) + maskAndAdd(r2lo, maskLow51Bits, c1, 1) + maskAndAdd(r3lo, maskLow51Bits, c2, 1) + maskAndAdd(r4lo, maskLow51Bits, c3, 1) + + Comment("Store output") + out := Dereference(Param("out")) + Store(r0lo, out.Field("l0")) + Store(r1lo, out.Field("l1")) + Store(r2lo, out.Field("l2")) + Store(r3lo, out.Field("l3")) + Store(r4lo, out.Field("l4")) + + RET() +} + +// mul64 sets r to i * aX * bX. +func mul64(r uint128, i int, aX, bX namedComponent) { + switch i { + case 1: + Comment(fmt.Sprintf("%s = %s×%s", r, aX, bX)) + Load(aX, RAX) + case 2: + Comment(fmt.Sprintf("%s = 2×%s×%s", r, aX, bX)) + Load(aX, RAX) + SHLQ(Imm(1), RAX) + default: + panic("unsupported i value") + } + MULQ(mustAddr(bX)) // RDX, RAX = RAX * bX + MOVQ(RAX, r.lo) + MOVQ(RDX, r.hi) +} + +// addMul64 sets r to r + i * aX * bX. +func addMul64(r uint128, i uint64, aX, bX namedComponent) { + switch i { + case 1: + Comment(fmt.Sprintf("%s += %s×%s", r, aX, bX)) + Load(aX, RAX) + default: + Comment(fmt.Sprintf("%s += %d×%s×%s", r, i, aX, bX)) + IMUL3Q(Imm(i), Load(aX, GP64()), RAX) + } + MULQ(mustAddr(bX)) // RDX, RAX = RAX * bX + ADDQ(RAX, r.lo) + ADCQ(RDX, r.hi) +} + +// shiftRightBy51 returns r >> 51 and r.lo. +// +// After this function is called, the uint128 may not be used anymore. +func shiftRightBy51(r *uint128) (out, lo GPVirtual) { + out = r.hi + lo = r.lo + SHLQ(Imm(64-51), r.lo, r.hi) + r.lo, r.hi = nil, nil // make sure the uint128 is unusable + return +} + +// maskAndAdd sets r = r&mask + c*i. +func maskAndAdd(r, mask, c GPVirtual, i uint64) { + ANDQ(mask, r) + if i != 1 { + IMUL3Q(Imm(i), c, c) + } + ADDQ(c, r) +} + +func mustAddr(c Component) Op { + b, err := c.Resolve() + if err != nil { + panic(err) + } + return b.Addr +} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/_asm/go.mod b/libgo/go/crypto/ed25519/internal/edwards25519/field/_asm/go.mod new file mode 100644 index 0000000..1127ade --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/field/_asm/go.mod @@ -0,0 +1,5 @@ +module asm + +go 1.16 + +require github.com/mmcloughlin/avo v0.2.0 diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe.go new file mode 100644 index 0000000..dbe8659 --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe.go @@ -0,0 +1,416 @@ +// Copyright (c) 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package field implements fast arithmetic modulo 2^255-19. +package field + +import ( + "crypto/subtle" + "encoding/binary" + "math/bits" +) + +// Element represents an element of the field GF(2^255-19). Note that this +// is not a cryptographically secure group, and should only be used to interact +// with edwards25519.Point coordinates. +// +// This type works similarly to math/big.Int, and all arguments and receivers +// are allowed to alias. +// +// The zero value is a valid zero element. +type Element struct { + // An element t represents the integer + // t.l0 + t.l1*2^51 + t.l2*2^102 + t.l3*2^153 + t.l4*2^204 + // + // Between operations, all limbs are expected to be lower than 2^52. + l0 uint64 + l1 uint64 + l2 uint64 + l3 uint64 + l4 uint64 +} + +const maskLow51Bits uint64 = (1 << 51) - 1 + +var feZero = &Element{0, 0, 0, 0, 0} + +// Zero sets v = 0, and returns v. +func (v *Element) Zero() *Element { + *v = *feZero + return v +} + +var feOne = &Element{1, 0, 0, 0, 0} + +// One sets v = 1, and returns v. +func (v *Element) One() *Element { + *v = *feOne + return v +} + +// reduce reduces v modulo 2^255 - 19 and returns it. +func (v *Element) reduce() *Element { + v.carryPropagate() + + // After the light reduction we now have a field element representation + // v < 2^255 + 2^13 * 19, but need v < 2^255 - 19. + + // If v >= 2^255 - 19, then v + 19 >= 2^255, which would overflow 2^255 - 1, + // generating a carry. That is, c will be 0 if v < 2^255 - 19, and 1 otherwise. + c := (v.l0 + 19) >> 51 + c = (v.l1 + c) >> 51 + c = (v.l2 + c) >> 51 + c = (v.l3 + c) >> 51 + c = (v.l4 + c) >> 51 + + // If v < 2^255 - 19 and c = 0, this will be a no-op. Otherwise, it's + // effectively applying the reduction identity to the carry. + v.l0 += 19 * c + + v.l1 += v.l0 >> 51 + v.l0 = v.l0 & maskLow51Bits + v.l2 += v.l1 >> 51 + v.l1 = v.l1 & maskLow51Bits + v.l3 += v.l2 >> 51 + v.l2 = v.l2 & maskLow51Bits + v.l4 += v.l3 >> 51 + v.l3 = v.l3 & maskLow51Bits + // no additional carry + v.l4 = v.l4 & maskLow51Bits + + return v +} + +// Add sets v = a + b, and returns v. +func (v *Element) Add(a, b *Element) *Element { + v.l0 = a.l0 + b.l0 + v.l1 = a.l1 + b.l1 + v.l2 = a.l2 + b.l2 + v.l3 = a.l3 + b.l3 + v.l4 = a.l4 + b.l4 + // Using the generic implementation here is actually faster than the + // assembly. Probably because the body of this function is so simple that + // the compiler can figure out better optimizations by inlining the carry + // propagation. + return v.carryPropagateGeneric() +} + +// Subtract sets v = a - b, and returns v. +func (v *Element) Subtract(a, b *Element) *Element { + // We first add 2 * p, to guarantee the subtraction won't underflow, and + // then subtract b (which can be up to 2^255 + 2^13 * 19). + v.l0 = (a.l0 + 0xFFFFFFFFFFFDA) - b.l0 + v.l1 = (a.l1 + 0xFFFFFFFFFFFFE) - b.l1 + v.l2 = (a.l2 + 0xFFFFFFFFFFFFE) - b.l2 + v.l3 = (a.l3 + 0xFFFFFFFFFFFFE) - b.l3 + v.l4 = (a.l4 + 0xFFFFFFFFFFFFE) - b.l4 + return v.carryPropagate() +} + +// Negate sets v = -a, and returns v. +func (v *Element) Negate(a *Element) *Element { + return v.Subtract(feZero, a) +} + +// Invert sets v = 1/z mod p, and returns v. +// +// If z == 0, Invert returns v = 0. +func (v *Element) Invert(z *Element) *Element { + // Inversion is implemented as exponentiation with exponent p − 2. It uses the + // same sequence of 255 squarings and 11 multiplications as [Curve25519]. + var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t Element + + z2.Square(z) // 2 + t.Square(&z2) // 4 + t.Square(&t) // 8 + z9.Multiply(&t, z) // 9 + z11.Multiply(&z9, &z2) // 11 + t.Square(&z11) // 22 + z2_5_0.Multiply(&t, &z9) // 31 = 2^5 - 2^0 + + t.Square(&z2_5_0) // 2^6 - 2^1 + for i := 0; i < 4; i++ { + t.Square(&t) // 2^10 - 2^5 + } + z2_10_0.Multiply(&t, &z2_5_0) // 2^10 - 2^0 + + t.Square(&z2_10_0) // 2^11 - 2^1 + for i := 0; i < 9; i++ { + t.Square(&t) // 2^20 - 2^10 + } + z2_20_0.Multiply(&t, &z2_10_0) // 2^20 - 2^0 + + t.Square(&z2_20_0) // 2^21 - 2^1 + for i := 0; i < 19; i++ { + t.Square(&t) // 2^40 - 2^20 + } + t.Multiply(&t, &z2_20_0) // 2^40 - 2^0 + + t.Square(&t) // 2^41 - 2^1 + for i := 0; i < 9; i++ { + t.Square(&t) // 2^50 - 2^10 + } + z2_50_0.Multiply(&t, &z2_10_0) // 2^50 - 2^0 + + t.Square(&z2_50_0) // 2^51 - 2^1 + for i := 0; i < 49; i++ { + t.Square(&t) // 2^100 - 2^50 + } + z2_100_0.Multiply(&t, &z2_50_0) // 2^100 - 2^0 + + t.Square(&z2_100_0) // 2^101 - 2^1 + for i := 0; i < 99; i++ { + t.Square(&t) // 2^200 - 2^100 + } + t.Multiply(&t, &z2_100_0) // 2^200 - 2^0 + + t.Square(&t) // 2^201 - 2^1 + for i := 0; i < 49; i++ { + t.Square(&t) // 2^250 - 2^50 + } + t.Multiply(&t, &z2_50_0) // 2^250 - 2^0 + + t.Square(&t) // 2^251 - 2^1 + t.Square(&t) // 2^252 - 2^2 + t.Square(&t) // 2^253 - 2^3 + t.Square(&t) // 2^254 - 2^4 + t.Square(&t) // 2^255 - 2^5 + + return v.Multiply(&t, &z11) // 2^255 - 21 +} + +// Set sets v = a, and returns v. +func (v *Element) Set(a *Element) *Element { + *v = *a + return v +} + +// SetBytes sets v to x, which must be a 32-byte little-endian encoding. +// +// Consistent with RFC 7748, the most significant bit (the high bit of the +// last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1) +// are accepted. Note that this is laxer than specified by RFC 8032. +func (v *Element) SetBytes(x []byte) *Element { + if len(x) != 32 { + panic("edwards25519: invalid field element input size") + } + + // Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51). + v.l0 = binary.LittleEndian.Uint64(x[0:8]) + v.l0 &= maskLow51Bits + // Bits 51:102 (bytes 6:14, bits 48:112, shift 3, mask 51). + v.l1 = binary.LittleEndian.Uint64(x[6:14]) >> 3 + v.l1 &= maskLow51Bits + // Bits 102:153 (bytes 12:20, bits 96:160, shift 6, mask 51). + v.l2 = binary.LittleEndian.Uint64(x[12:20]) >> 6 + v.l2 &= maskLow51Bits + // Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51). + v.l3 = binary.LittleEndian.Uint64(x[19:27]) >> 1 + v.l3 &= maskLow51Bits + // Bits 204:251 (bytes 24:32, bits 192:256, shift 12, mask 51). + // Note: not bytes 25:33, shift 4, to avoid overread. + v.l4 = binary.LittleEndian.Uint64(x[24:32]) >> 12 + v.l4 &= maskLow51Bits + + return v +} + +// Bytes returns the canonical 32-byte little-endian encoding of v. +func (v *Element) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var out [32]byte + return v.bytes(&out) +} + +func (v *Element) bytes(out *[32]byte) []byte { + t := *v + t.reduce() + + var buf [8]byte + for i, l := range [5]uint64{t.l0, t.l1, t.l2, t.l3, t.l4} { + bitsOffset := i * 51 + binary.LittleEndian.PutUint64(buf[:], l<<uint(bitsOffset%8)) + for i, bb := range buf { + off := bitsOffset/8 + i + if off >= len(out) { + break + } + out[off] |= bb + } + } + + return out[:] +} + +// Equal returns 1 if v and u are equal, and 0 otherwise. +func (v *Element) Equal(u *Element) int { + sa, sv := u.Bytes(), v.Bytes() + return subtle.ConstantTimeCompare(sa, sv) +} + +// mask64Bits returns 0xffffffff if cond is 1, and 0 otherwise. +func mask64Bits(cond int) uint64 { return ^(uint64(cond) - 1) } + +// Select sets v to a if cond == 1, and to b if cond == 0. +func (v *Element) Select(a, b *Element, cond int) *Element { + m := mask64Bits(cond) + v.l0 = (m & a.l0) | (^m & b.l0) + v.l1 = (m & a.l1) | (^m & b.l1) + v.l2 = (m & a.l2) | (^m & b.l2) + v.l3 = (m & a.l3) | (^m & b.l3) + v.l4 = (m & a.l4) | (^m & b.l4) + return v +} + +// Swap swaps v and u if cond == 1 or leaves them unchanged if cond == 0, and returns v. +func (v *Element) Swap(u *Element, cond int) { + m := mask64Bits(cond) + t := m & (v.l0 ^ u.l0) + v.l0 ^= t + u.l0 ^= t + t = m & (v.l1 ^ u.l1) + v.l1 ^= t + u.l1 ^= t + t = m & (v.l2 ^ u.l2) + v.l2 ^= t + u.l2 ^= t + t = m & (v.l3 ^ u.l3) + v.l3 ^= t + u.l3 ^= t + t = m & (v.l4 ^ u.l4) + v.l4 ^= t + u.l4 ^= t +} + +// IsNegative returns 1 if v is negative, and 0 otherwise. +func (v *Element) IsNegative() int { + return int(v.Bytes()[0] & 1) +} + +// Absolute sets v to |u|, and returns v. +func (v *Element) Absolute(u *Element) *Element { + return v.Select(new(Element).Negate(u), u, u.IsNegative()) +} + +// Multiply sets v = x * y, and returns v. +func (v *Element) Multiply(x, y *Element) *Element { + feMul(v, x, y) + return v +} + +// Square sets v = x * x, and returns v. +func (v *Element) Square(x *Element) *Element { + feSquare(v, x) + return v +} + +// Mult32 sets v = x * y, and returns v. +func (v *Element) Mult32(x *Element, y uint32) *Element { + x0lo, x0hi := mul51(x.l0, y) + x1lo, x1hi := mul51(x.l1, y) + x2lo, x2hi := mul51(x.l2, y) + x3lo, x3hi := mul51(x.l3, y) + x4lo, x4hi := mul51(x.l4, y) + v.l0 = x0lo + 19*x4hi // carried over per the reduction identity + v.l1 = x1lo + x0hi + v.l2 = x2lo + x1hi + v.l3 = x3lo + x2hi + v.l4 = x4lo + x3hi + // The hi portions are going to be only 32 bits, plus any previous excess, + // so we can skip the carry propagation. + return v +} + +// mul51 returns lo + hi * 2⁵¹ = a * b. +func mul51(a uint64, b uint32) (lo uint64, hi uint64) { + mh, ml := bits.Mul64(a, uint64(b)) + lo = ml & maskLow51Bits + hi = (mh << 13) | (ml >> 51) + return +} + +// Pow22523 set v = x^((p-5)/8), and returns v. (p-5)/8 is 2^252-3. +func (v *Element) Pow22523(x *Element) *Element { + var t0, t1, t2 Element + + t0.Square(x) // x^2 + t1.Square(&t0) // x^4 + t1.Square(&t1) // x^8 + t1.Multiply(x, &t1) // x^9 + t0.Multiply(&t0, &t1) // x^11 + t0.Square(&t0) // x^22 + t0.Multiply(&t1, &t0) // x^31 + t1.Square(&t0) // x^62 + for i := 1; i < 5; i++ { // x^992 + t1.Square(&t1) + } + t0.Multiply(&t1, &t0) // x^1023 -> 1023 = 2^10 - 1 + t1.Square(&t0) // 2^11 - 2 + for i := 1; i < 10; i++ { // 2^20 - 2^10 + t1.Square(&t1) + } + t1.Multiply(&t1, &t0) // 2^20 - 1 + t2.Square(&t1) // 2^21 - 2 + for i := 1; i < 20; i++ { // 2^40 - 2^20 + t2.Square(&t2) + } + t1.Multiply(&t2, &t1) // 2^40 - 1 + t1.Square(&t1) // 2^41 - 2 + for i := 1; i < 10; i++ { // 2^50 - 2^10 + t1.Square(&t1) + } + t0.Multiply(&t1, &t0) // 2^50 - 1 + t1.Square(&t0) // 2^51 - 2 + for i := 1; i < 50; i++ { // 2^100 - 2^50 + t1.Square(&t1) + } + t1.Multiply(&t1, &t0) // 2^100 - 1 + t2.Square(&t1) // 2^101 - 2 + for i := 1; i < 100; i++ { // 2^200 - 2^100 + t2.Square(&t2) + } + t1.Multiply(&t2, &t1) // 2^200 - 1 + t1.Square(&t1) // 2^201 - 2 + for i := 1; i < 50; i++ { // 2^250 - 2^50 + t1.Square(&t1) + } + t0.Multiply(&t1, &t0) // 2^250 - 1 + t0.Square(&t0) // 2^251 - 2 + t0.Square(&t0) // 2^252 - 4 + return v.Multiply(&t0, x) // 2^252 - 3 -> x^(2^252-3) +} + +// sqrtM1 is 2^((p-1)/4), which squared is equal to -1 by Euler's Criterion. +var sqrtM1 = &Element{1718705420411056, 234908883556509, + 2233514472574048, 2117202627021982, 765476049583133} + +// SqrtRatio sets r to the non-negative square root of the ratio of u and v. +// +// If u/v is square, SqrtRatio returns r and 1. If u/v is not square, SqrtRatio +// sets r according to Section 4.3 of draft-irtf-cfrg-ristretto255-decaf448-00, +// and returns r and 0. +func (r *Element) SqrtRatio(u, v *Element) (rr *Element, wasSquare int) { + var a, b Element + + // r = (u * v3) * (u * v7)^((p-5)/8) + v2 := a.Square(v) + uv3 := b.Multiply(u, b.Multiply(v2, v)) + uv7 := a.Multiply(uv3, a.Square(v2)) + r.Multiply(uv3, r.Pow22523(uv7)) + + check := a.Multiply(v, a.Square(r)) // check = v * r^2 + + uNeg := b.Negate(u) + correctSignSqrt := check.Equal(u) + flippedSignSqrt := check.Equal(uNeg) + flippedSignSqrtI := check.Equal(uNeg.Multiply(uNeg, sqrtM1)) + + rPrime := b.Multiply(r, sqrtM1) // r_prime = SQRT_M1 * r + // r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r) + r.Select(rPrime, r, flippedSignSqrt|flippedSignSqrtI) + + r.Absolute(r) // Choose the nonnegative square root. + return r, correctSignSqrt | flippedSignSqrt +} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_alias_test.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_alias_test.go new file mode 100644 index 0000000..5ad81df0 --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_alias_test.go @@ -0,0 +1,126 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package field + +import ( + "testing" + "testing/quick" +) + +func checkAliasingOneArg(f func(v, x *Element) *Element) func(v, x Element) bool { + return func(v, x Element) bool { + x1, v1 := x, x + + // Calculate a reference f(x) without aliasing. + if out := f(&v, &x); out != &v && isInBounds(out) { + return false + } + + // Test aliasing the argument and the receiver. + if out := f(&v1, &v1); out != &v1 || v1 != v { + return false + } + + // Ensure the arguments was not modified. + return x == x1 + } +} + +func checkAliasingTwoArgs(f func(v, x, y *Element) *Element) func(v, x, y Element) bool { + return func(v, x, y Element) bool { + x1, y1, v1 := x, y, Element{} + + // Calculate a reference f(x, y) without aliasing. + if out := f(&v, &x, &y); out != &v && isInBounds(out) { + return false + } + + // Test aliasing the first argument and the receiver. + v1 = x + if out := f(&v1, &v1, &y); out != &v1 || v1 != v { + return false + } + // Test aliasing the second argument and the receiver. + v1 = y + if out := f(&v1, &x, &v1); out != &v1 || v1 != v { + return false + } + + // Calculate a reference f(x, x) without aliasing. + if out := f(&v, &x, &x); out != &v { + return false + } + + // Test aliasing the first argument and the receiver. + v1 = x + if out := f(&v1, &v1, &x); out != &v1 || v1 != v { + return false + } + // Test aliasing the second argument and the receiver. + v1 = x + if out := f(&v1, &x, &v1); out != &v1 || v1 != v { + return false + } + // Test aliasing both arguments and the receiver. + v1 = x + if out := f(&v1, &v1, &v1); out != &v1 || v1 != v { + return false + } + + // Ensure the arguments were not modified. + return x == x1 && y == y1 + } +} + +// TestAliasing checks that receivers and arguments can alias each other without +// leading to incorrect results. That is, it ensures that it's safe to write +// +// v.Invert(v) +// +// or +// +// v.Add(v, v) +// +// without any of the inputs getting clobbered by the output being written. +func TestAliasing(t *testing.T) { + type target struct { + name string + oneArgF func(v, x *Element) *Element + twoArgsF func(v, x, y *Element) *Element + } + for _, tt := range []target{ + {name: "Absolute", oneArgF: (*Element).Absolute}, + {name: "Invert", oneArgF: (*Element).Invert}, + {name: "Negate", oneArgF: (*Element).Negate}, + {name: "Set", oneArgF: (*Element).Set}, + {name: "Square", oneArgF: (*Element).Square}, + {name: "Multiply", twoArgsF: (*Element).Multiply}, + {name: "Add", twoArgsF: (*Element).Add}, + {name: "Subtract", twoArgsF: (*Element).Subtract}, + { + name: "Select0", + twoArgsF: func(v, x, y *Element) *Element { + return (*Element).Select(v, x, y, 0) + }, + }, + { + name: "Select1", + twoArgsF: func(v, x, y *Element) *Element { + return (*Element).Select(v, x, y, 1) + }, + }, + } { + var err error + switch { + case tt.oneArgF != nil: + err = quick.Check(checkAliasingOneArg(tt.oneArgF), &quick.Config{MaxCountScale: 1 << 8}) + case tt.twoArgsF != nil: + err = quick.Check(checkAliasingTwoArgs(tt.twoArgsF), &quick.Config{MaxCountScale: 1 << 8}) + } + if err != nil { + t.Errorf("%v: %v", tt.name, err) + } + } +} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_amd64.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_amd64.go new file mode 100644 index 0000000..8fe5839 --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_amd64.go @@ -0,0 +1,14 @@ +// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. + +//go:build amd64 && gc && !purego +// +build amd64,gc,!purego + +package field + +// feMul sets out = a * b. It works like feMulGeneric. +//go:noescape +func feMul(out *Element, a *Element, b *Element) + +// feSquare sets out = a * a. It works like feSquareGeneric. +//go:noescape +func feSquare(out *Element, a *Element) diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_amd64_noasm.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_amd64_noasm.go new file mode 100644 index 0000000..ddb6c9b --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_amd64_noasm.go @@ -0,0 +1,12 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !amd64 || !gc || purego +// +build !amd64 !gc purego + +package field + +func feMul(v, x, y *Element) { feMulGeneric(v, x, y) } + +func feSquare(v, x *Element) { feSquareGeneric(v, x) } diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_arm64.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_arm64.go new file mode 100644 index 0000000..af459ef --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_arm64.go @@ -0,0 +1,16 @@ +// Copyright (c) 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build arm64 && gc && !purego +// +build arm64,gc,!purego + +package field + +//go:noescape +func carryPropagate(v *Element) + +func (v *Element) carryPropagate() *Element { + carryPropagate(v) + return v +} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_arm64_noasm.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_arm64_noasm.go new file mode 100644 index 0000000..234a5b2 --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_arm64_noasm.go @@ -0,0 +1,12 @@ +// Copyright (c) 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !arm64 || !gc || purego +// +build !arm64 !gc purego + +package field + +func (v *Element) carryPropagate() *Element { + return v.carryPropagateGeneric() +} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_bench_test.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_bench_test.go new file mode 100644 index 0000000..77dc06c --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_bench_test.go @@ -0,0 +1,36 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package field + +import "testing" + +func BenchmarkAdd(b *testing.B) { + var x, y Element + x.One() + y.Add(feOne, feOne) + b.ResetTimer() + for i := 0; i < b.N; i++ { + x.Add(&x, &y) + } +} + +func BenchmarkMultiply(b *testing.B) { + var x, y Element + x.One() + y.Add(feOne, feOne) + b.ResetTimer() + for i := 0; i < b.N; i++ { + x.Multiply(&x, &y) + } +} + +func BenchmarkMult32(b *testing.B) { + var x Element + x.One() + b.ResetTimer() + for i := 0; i < b.N; i++ { + x.Mult32(&x, 0xaa42aa42) + } +} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_generic.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_generic.go new file mode 100644 index 0000000..bccf851 --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_generic.go @@ -0,0 +1,264 @@ +// Copyright (c) 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package field + +import "math/bits" + +// uint128 holds a 128-bit number as two 64-bit limbs, for use with the +// bits.Mul64 and bits.Add64 intrinsics. +type uint128 struct { + lo, hi uint64 +} + +// mul64 returns a * b. +func mul64(a, b uint64) uint128 { + hi, lo := bits.Mul64(a, b) + return uint128{lo, hi} +} + +// addMul64 returns v + a * b. +func addMul64(v uint128, a, b uint64) uint128 { + hi, lo := bits.Mul64(a, b) + lo, c := bits.Add64(lo, v.lo, 0) + hi, _ = bits.Add64(hi, v.hi, c) + return uint128{lo, hi} +} + +// shiftRightBy51 returns a >> 51. a is assumed to be at most 115 bits. +func shiftRightBy51(a uint128) uint64 { + return (a.hi << (64 - 51)) | (a.lo >> 51) +} + +func feMulGeneric(v, a, b *Element) { + a0 := a.l0 + a1 := a.l1 + a2 := a.l2 + a3 := a.l3 + a4 := a.l4 + + b0 := b.l0 + b1 := b.l1 + b2 := b.l2 + b3 := b.l3 + b4 := b.l4 + + // Limb multiplication works like pen-and-paper columnar multiplication, but + // with 51-bit limbs instead of digits. + // + // a4 a3 a2 a1 a0 x + // b4 b3 b2 b1 b0 = + // ------------------------ + // a4b0 a3b0 a2b0 a1b0 a0b0 + + // a4b1 a3b1 a2b1 a1b1 a0b1 + + // a4b2 a3b2 a2b2 a1b2 a0b2 + + // a4b3 a3b3 a2b3 a1b3 a0b3 + + // a4b4 a3b4 a2b4 a1b4 a0b4 = + // ---------------------------------------------- + // r8 r7 r6 r5 r4 r3 r2 r1 r0 + // + // We can then use the reduction identity (a * 2²⁵⁵ + b = a * 19 + b) to + // reduce the limbs that would overflow 255 bits. r5 * 2²⁵⁵ becomes 19 * r5, + // r6 * 2³⁰⁶ becomes 19 * r6 * 2⁵¹, etc. + // + // Reduction can be carried out simultaneously to multiplication. For + // example, we do not compute r5: whenever the result of a multiplication + // belongs to r5, like a1b4, we multiply it by 19 and add the result to r0. + // + // a4b0 a3b0 a2b0 a1b0 a0b0 + + // a3b1 a2b1 a1b1 a0b1 19×a4b1 + + // a2b2 a1b2 a0b2 19×a4b2 19×a3b2 + + // a1b3 a0b3 19×a4b3 19×a3b3 19×a2b3 + + // a0b4 19×a4b4 19×a3b4 19×a2b4 19×a1b4 = + // -------------------------------------- + // r4 r3 r2 r1 r0 + // + // Finally we add up the columns into wide, overlapping limbs. + + a1_19 := a1 * 19 + a2_19 := a2 * 19 + a3_19 := a3 * 19 + a4_19 := a4 * 19 + + // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) + r0 := mul64(a0, b0) + r0 = addMul64(r0, a1_19, b4) + r0 = addMul64(r0, a2_19, b3) + r0 = addMul64(r0, a3_19, b2) + r0 = addMul64(r0, a4_19, b1) + + // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2) + r1 := mul64(a0, b1) + r1 = addMul64(r1, a1, b0) + r1 = addMul64(r1, a2_19, b4) + r1 = addMul64(r1, a3_19, b3) + r1 = addMul64(r1, a4_19, b2) + + // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3) + r2 := mul64(a0, b2) + r2 = addMul64(r2, a1, b1) + r2 = addMul64(r2, a2, b0) + r2 = addMul64(r2, a3_19, b4) + r2 = addMul64(r2, a4_19, b3) + + // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4 + r3 := mul64(a0, b3) + r3 = addMul64(r3, a1, b2) + r3 = addMul64(r3, a2, b1) + r3 = addMul64(r3, a3, b0) + r3 = addMul64(r3, a4_19, b4) + + // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 + r4 := mul64(a0, b4) + r4 = addMul64(r4, a1, b3) + r4 = addMul64(r4, a2, b2) + r4 = addMul64(r4, a3, b1) + r4 = addMul64(r4, a4, b0) + + // After the multiplication, we need to reduce (carry) the five coefficients + // to obtain a result with limbs that are at most slightly larger than 2⁵¹, + // to respect the Element invariant. + // + // Overall, the reduction works the same as carryPropagate, except with + // wider inputs: we take the carry for each coefficient by shifting it right + // by 51, and add it to the limb above it. The top carry is multiplied by 19 + // according to the reduction identity and added to the lowest limb. + // + // The largest coefficient (r0) will be at most 111 bits, which guarantees + // that all carries are at most 111 - 51 = 60 bits, which fits in a uint64. + // + // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) + // r0 < 2⁵²×2⁵² + 19×(2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵²) + // r0 < (1 + 19 × 4) × 2⁵² × 2⁵² + // r0 < 2⁷ × 2⁵² × 2⁵² + // r0 < 2¹¹¹ + // + // Moreover, the top coefficient (r4) is at most 107 bits, so c4 is at most + // 56 bits, and c4 * 19 is at most 61 bits, which again fits in a uint64 and + // allows us to easily apply the reduction identity. + // + // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 + // r4 < 5 × 2⁵² × 2⁵² + // r4 < 2¹⁰⁷ + // + + c0 := shiftRightBy51(r0) + c1 := shiftRightBy51(r1) + c2 := shiftRightBy51(r2) + c3 := shiftRightBy51(r3) + c4 := shiftRightBy51(r4) + + rr0 := r0.lo&maskLow51Bits + c4*19 + rr1 := r1.lo&maskLow51Bits + c0 + rr2 := r2.lo&maskLow51Bits + c1 + rr3 := r3.lo&maskLow51Bits + c2 + rr4 := r4.lo&maskLow51Bits + c3 + + // Now all coefficients fit into 64-bit registers but are still too large to + // be passed around as a Element. We therefore do one last carry chain, + // where the carries will be small enough to fit in the wiggle room above 2⁵¹. + *v = Element{rr0, rr1, rr2, rr3, rr4} + v.carryPropagate() +} + +func feSquareGeneric(v, a *Element) { + l0 := a.l0 + l1 := a.l1 + l2 := a.l2 + l3 := a.l3 + l4 := a.l4 + + // Squaring works precisely like multiplication above, but thanks to its + // symmetry we get to group a few terms together. + // + // l4 l3 l2 l1 l0 x + // l4 l3 l2 l1 l0 = + // ------------------------ + // l4l0 l3l0 l2l0 l1l0 l0l0 + + // l4l1 l3l1 l2l1 l1l1 l0l1 + + // l4l2 l3l2 l2l2 l1l2 l0l2 + + // l4l3 l3l3 l2l3 l1l3 l0l3 + + // l4l4 l3l4 l2l4 l1l4 l0l4 = + // ---------------------------------------------- + // r8 r7 r6 r5 r4 r3 r2 r1 r0 + // + // l4l0 l3l0 l2l0 l1l0 l0l0 + + // l3l1 l2l1 l1l1 l0l1 19×l4l1 + + // l2l2 l1l2 l0l2 19×l4l2 19×l3l2 + + // l1l3 l0l3 19×l4l3 19×l3l3 19×l2l3 + + // l0l4 19×l4l4 19×l3l4 19×l2l4 19×l1l4 = + // -------------------------------------- + // r4 r3 r2 r1 r0 + // + // With precomputed 2×, 19×, and 2×19× terms, we can compute each limb with + // only three Mul64 and four Add64, instead of five and eight. + + l0_2 := l0 * 2 + l1_2 := l1 * 2 + + l1_38 := l1 * 38 + l2_38 := l2 * 38 + l3_38 := l3 * 38 + + l3_19 := l3 * 19 + l4_19 := l4 * 19 + + // r0 = l0×l0 + 19×(l1×l4 + l2×l3 + l3×l2 + l4×l1) = l0×l0 + 19×2×(l1×l4 + l2×l3) + r0 := mul64(l0, l0) + r0 = addMul64(r0, l1_38, l4) + r0 = addMul64(r0, l2_38, l3) + + // r1 = l0×l1 + l1×l0 + 19×(l2×l4 + l3×l3 + l4×l2) = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3 + r1 := mul64(l0_2, l1) + r1 = addMul64(r1, l2_38, l4) + r1 = addMul64(r1, l3_19, l3) + + // r2 = l0×l2 + l1×l1 + l2×l0 + 19×(l3×l4 + l4×l3) = 2×l0×l2 + l1×l1 + 19×2×l3×l4 + r2 := mul64(l0_2, l2) + r2 = addMul64(r2, l1, l1) + r2 = addMul64(r2, l3_38, l4) + + // r3 = l0×l3 + l1×l2 + l2×l1 + l3×l0 + 19×l4×l4 = 2×l0×l3 + 2×l1×l2 + 19×l4×l4 + r3 := mul64(l0_2, l3) + r3 = addMul64(r3, l1_2, l2) + r3 = addMul64(r3, l4_19, l4) + + // r4 = l0×l4 + l1×l3 + l2×l2 + l3×l1 + l4×l0 = 2×l0×l4 + 2×l1×l3 + l2×l2 + r4 := mul64(l0_2, l4) + r4 = addMul64(r4, l1_2, l3) + r4 = addMul64(r4, l2, l2) + + c0 := shiftRightBy51(r0) + c1 := shiftRightBy51(r1) + c2 := shiftRightBy51(r2) + c3 := shiftRightBy51(r3) + c4 := shiftRightBy51(r4) + + rr0 := r0.lo&maskLow51Bits + c4*19 + rr1 := r1.lo&maskLow51Bits + c0 + rr2 := r2.lo&maskLow51Bits + c1 + rr3 := r3.lo&maskLow51Bits + c2 + rr4 := r4.lo&maskLow51Bits + c3 + + *v = Element{rr0, rr1, rr2, rr3, rr4} + v.carryPropagate() +} + +// carryPropagate brings the limbs below 52 bits by applying the reduction +// identity (a * 2²⁵⁵ + b = a * 19 + b) to the l4 carry. +func (v *Element) carryPropagateGeneric() *Element { + c0 := v.l0 >> 51 + c1 := v.l1 >> 51 + c2 := v.l2 >> 51 + c3 := v.l3 >> 51 + c4 := v.l4 >> 51 + + v.l0 = v.l0&maskLow51Bits + c4*19 + v.l1 = v.l1&maskLow51Bits + c0 + v.l2 = v.l2&maskLow51Bits + c1 + v.l3 = v.l3&maskLow51Bits + c2 + v.l4 = v.l4&maskLow51Bits + c3 + + return v +} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_test.go b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_test.go new file mode 100644 index 0000000..b484459 --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/field/fe_test.go @@ -0,0 +1,558 @@ +// Copyright (c) 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package field + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "io" + "math/big" + "math/bits" + mathrand "math/rand" + "reflect" + "testing" + "testing/quick" +) + +func (v Element) String() string { + return hex.EncodeToString(v.Bytes()) +} + +// quickCheckConfig1024 will make each quickcheck test run (1024 * -quickchecks) +// times. The default value of -quickchecks is 100. +var quickCheckConfig1024 = &quick.Config{MaxCountScale: 1 << 10} + +func generateFieldElement(rand *mathrand.Rand) Element { + const maskLow52Bits = (1 << 52) - 1 + return Element{ + rand.Uint64() & maskLow52Bits, + rand.Uint64() & maskLow52Bits, + rand.Uint64() & maskLow52Bits, + rand.Uint64() & maskLow52Bits, + rand.Uint64() & maskLow52Bits, + } +} + +// weirdLimbs can be combined to generate a range of edge-case field elements. +// 0 and -1 are intentionally more weighted, as they combine well. +var ( + weirdLimbs51 = []uint64{ + 0, 0, 0, 0, + 1, + 19 - 1, + 19, + 0x2aaaaaaaaaaaa, + 0x5555555555555, + (1 << 51) - 20, + (1 << 51) - 19, + (1 << 51) - 1, (1 << 51) - 1, + (1 << 51) - 1, (1 << 51) - 1, + } + weirdLimbs52 = []uint64{ + 0, 0, 0, 0, 0, 0, + 1, + 19 - 1, + 19, + 0x2aaaaaaaaaaaa, + 0x5555555555555, + (1 << 51) - 20, + (1 << 51) - 19, + (1 << 51) - 1, (1 << 51) - 1, + (1 << 51) - 1, (1 << 51) - 1, + (1 << 51) - 1, (1 << 51) - 1, + 1 << 51, + (1 << 51) + 1, + (1 << 52) - 19, + (1 << 52) - 1, + } +) + +func generateWeirdFieldElement(rand *mathrand.Rand) Element { + return Element{ + weirdLimbs52[rand.Intn(len(weirdLimbs52))], + weirdLimbs51[rand.Intn(len(weirdLimbs51))], + weirdLimbs51[rand.Intn(len(weirdLimbs51))], + weirdLimbs51[rand.Intn(len(weirdLimbs51))], + weirdLimbs51[rand.Intn(len(weirdLimbs51))], + } +} + +func (Element) Generate(rand *mathrand.Rand, size int) reflect.Value { + if rand.Intn(2) == 0 { + return reflect.ValueOf(generateWeirdFieldElement(rand)) + } + return reflect.ValueOf(generateFieldElement(rand)) +} + +// isInBounds returns whether the element is within the expected bit size bounds +// after a light reduction. +func isInBounds(x *Element) bool { + return bits.Len64(x.l0) <= 52 && + bits.Len64(x.l1) <= 52 && + bits.Len64(x.l2) <= 52 && + bits.Len64(x.l3) <= 52 && + bits.Len64(x.l4) <= 52 +} + +func TestMultiplyDistributesOverAdd(t *testing.T) { + multiplyDistributesOverAdd := func(x, y, z Element) bool { + // Compute t1 = (x+y)*z + t1 := new(Element) + t1.Add(&x, &y) + t1.Multiply(t1, &z) + + // Compute t2 = x*z + y*z + t2 := new(Element) + t3 := new(Element) + t2.Multiply(&x, &z) + t3.Multiply(&y, &z) + t2.Add(t2, t3) + + return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2) + } + + if err := quick.Check(multiplyDistributesOverAdd, quickCheckConfig1024); err != nil { + t.Error(err) + } +} + +func TestMul64to128(t *testing.T) { + a := uint64(5) + b := uint64(5) + r := mul64(a, b) + if r.lo != 0x19 || r.hi != 0 { + t.Errorf("lo-range wide mult failed, got %d + %d*(2**64)", r.lo, r.hi) + } + + a = uint64(18014398509481983) // 2^54 - 1 + b = uint64(18014398509481983) // 2^54 - 1 + r = mul64(a, b) + if r.lo != 0xff80000000000001 || r.hi != 0xfffffffffff { + t.Errorf("hi-range wide mult failed, got %d + %d*(2**64)", r.lo, r.hi) + } + + a = uint64(1125899906842661) + b = uint64(2097155) + r = mul64(a, b) + r = addMul64(r, a, b) + r = addMul64(r, a, b) + r = addMul64(r, a, b) + r = addMul64(r, a, b) + if r.lo != 16888498990613035 || r.hi != 640 { + t.Errorf("wrong answer: %d + %d*(2**64)", r.lo, r.hi) + } +} + +func TestSetBytesRoundTrip(t *testing.T) { + f1 := func(in [32]byte, fe Element) bool { + fe.SetBytes(in[:]) + + // Mask the most significant bit as it's ignored by SetBytes. (Now + // instead of earlier so we check the masking in SetBytes is working.) + in[len(in)-1] &= (1 << 7) - 1 + + return bytes.Equal(in[:], fe.Bytes()) && isInBounds(&fe) + } + if err := quick.Check(f1, nil); err != nil { + t.Errorf("failed bytes->FE->bytes round-trip: %v", err) + } + + f2 := func(fe, r Element) bool { + r.SetBytes(fe.Bytes()) + + // Intentionally not using Equal not to go through Bytes again. + // Calling reduce because both Generate and SetBytes can produce + // non-canonical representations. + fe.reduce() + r.reduce() + return fe == r + } + if err := quick.Check(f2, nil); err != nil { + t.Errorf("failed FE->bytes->FE round-trip: %v", err) + } + + // Check some fixed vectors from dalek + type feRTTest struct { + fe Element + b []byte + } + var tests = []feRTTest{ + { + fe: Element{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676}, + b: []byte{74, 209, 69, 197, 70, 70, 161, 222, 56, 226, 229, 19, 112, 60, 25, 92, 187, 74, 222, 56, 50, 153, 51, 233, 40, 74, 57, 6, 160, 185, 213, 31}, + }, + { + fe: Element{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972}, + b: []byte{199, 23, 106, 112, 61, 77, 216, 79, 186, 60, 11, 118, 13, 16, 103, 15, 42, 32, 83, 250, 44, 57, 204, 198, 78, 199, 253, 119, 146, 172, 3, 122}, + }, + } + + for _, tt := range tests { + b := tt.fe.Bytes() + if !bytes.Equal(b, tt.b) || new(Element).SetBytes(tt.b).Equal(&tt.fe) != 1 { + t.Errorf("Failed fixed roundtrip: %v", tt) + } + } +} + +func swapEndianness(buf []byte) []byte { + for i := 0; i < len(buf)/2; i++ { + buf[i], buf[len(buf)-i-1] = buf[len(buf)-i-1], buf[i] + } + return buf +} + +func TestBytesBigEquivalence(t *testing.T) { + f1 := func(in [32]byte, fe, fe1 Element) bool { + fe.SetBytes(in[:]) + + in[len(in)-1] &= (1 << 7) - 1 // mask the most significant bit + b := new(big.Int).SetBytes(swapEndianness(in[:])) + fe1.fromBig(b) + + if fe != fe1 { + return false + } + + buf := make([]byte, 32) // pad with zeroes + copy(buf, swapEndianness(fe1.toBig().Bytes())) + + return bytes.Equal(fe.Bytes(), buf) && isInBounds(&fe) && isInBounds(&fe1) + } + if err := quick.Check(f1, nil); err != nil { + t.Error(err) + } +} + +// fromBig sets v = n, and returns v. The bit length of n must not exceed 256. +func (v *Element) fromBig(n *big.Int) *Element { + if n.BitLen() > 32*8 { + panic("edwards25519: invalid field element input size") + } + + buf := make([]byte, 0, 32) + for _, word := range n.Bits() { + for i := 0; i < bits.UintSize; i += 8 { + if len(buf) >= cap(buf) { + break + } + buf = append(buf, byte(word)) + word >>= 8 + } + } + + return v.SetBytes(buf[:32]) +} + +func (v *Element) fromDecimal(s string) *Element { + n, ok := new(big.Int).SetString(s, 10) + if !ok { + panic("not a valid decimal: " + s) + } + return v.fromBig(n) +} + +// toBig returns v as a big.Int. +func (v *Element) toBig() *big.Int { + buf := v.Bytes() + + words := make([]big.Word, 32*8/bits.UintSize) + for n := range words { + for i := 0; i < bits.UintSize; i += 8 { + if len(buf) == 0 { + break + } + words[n] |= big.Word(buf[0]) << big.Word(i) + buf = buf[1:] + } + } + + return new(big.Int).SetBits(words) +} + +func TestDecimalConstants(t *testing.T) { + sqrtM1String := "19681161376707505956807079304988542015446066515923890162744021073123829784752" + if exp := new(Element).fromDecimal(sqrtM1String); sqrtM1.Equal(exp) != 1 { + t.Errorf("sqrtM1 is %v, expected %v", sqrtM1, exp) + } + // d is in the parent package, and we don't want to expose d or fromDecimal. + // dString := "37095705934669439343138083508754565189542113879843219016388785533085940283555" + // if exp := new(Element).fromDecimal(dString); d.Equal(exp) != 1 { + // t.Errorf("d is %v, expected %v", d, exp) + // } +} + +func TestSetBytesRoundTripEdgeCases(t *testing.T) { + // TODO: values close to 0, close to 2^255-19, between 2^255-19 and 2^255-1, + // and between 2^255 and 2^256-1. Test both the documented SetBytes + // behavior, and that Bytes reduces them. +} + +// Tests self-consistency between Multiply and Square. +func TestConsistency(t *testing.T) { + var x Element + var x2, x2sq Element + + x = Element{1, 1, 1, 1, 1} + x2.Multiply(&x, &x) + x2sq.Square(&x) + + if x2 != x2sq { + t.Fatalf("all ones failed\nmul: %x\nsqr: %x\n", x2, x2sq) + } + + var bytes [32]byte + + _, err := io.ReadFull(rand.Reader, bytes[:]) + if err != nil { + t.Fatal(err) + } + x.SetBytes(bytes[:]) + + x2.Multiply(&x, &x) + x2sq.Square(&x) + + if x2 != x2sq { + t.Fatalf("all ones failed\nmul: %x\nsqr: %x\n", x2, x2sq) + } +} + +func TestEqual(t *testing.T) { + x := Element{1, 1, 1, 1, 1} + y := Element{5, 4, 3, 2, 1} + + eq := x.Equal(&x) + if eq != 1 { + t.Errorf("wrong about equality") + } + + eq = x.Equal(&y) + if eq != 0 { + t.Errorf("wrong about inequality") + } +} + +func TestInvert(t *testing.T) { + x := Element{1, 1, 1, 1, 1} + one := Element{1, 0, 0, 0, 0} + var xinv, r Element + + xinv.Invert(&x) + r.Multiply(&x, &xinv) + r.reduce() + + if one != r { + t.Errorf("inversion identity failed, got: %x", r) + } + + var bytes [32]byte + + _, err := io.ReadFull(rand.Reader, bytes[:]) + if err != nil { + t.Fatal(err) + } + x.SetBytes(bytes[:]) + + xinv.Invert(&x) + r.Multiply(&x, &xinv) + r.reduce() + + if one != r { + t.Errorf("random inversion identity failed, got: %x for field element %x", r, x) + } + + zero := Element{} + x.Set(&zero) + if xx := xinv.Invert(&x); xx != &xinv { + t.Errorf("inverting zero did not return the receiver") + } else if xinv.Equal(&zero) != 1 { + t.Errorf("inverting zero did not return zero") + } +} + +func TestSelectSwap(t *testing.T) { + a := Element{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676} + b := Element{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972} + + var c, d Element + + c.Select(&a, &b, 1) + d.Select(&a, &b, 0) + + if c.Equal(&a) != 1 || d.Equal(&b) != 1 { + t.Errorf("Select failed") + } + + c.Swap(&d, 0) + + if c.Equal(&a) != 1 || d.Equal(&b) != 1 { + t.Errorf("Swap failed") + } + + c.Swap(&d, 1) + + if c.Equal(&b) != 1 || d.Equal(&a) != 1 { + t.Errorf("Swap failed") + } +} + +func TestMult32(t *testing.T) { + mult32EquivalentToMul := func(x Element, y uint32) bool { + t1 := new(Element) + for i := 0; i < 100; i++ { + t1.Mult32(&x, y) + } + + ty := new(Element) + ty.l0 = uint64(y) + + t2 := new(Element) + for i := 0; i < 100; i++ { + t2.Multiply(&x, ty) + } + + return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2) + } + + if err := quick.Check(mult32EquivalentToMul, quickCheckConfig1024); err != nil { + t.Error(err) + } +} + +func TestSqrtRatio(t *testing.T) { + // From draft-irtf-cfrg-ristretto255-decaf448-00, Appendix A.4. + type test struct { + u, v string + wasSquare int + r string + } + var tests = []test{ + // If u is 0, the function is defined to return (0, TRUE), even if v + // is zero. Note that where used in this package, the denominator v + // is never zero. + { + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + 1, "0000000000000000000000000000000000000000000000000000000000000000", + }, + // 0/1 == 0² + { + "0000000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", + 1, "0000000000000000000000000000000000000000000000000000000000000000", + }, + // If u is non-zero and v is zero, defined to return (0, FALSE). + { + "0100000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + 0, "0000000000000000000000000000000000000000000000000000000000000000", + }, + // 2/1 is not square in this field. + { + "0200000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", + 0, "3c5ff1b5d8e4113b871bd052f9e7bcd0582804c266ffb2d4f4203eb07fdb7c54", + }, + // 4/1 == 2² + { + "0400000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", + 1, "0200000000000000000000000000000000000000000000000000000000000000", + }, + // 1/4 == (2⁻¹)² == (2^(p-2))² per Euler's theorem + { + "0100000000000000000000000000000000000000000000000000000000000000", + "0400000000000000000000000000000000000000000000000000000000000000", + 1, "f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f", + }, + } + + for i, tt := range tests { + u := new(Element).SetBytes(decodeHex(tt.u)) + v := new(Element).SetBytes(decodeHex(tt.v)) + want := new(Element).SetBytes(decodeHex(tt.r)) + got, wasSquare := new(Element).SqrtRatio(u, v) + if got.Equal(want) == 0 || wasSquare != tt.wasSquare { + t.Errorf("%d: got (%v, %v), want (%v, %v)", i, got, wasSquare, want, tt.wasSquare) + } + } +} + +func TestCarryPropagate(t *testing.T) { + asmLikeGeneric := func(a [5]uint64) bool { + t1 := &Element{a[0], a[1], a[2], a[3], a[4]} + t2 := &Element{a[0], a[1], a[2], a[3], a[4]} + + t1.carryPropagate() + t2.carryPropagateGeneric() + + if *t1 != *t2 { + t.Logf("got: %#v,\nexpected: %#v", t1, t2) + } + + return *t1 == *t2 && isInBounds(t2) + } + + if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil { + t.Error(err) + } + + if !asmLikeGeneric([5]uint64{0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}) { + t.Errorf("failed for {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}") + } +} + +func TestFeSquare(t *testing.T) { + asmLikeGeneric := func(a Element) bool { + t1 := a + t2 := a + + feSquareGeneric(&t1, &t1) + feSquare(&t2, &t2) + + if t1 != t2 { + t.Logf("got: %#v,\nexpected: %#v", t1, t2) + } + + return t1 == t2 && isInBounds(&t2) + } + + if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil { + t.Error(err) + } +} + +func TestFeMul(t *testing.T) { + asmLikeGeneric := func(a, b Element) bool { + a1 := a + a2 := a + b1 := b + b2 := b + + feMulGeneric(&a1, &a1, &b1) + feMul(&a2, &a2, &b2) + + if a1 != a2 || b1 != b2 { + t.Logf("got: %#v,\nexpected: %#v", a1, a2) + t.Logf("got: %#v,\nexpected: %#v", b1, b2) + } + + return a1 == a2 && isInBounds(&a2) && + b1 == b2 && isInBounds(&b2) + } + + if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil { + t.Error(err) + } +} + +func decodeHex(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b +} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/scalar.go b/libgo/go/crypto/ed25519/internal/edwards25519/scalar.go new file mode 100644 index 0000000..889acaa --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/scalar.go @@ -0,0 +1,1025 @@ +// Copyright (c) 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "crypto/subtle" + "encoding/binary" + "errors" +) + +// A Scalar is an integer modulo +// +// l = 2^252 + 27742317777372353535851937790883648493 +// +// which is the prime order of the edwards25519 group. +// +// This type works similarly to math/big.Int, and all arguments and +// receivers are allowed to alias. +// +// The zero value is a valid zero element. +type Scalar struct { + // s is the Scalar value in little-endian. The value is always reduced + // between operations. + s [32]byte +} + +var ( + scZero = Scalar{[32]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}} + + scOne = Scalar{[32]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}} + + scMinusOne = Scalar{[32]byte{236, 211, 245, 92, 26, 99, 18, 88, 214, 156, 247, 162, 222, 249, 222, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}} +) + +// NewScalar returns a new zero Scalar. +func NewScalar() *Scalar { + return &Scalar{} +} + +// MultiplyAdd sets s = x * y + z mod l, and returns s. +func (s *Scalar) MultiplyAdd(x, y, z *Scalar) *Scalar { + scMulAdd(&s.s, &x.s, &y.s, &z.s) + return s +} + +// Add sets s = x + y mod l, and returns s. +func (s *Scalar) Add(x, y *Scalar) *Scalar { + // s = 1 * x + y mod l + scMulAdd(&s.s, &scOne.s, &x.s, &y.s) + return s +} + +// Subtract sets s = x - y mod l, and returns s. +func (s *Scalar) Subtract(x, y *Scalar) *Scalar { + // s = -1 * y + x mod l + scMulAdd(&s.s, &scMinusOne.s, &y.s, &x.s) + return s +} + +// Negate sets s = -x mod l, and returns s. +func (s *Scalar) Negate(x *Scalar) *Scalar { + // s = -1 * x + 0 mod l + scMulAdd(&s.s, &scMinusOne.s, &x.s, &scZero.s) + return s +} + +// Multiply sets s = x * y mod l, and returns s. +func (s *Scalar) Multiply(x, y *Scalar) *Scalar { + // s = x * y + 0 mod l + scMulAdd(&s.s, &x.s, &y.s, &scZero.s) + return s +} + +// Set sets s = x, and returns s. +func (s *Scalar) Set(x *Scalar) *Scalar { + *s = *x + return s +} + +// SetUniformBytes sets s to an uniformly distributed value given 64 uniformly +// distributed random bytes. +func (s *Scalar) SetUniformBytes(x []byte) *Scalar { + if len(x) != 64 { + panic("edwards25519: invalid SetUniformBytes input length") + } + var wideBytes [64]byte + copy(wideBytes[:], x[:]) + scReduce(&s.s, &wideBytes) + return s +} + +// SetCanonicalBytes sets s = x, where x is a 32-byte little-endian encoding of +// s, and returns s. If x is not a canonical encoding of s, SetCanonicalBytes +// returns nil and an error, and the receiver is unchanged. +func (s *Scalar) SetCanonicalBytes(x []byte) (*Scalar, error) { + if len(x) != 32 { + return nil, errors.New("invalid scalar length") + } + ss := &Scalar{} + copy(ss.s[:], x) + if !isReduced(ss) { + return nil, errors.New("invalid scalar encoding") + } + s.s = ss.s + return s, nil +} + +// isReduced returns whether the given scalar is reduced modulo l. +func isReduced(s *Scalar) bool { + for i := len(s.s) - 1; i >= 0; i-- { + switch { + case s.s[i] > scMinusOne.s[i]: + return false + case s.s[i] < scMinusOne.s[i]: + return true + } + } + return true +} + +// SetBytesWithClamping applies the buffer pruning described in RFC 8032, +// Section 5.1.5 (also known as clamping) and sets s to the result. The input +// must be 32 bytes, and it is not modified. +// +// Note that since Scalar values are always reduced modulo the prime order of +// the curve, the resulting value will not preserve any of the cofactor-clearing +// properties that clamping is meant to provide. It will however work as +// expected as long as it is applied to points on the prime order subgroup, like +// in Ed25519. In fact, it is lost to history why RFC 8032 adopted the +// irrelevant RFC 7748 clamping, but it is now required for compatibility. +func (s *Scalar) SetBytesWithClamping(x []byte) *Scalar { + // The description above omits the purpose of the high bits of the clamping + // for brevity, but those are also lost to reductions, and are also + // irrelevant to edwards25519 as they protect against a specific + // implementation bug that was once observed in a generic Montgomery ladder. + if len(x) != 32 { + panic("edwards25519: invalid SetBytesWithClamping input length") + } + var wideBytes [64]byte + copy(wideBytes[:], x[:]) + wideBytes[0] &= 248 + wideBytes[31] &= 63 + wideBytes[31] |= 64 + scReduce(&s.s, &wideBytes) + return s +} + +// Bytes returns the canonical 32-byte little-endian encoding of s. +func (s *Scalar) Bytes() []byte { + buf := make([]byte, 32) + copy(buf, s.s[:]) + return buf +} + +// Equal returns 1 if s and t are equal, and 0 otherwise. +func (s *Scalar) Equal(t *Scalar) int { + return subtle.ConstantTimeCompare(s.s[:], t.s[:]) +} + +// scMulAdd and scReduce are ported from the public domain, “ref10” +// implementation of ed25519 from SUPERCOP. + +func load3(in []byte) int64 { + r := int64(in[0]) + r |= int64(in[1]) << 8 + r |= int64(in[2]) << 16 + return r +} + +func load4(in []byte) int64 { + r := int64(in[0]) + r |= int64(in[1]) << 8 + r |= int64(in[2]) << 16 + r |= int64(in[3]) << 24 + return r +} + +// Input: +// a[0]+256*a[1]+...+256^31*a[31] = a +// b[0]+256*b[1]+...+256^31*b[31] = b +// c[0]+256*c[1]+...+256^31*c[31] = c +// +// Output: +// s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l +// where l = 2^252 + 27742317777372353535851937790883648493. +func scMulAdd(s, a, b, c *[32]byte) { + a0 := 2097151 & load3(a[:]) + a1 := 2097151 & (load4(a[2:]) >> 5) + a2 := 2097151 & (load3(a[5:]) >> 2) + a3 := 2097151 & (load4(a[7:]) >> 7) + a4 := 2097151 & (load4(a[10:]) >> 4) + a5 := 2097151 & (load3(a[13:]) >> 1) + a6 := 2097151 & (load4(a[15:]) >> 6) + a7 := 2097151 & (load3(a[18:]) >> 3) + a8 := 2097151 & load3(a[21:]) + a9 := 2097151 & (load4(a[23:]) >> 5) + a10 := 2097151 & (load3(a[26:]) >> 2) + a11 := (load4(a[28:]) >> 7) + b0 := 2097151 & load3(b[:]) + b1 := 2097151 & (load4(b[2:]) >> 5) + b2 := 2097151 & (load3(b[5:]) >> 2) + b3 := 2097151 & (load4(b[7:]) >> 7) + b4 := 2097151 & (load4(b[10:]) >> 4) + b5 := 2097151 & (load3(b[13:]) >> 1) + b6 := 2097151 & (load4(b[15:]) >> 6) + b7 := 2097151 & (load3(b[18:]) >> 3) + b8 := 2097151 & load3(b[21:]) + b9 := 2097151 & (load4(b[23:]) >> 5) + b10 := 2097151 & (load3(b[26:]) >> 2) + b11 := (load4(b[28:]) >> 7) + c0 := 2097151 & load3(c[:]) + c1 := 2097151 & (load4(c[2:]) >> 5) + c2 := 2097151 & (load3(c[5:]) >> 2) + c3 := 2097151 & (load4(c[7:]) >> 7) + c4 := 2097151 & (load4(c[10:]) >> 4) + c5 := 2097151 & (load3(c[13:]) >> 1) + c6 := 2097151 & (load4(c[15:]) >> 6) + c7 := 2097151 & (load3(c[18:]) >> 3) + c8 := 2097151 & load3(c[21:]) + c9 := 2097151 & (load4(c[23:]) >> 5) + c10 := 2097151 & (load3(c[26:]) >> 2) + c11 := (load4(c[28:]) >> 7) + var carry [23]int64 + + s0 := c0 + a0*b0 + s1 := c1 + a0*b1 + a1*b0 + s2 := c2 + a0*b2 + a1*b1 + a2*b0 + s3 := c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0 + s4 := c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0 + s5 := c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0 + s6 := c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0 + s7 := c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0 + s8 := c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0 + s9 := c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0 + s10 := c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0 + s11 := c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0 + s12 := a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1 + s13 := a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2 + s14 := a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3 + s15 := a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4 + s16 := a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5 + s17 := a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6 + s18 := a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7 + s19 := a8*b11 + a9*b10 + a10*b9 + a11*b8 + s20 := a9*b11 + a10*b10 + a11*b9 + s21 := a10*b11 + a11*b10 + s22 := a11 * b11 + s23 := int64(0) + + carry[0] = (s0 + (1 << 20)) >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[2] = (s2 + (1 << 20)) >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[4] = (s4 + (1 << 20)) >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[6] = (s6 + (1 << 20)) >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[8] = (s8 + (1 << 20)) >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[10] = (s10 + (1 << 20)) >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + carry[12] = (s12 + (1 << 20)) >> 21 + s13 += carry[12] + s12 -= carry[12] << 21 + carry[14] = (s14 + (1 << 20)) >> 21 + s15 += carry[14] + s14 -= carry[14] << 21 + carry[16] = (s16 + (1 << 20)) >> 21 + s17 += carry[16] + s16 -= carry[16] << 21 + carry[18] = (s18 + (1 << 20)) >> 21 + s19 += carry[18] + s18 -= carry[18] << 21 + carry[20] = (s20 + (1 << 20)) >> 21 + s21 += carry[20] + s20 -= carry[20] << 21 + carry[22] = (s22 + (1 << 20)) >> 21 + s23 += carry[22] + s22 -= carry[22] << 21 + + carry[1] = (s1 + (1 << 20)) >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[3] = (s3 + (1 << 20)) >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[5] = (s5 + (1 << 20)) >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[7] = (s7 + (1 << 20)) >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[9] = (s9 + (1 << 20)) >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[11] = (s11 + (1 << 20)) >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + carry[13] = (s13 + (1 << 20)) >> 21 + s14 += carry[13] + s13 -= carry[13] << 21 + carry[15] = (s15 + (1 << 20)) >> 21 + s16 += carry[15] + s15 -= carry[15] << 21 + carry[17] = (s17 + (1 << 20)) >> 21 + s18 += carry[17] + s17 -= carry[17] << 21 + carry[19] = (s19 + (1 << 20)) >> 21 + s20 += carry[19] + s19 -= carry[19] << 21 + carry[21] = (s21 + (1 << 20)) >> 21 + s22 += carry[21] + s21 -= carry[21] << 21 + + s11 += s23 * 666643 + s12 += s23 * 470296 + s13 += s23 * 654183 + s14 -= s23 * 997805 + s15 += s23 * 136657 + s16 -= s23 * 683901 + s23 = 0 + + s10 += s22 * 666643 + s11 += s22 * 470296 + s12 += s22 * 654183 + s13 -= s22 * 997805 + s14 += s22 * 136657 + s15 -= s22 * 683901 + s22 = 0 + + s9 += s21 * 666643 + s10 += s21 * 470296 + s11 += s21 * 654183 + s12 -= s21 * 997805 + s13 += s21 * 136657 + s14 -= s21 * 683901 + s21 = 0 + + s8 += s20 * 666643 + s9 += s20 * 470296 + s10 += s20 * 654183 + s11 -= s20 * 997805 + s12 += s20 * 136657 + s13 -= s20 * 683901 + s20 = 0 + + s7 += s19 * 666643 + s8 += s19 * 470296 + s9 += s19 * 654183 + s10 -= s19 * 997805 + s11 += s19 * 136657 + s12 -= s19 * 683901 + s19 = 0 + + s6 += s18 * 666643 + s7 += s18 * 470296 + s8 += s18 * 654183 + s9 -= s18 * 997805 + s10 += s18 * 136657 + s11 -= s18 * 683901 + s18 = 0 + + carry[6] = (s6 + (1 << 20)) >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[8] = (s8 + (1 << 20)) >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[10] = (s10 + (1 << 20)) >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + carry[12] = (s12 + (1 << 20)) >> 21 + s13 += carry[12] + s12 -= carry[12] << 21 + carry[14] = (s14 + (1 << 20)) >> 21 + s15 += carry[14] + s14 -= carry[14] << 21 + carry[16] = (s16 + (1 << 20)) >> 21 + s17 += carry[16] + s16 -= carry[16] << 21 + + carry[7] = (s7 + (1 << 20)) >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[9] = (s9 + (1 << 20)) >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[11] = (s11 + (1 << 20)) >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + carry[13] = (s13 + (1 << 20)) >> 21 + s14 += carry[13] + s13 -= carry[13] << 21 + carry[15] = (s15 + (1 << 20)) >> 21 + s16 += carry[15] + s15 -= carry[15] << 21 + + s5 += s17 * 666643 + s6 += s17 * 470296 + s7 += s17 * 654183 + s8 -= s17 * 997805 + s9 += s17 * 136657 + s10 -= s17 * 683901 + s17 = 0 + + s4 += s16 * 666643 + s5 += s16 * 470296 + s6 += s16 * 654183 + s7 -= s16 * 997805 + s8 += s16 * 136657 + s9 -= s16 * 683901 + s16 = 0 + + s3 += s15 * 666643 + s4 += s15 * 470296 + s5 += s15 * 654183 + s6 -= s15 * 997805 + s7 += s15 * 136657 + s8 -= s15 * 683901 + s15 = 0 + + s2 += s14 * 666643 + s3 += s14 * 470296 + s4 += s14 * 654183 + s5 -= s14 * 997805 + s6 += s14 * 136657 + s7 -= s14 * 683901 + s14 = 0 + + s1 += s13 * 666643 + s2 += s13 * 470296 + s3 += s13 * 654183 + s4 -= s13 * 997805 + s5 += s13 * 136657 + s6 -= s13 * 683901 + s13 = 0 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = (s0 + (1 << 20)) >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[2] = (s2 + (1 << 20)) >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[4] = (s4 + (1 << 20)) >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[6] = (s6 + (1 << 20)) >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[8] = (s8 + (1 << 20)) >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[10] = (s10 + (1 << 20)) >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + + carry[1] = (s1 + (1 << 20)) >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[3] = (s3 + (1 << 20)) >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[5] = (s5 + (1 << 20)) >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[7] = (s7 + (1 << 20)) >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[9] = (s9 + (1 << 20)) >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[11] = (s11 + (1 << 20)) >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = s0 >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[1] = s1 >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[2] = s2 >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[3] = s3 >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[4] = s4 >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[5] = s5 >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[6] = s6 >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[7] = s7 >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[8] = s8 >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[9] = s9 >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[10] = s10 >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + carry[11] = s11 >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = s0 >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[1] = s1 >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[2] = s2 >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[3] = s3 >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[4] = s4 >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[5] = s5 >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[6] = s6 >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[7] = s7 >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[8] = s8 >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[9] = s9 >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[10] = s10 >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + + s[0] = byte(s0 >> 0) + s[1] = byte(s0 >> 8) + s[2] = byte((s0 >> 16) | (s1 << 5)) + s[3] = byte(s1 >> 3) + s[4] = byte(s1 >> 11) + s[5] = byte((s1 >> 19) | (s2 << 2)) + s[6] = byte(s2 >> 6) + s[7] = byte((s2 >> 14) | (s3 << 7)) + s[8] = byte(s3 >> 1) + s[9] = byte(s3 >> 9) + s[10] = byte((s3 >> 17) | (s4 << 4)) + s[11] = byte(s4 >> 4) + s[12] = byte(s4 >> 12) + s[13] = byte((s4 >> 20) | (s5 << 1)) + s[14] = byte(s5 >> 7) + s[15] = byte((s5 >> 15) | (s6 << 6)) + s[16] = byte(s6 >> 2) + s[17] = byte(s6 >> 10) + s[18] = byte((s6 >> 18) | (s7 << 3)) + s[19] = byte(s7 >> 5) + s[20] = byte(s7 >> 13) + s[21] = byte(s8 >> 0) + s[22] = byte(s8 >> 8) + s[23] = byte((s8 >> 16) | (s9 << 5)) + s[24] = byte(s9 >> 3) + s[25] = byte(s9 >> 11) + s[26] = byte((s9 >> 19) | (s10 << 2)) + s[27] = byte(s10 >> 6) + s[28] = byte((s10 >> 14) | (s11 << 7)) + s[29] = byte(s11 >> 1) + s[30] = byte(s11 >> 9) + s[31] = byte(s11 >> 17) +} + +// Input: +// s[0]+256*s[1]+...+256^63*s[63] = s +// +// Output: +// s[0]+256*s[1]+...+256^31*s[31] = s mod l +// where l = 2^252 + 27742317777372353535851937790883648493. +func scReduce(out *[32]byte, s *[64]byte) { + s0 := 2097151 & load3(s[:]) + s1 := 2097151 & (load4(s[2:]) >> 5) + s2 := 2097151 & (load3(s[5:]) >> 2) + s3 := 2097151 & (load4(s[7:]) >> 7) + s4 := 2097151 & (load4(s[10:]) >> 4) + s5 := 2097151 & (load3(s[13:]) >> 1) + s6 := 2097151 & (load4(s[15:]) >> 6) + s7 := 2097151 & (load3(s[18:]) >> 3) + s8 := 2097151 & load3(s[21:]) + s9 := 2097151 & (load4(s[23:]) >> 5) + s10 := 2097151 & (load3(s[26:]) >> 2) + s11 := 2097151 & (load4(s[28:]) >> 7) + s12 := 2097151 & (load4(s[31:]) >> 4) + s13 := 2097151 & (load3(s[34:]) >> 1) + s14 := 2097151 & (load4(s[36:]) >> 6) + s15 := 2097151 & (load3(s[39:]) >> 3) + s16 := 2097151 & load3(s[42:]) + s17 := 2097151 & (load4(s[44:]) >> 5) + s18 := 2097151 & (load3(s[47:]) >> 2) + s19 := 2097151 & (load4(s[49:]) >> 7) + s20 := 2097151 & (load4(s[52:]) >> 4) + s21 := 2097151 & (load3(s[55:]) >> 1) + s22 := 2097151 & (load4(s[57:]) >> 6) + s23 := (load4(s[60:]) >> 3) + + s11 += s23 * 666643 + s12 += s23 * 470296 + s13 += s23 * 654183 + s14 -= s23 * 997805 + s15 += s23 * 136657 + s16 -= s23 * 683901 + s23 = 0 + + s10 += s22 * 666643 + s11 += s22 * 470296 + s12 += s22 * 654183 + s13 -= s22 * 997805 + s14 += s22 * 136657 + s15 -= s22 * 683901 + s22 = 0 + + s9 += s21 * 666643 + s10 += s21 * 470296 + s11 += s21 * 654183 + s12 -= s21 * 997805 + s13 += s21 * 136657 + s14 -= s21 * 683901 + s21 = 0 + + s8 += s20 * 666643 + s9 += s20 * 470296 + s10 += s20 * 654183 + s11 -= s20 * 997805 + s12 += s20 * 136657 + s13 -= s20 * 683901 + s20 = 0 + + s7 += s19 * 666643 + s8 += s19 * 470296 + s9 += s19 * 654183 + s10 -= s19 * 997805 + s11 += s19 * 136657 + s12 -= s19 * 683901 + s19 = 0 + + s6 += s18 * 666643 + s7 += s18 * 470296 + s8 += s18 * 654183 + s9 -= s18 * 997805 + s10 += s18 * 136657 + s11 -= s18 * 683901 + s18 = 0 + + var carry [17]int64 + + carry[6] = (s6 + (1 << 20)) >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[8] = (s8 + (1 << 20)) >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[10] = (s10 + (1 << 20)) >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + carry[12] = (s12 + (1 << 20)) >> 21 + s13 += carry[12] + s12 -= carry[12] << 21 + carry[14] = (s14 + (1 << 20)) >> 21 + s15 += carry[14] + s14 -= carry[14] << 21 + carry[16] = (s16 + (1 << 20)) >> 21 + s17 += carry[16] + s16 -= carry[16] << 21 + + carry[7] = (s7 + (1 << 20)) >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[9] = (s9 + (1 << 20)) >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[11] = (s11 + (1 << 20)) >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + carry[13] = (s13 + (1 << 20)) >> 21 + s14 += carry[13] + s13 -= carry[13] << 21 + carry[15] = (s15 + (1 << 20)) >> 21 + s16 += carry[15] + s15 -= carry[15] << 21 + + s5 += s17 * 666643 + s6 += s17 * 470296 + s7 += s17 * 654183 + s8 -= s17 * 997805 + s9 += s17 * 136657 + s10 -= s17 * 683901 + s17 = 0 + + s4 += s16 * 666643 + s5 += s16 * 470296 + s6 += s16 * 654183 + s7 -= s16 * 997805 + s8 += s16 * 136657 + s9 -= s16 * 683901 + s16 = 0 + + s3 += s15 * 666643 + s4 += s15 * 470296 + s5 += s15 * 654183 + s6 -= s15 * 997805 + s7 += s15 * 136657 + s8 -= s15 * 683901 + s15 = 0 + + s2 += s14 * 666643 + s3 += s14 * 470296 + s4 += s14 * 654183 + s5 -= s14 * 997805 + s6 += s14 * 136657 + s7 -= s14 * 683901 + s14 = 0 + + s1 += s13 * 666643 + s2 += s13 * 470296 + s3 += s13 * 654183 + s4 -= s13 * 997805 + s5 += s13 * 136657 + s6 -= s13 * 683901 + s13 = 0 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = (s0 + (1 << 20)) >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[2] = (s2 + (1 << 20)) >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[4] = (s4 + (1 << 20)) >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[6] = (s6 + (1 << 20)) >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[8] = (s8 + (1 << 20)) >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[10] = (s10 + (1 << 20)) >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + + carry[1] = (s1 + (1 << 20)) >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[3] = (s3 + (1 << 20)) >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[5] = (s5 + (1 << 20)) >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[7] = (s7 + (1 << 20)) >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[9] = (s9 + (1 << 20)) >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[11] = (s11 + (1 << 20)) >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = s0 >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[1] = s1 >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[2] = s2 >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[3] = s3 >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[4] = s4 >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[5] = s5 >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[6] = s6 >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[7] = s7 >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[8] = s8 >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[9] = s9 >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[10] = s10 >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + carry[11] = s11 >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = s0 >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[1] = s1 >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[2] = s2 >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[3] = s3 >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[4] = s4 >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[5] = s5 >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[6] = s6 >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[7] = s7 >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[8] = s8 >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[9] = s9 >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[10] = s10 >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + + out[0] = byte(s0 >> 0) + out[1] = byte(s0 >> 8) + out[2] = byte((s0 >> 16) | (s1 << 5)) + out[3] = byte(s1 >> 3) + out[4] = byte(s1 >> 11) + out[5] = byte((s1 >> 19) | (s2 << 2)) + out[6] = byte(s2 >> 6) + out[7] = byte((s2 >> 14) | (s3 << 7)) + out[8] = byte(s3 >> 1) + out[9] = byte(s3 >> 9) + out[10] = byte((s3 >> 17) | (s4 << 4)) + out[11] = byte(s4 >> 4) + out[12] = byte(s4 >> 12) + out[13] = byte((s4 >> 20) | (s5 << 1)) + out[14] = byte(s5 >> 7) + out[15] = byte((s5 >> 15) | (s6 << 6)) + out[16] = byte(s6 >> 2) + out[17] = byte(s6 >> 10) + out[18] = byte((s6 >> 18) | (s7 << 3)) + out[19] = byte(s7 >> 5) + out[20] = byte(s7 >> 13) + out[21] = byte(s8 >> 0) + out[22] = byte(s8 >> 8) + out[23] = byte((s8 >> 16) | (s9 << 5)) + out[24] = byte(s9 >> 3) + out[25] = byte(s9 >> 11) + out[26] = byte((s9 >> 19) | (s10 << 2)) + out[27] = byte(s10 >> 6) + out[28] = byte((s10 >> 14) | (s11 << 7)) + out[29] = byte(s11 >> 1) + out[30] = byte(s11 >> 9) + out[31] = byte(s11 >> 17) +} + +// nonAdjacentForm computes a width-w non-adjacent form for this scalar. +// +// w must be between 2 and 8, or nonAdjacentForm will panic. +func (s *Scalar) nonAdjacentForm(w uint) [256]int8 { + // This implementation is adapted from the one + // in curve25519-dalek and is documented there: + // https://github.com/dalek-cryptography/curve25519-dalek/blob/f630041af28e9a405255f98a8a93adca18e4315b/src/scalar.rs#L800-L871 + if s.s[31] > 127 { + panic("scalar has high bit set illegally") + } + if w < 2 { + panic("w must be at least 2 by the definition of NAF") + } else if w > 8 { + panic("NAF digits must fit in int8") + } + + var naf [256]int8 + var digits [5]uint64 + + for i := 0; i < 4; i++ { + digits[i] = binary.LittleEndian.Uint64(s.s[i*8:]) + } + + width := uint64(1 << w) + windowMask := uint64(width - 1) + + pos := uint(0) + carry := uint64(0) + for pos < 256 { + indexU64 := pos / 64 + indexBit := pos % 64 + var bitBuf uint64 + if indexBit < 64-w { + // This window's bits are contained in a single u64 + bitBuf = digits[indexU64] >> indexBit + } else { + // Combine the current 64 bits with bits from the next 64 + bitBuf = (digits[indexU64] >> indexBit) | (digits[1+indexU64] << (64 - indexBit)) + } + + // Add carry into the current window + window := carry + (bitBuf & windowMask) + + if window&1 == 0 { + // If the window value is even, preserve the carry and continue. + // Why is the carry preserved? + // If carry == 0 and window & 1 == 0, + // then the next carry should be 0 + // If carry == 1 and window & 1 == 0, + // then bit_buf & 1 == 1 so the next carry should be 1 + pos += 1 + continue + } + + if window < width/2 { + carry = 0 + naf[pos] = int8(window) + } else { + carry = 1 + naf[pos] = int8(window) - int8(width) + } + + pos += w + } + return naf +} + +func (s *Scalar) signedRadix16() [64]int8 { + if s.s[31] > 127 { + panic("scalar has high bit set illegally") + } + + var digits [64]int8 + + // Compute unsigned radix-16 digits: + for i := 0; i < 32; i++ { + digits[2*i] = int8(s.s[i] & 15) + digits[2*i+1] = int8((s.s[i] >> 4) & 15) + } + + // Recenter coefficients: + for i := 0; i < 63; i++ { + carry := (digits[i] + 8) >> 4 + digits[i] -= carry << 4 + digits[i+1] += carry + } + + return digits +} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/scalar_alias_test.go b/libgo/go/crypto/ed25519/internal/edwards25519/scalar_alias_test.go new file mode 100644 index 0000000..18d800d --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/scalar_alias_test.go @@ -0,0 +1,93 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "testing" + "testing/quick" +) + +func TestScalarAliasing(t *testing.T) { + checkAliasingOneArg := func(f func(v, x *Scalar) *Scalar, v, x Scalar) bool { + x1, v1 := x, x + + // Calculate a reference f(x) without aliasing. + if out := f(&v, &x); out != &v || !isReduced(out) { + return false + } + + // Test aliasing the argument and the receiver. + if out := f(&v1, &v1); out != &v1 || v1 != v || !isReduced(out) { + return false + } + + // Ensure the arguments was not modified. + return x == x1 + } + + checkAliasingTwoArgs := func(f func(v, x, y *Scalar) *Scalar, v, x, y Scalar) bool { + x1, y1, v1 := x, y, Scalar{} + + // Calculate a reference f(x, y) without aliasing. + if out := f(&v, &x, &y); out != &v || !isReduced(out) { + return false + } + + // Test aliasing the first argument and the receiver. + v1 = x + if out := f(&v1, &v1, &y); out != &v1 || v1 != v || !isReduced(out) { + return false + } + // Test aliasing the second argument and the receiver. + v1 = y + if out := f(&v1, &x, &v1); out != &v1 || v1 != v || !isReduced(out) { + return false + } + + // Calculate a reference f(x, x) without aliasing. + if out := f(&v, &x, &x); out != &v || !isReduced(out) { + return false + } + + // Test aliasing the first argument and the receiver. + v1 = x + if out := f(&v1, &v1, &x); out != &v1 || v1 != v || !isReduced(out) { + return false + } + // Test aliasing the second argument and the receiver. + v1 = x + if out := f(&v1, &x, &v1); out != &v1 || v1 != v || !isReduced(out) { + return false + } + // Test aliasing both arguments and the receiver. + v1 = x + if out := f(&v1, &v1, &v1); out != &v1 || v1 != v || !isReduced(out) { + return false + } + + // Ensure the arguments were not modified. + return x == x1 && y == y1 + } + + for name, f := range map[string]interface{}{ + "Negate": func(v, x Scalar) bool { + return checkAliasingOneArg((*Scalar).Negate, v, x) + }, + "Multiply": func(v, x, y Scalar) bool { + return checkAliasingTwoArgs((*Scalar).Multiply, v, x, y) + }, + "Add": func(v, x, y Scalar) bool { + return checkAliasingTwoArgs((*Scalar).Add, v, x, y) + }, + "Subtract": func(v, x, y Scalar) bool { + return checkAliasingTwoArgs((*Scalar).Subtract, v, x, y) + }, + } { + err := quick.Check(f, &quick.Config{MaxCountScale: 1 << 5}) + if err != nil { + t.Errorf("%v: %v", name, err) + } + } +} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/scalar_test.go b/libgo/go/crypto/ed25519/internal/edwards25519/scalar_test.go new file mode 100644 index 0000000..704caff --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/scalar_test.go @@ -0,0 +1,233 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "bytes" + "encoding/hex" + "math/big" + mathrand "math/rand" + "reflect" + "testing" + "testing/quick" +) + +// Generate returns a valid (reduced modulo l) Scalar with a distribution +// weighted towards high, low, and edge values. +func (Scalar) Generate(rand *mathrand.Rand, size int) reflect.Value { + s := scZero + diceRoll := rand.Intn(100) + switch { + case diceRoll == 0: + case diceRoll == 1: + s = scOne + case diceRoll == 2: + s = scMinusOne + case diceRoll < 5: + // Generate a low scalar in [0, 2^125). + rand.Read(s.s[:16]) + s.s[15] &= (1 << 5) - 1 + case diceRoll < 10: + // Generate a high scalar in [2^252, 2^252 + 2^124). + s.s[31] = 1 << 4 + rand.Read(s.s[:16]) + s.s[15] &= (1 << 4) - 1 + default: + // Generate a valid scalar in [0, l) by returning [0, 2^252) which has a + // negligibly different distribution (the former has a 2^-127.6 chance + // of being out of the latter range). + rand.Read(s.s[:]) + s.s[31] &= (1 << 4) - 1 + } + return reflect.ValueOf(s) +} + +// quickCheckConfig1024 will make each quickcheck test run (1024 * -quickchecks) +// times. The default value of -quickchecks is 100. +var quickCheckConfig1024 = &quick.Config{MaxCountScale: 1 << 10} + +func TestScalarGenerate(t *testing.T) { + f := func(sc Scalar) bool { + return isReduced(&sc) + } + if err := quick.Check(f, quickCheckConfig1024); err != nil { + t.Errorf("generated unreduced scalar: %v", err) + } +} + +func TestScalarSetCanonicalBytes(t *testing.T) { + f1 := func(in [32]byte, sc Scalar) bool { + // Mask out top 4 bits to guarantee value falls in [0, l). + in[len(in)-1] &= (1 << 4) - 1 + if _, err := sc.SetCanonicalBytes(in[:]); err != nil { + return false + } + return bytes.Equal(in[:], sc.Bytes()) && isReduced(&sc) + } + if err := quick.Check(f1, quickCheckConfig1024); err != nil { + t.Errorf("failed bytes->scalar->bytes round-trip: %v", err) + } + + f2 := func(sc1, sc2 Scalar) bool { + if _, err := sc2.SetCanonicalBytes(sc1.Bytes()); err != nil { + return false + } + return sc1 == sc2 + } + if err := quick.Check(f2, quickCheckConfig1024); err != nil { + t.Errorf("failed scalar->bytes->scalar round-trip: %v", err) + } + + b := scMinusOne.s + b[31] += 1 + s := scOne + if out, err := s.SetCanonicalBytes(b[:]); err == nil { + t.Errorf("SetCanonicalBytes worked on a non-canonical value") + } else if s != scOne { + t.Errorf("SetCanonicalBytes modified its receiver") + } else if out != nil { + t.Errorf("SetCanonicalBytes did not return nil with an error") + } +} + +func TestScalarSetUniformBytes(t *testing.T) { + mod, _ := new(big.Int).SetString("27742317777372353535851937790883648493", 10) + mod.Add(mod, new(big.Int).Lsh(big.NewInt(1), 252)) + f := func(in [64]byte, sc Scalar) bool { + sc.SetUniformBytes(in[:]) + if !isReduced(&sc) { + return false + } + scBig := bigIntFromLittleEndianBytes(sc.s[:]) + inBig := bigIntFromLittleEndianBytes(in[:]) + return inBig.Mod(inBig, mod).Cmp(scBig) == 0 + } + if err := quick.Check(f, quickCheckConfig1024); err != nil { + t.Error(err) + } +} + +func TestScalarSetBytesWithClamping(t *testing.T) { + // Generated with libsodium.js 1.0.18 crypto_scalarmult_ed25519_base. + + random := "633d368491364dc9cd4c1bf891b1d59460face1644813240a313e61f2c88216e" + s := new(Scalar).SetBytesWithClamping(decodeHex(random)) + p := new(Point).ScalarBaseMult(s) + want := "1d87a9026fd0126a5736fe1628c95dd419172b5b618457e041c9c861b2494a94" + if got := hex.EncodeToString(p.Bytes()); got != want { + t.Errorf("random: got %q, want %q", got, want) + } + + zero := "0000000000000000000000000000000000000000000000000000000000000000" + s = new(Scalar).SetBytesWithClamping(decodeHex(zero)) + p = new(Point).ScalarBaseMult(s) + want = "693e47972caf527c7883ad1b39822f026f47db2ab0e1919955b8993aa04411d1" + if got := hex.EncodeToString(p.Bytes()); got != want { + t.Errorf("zero: got %q, want %q", got, want) + } + + one := "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + s = new(Scalar).SetBytesWithClamping(decodeHex(one)) + p = new(Point).ScalarBaseMult(s) + want = "12e9a68b73fd5aacdbcaf3e88c46fea6ebedb1aa84eed1842f07f8edab65e3a7" + if got := hex.EncodeToString(p.Bytes()); got != want { + t.Errorf("one: got %q, want %q", got, want) + } +} + +func bigIntFromLittleEndianBytes(b []byte) *big.Int { + bb := make([]byte, len(b)) + for i := range b { + bb[i] = b[len(b)-i-1] + } + return new(big.Int).SetBytes(bb) +} + +func TestScalarMultiplyDistributesOverAdd(t *testing.T) { + multiplyDistributesOverAdd := func(x, y, z Scalar) bool { + // Compute t1 = (x+y)*z + var t1 Scalar + t1.Add(&x, &y) + t1.Multiply(&t1, &z) + + // Compute t2 = x*z + y*z + var t2 Scalar + var t3 Scalar + t2.Multiply(&x, &z) + t3.Multiply(&y, &z) + t2.Add(&t2, &t3) + + return t1 == t2 && isReduced(&t1) && isReduced(&t3) + } + + if err := quick.Check(multiplyDistributesOverAdd, quickCheckConfig1024); err != nil { + t.Error(err) + } +} + +func TestScalarAddLikeSubNeg(t *testing.T) { + addLikeSubNeg := func(x, y Scalar) bool { + // Compute t1 = x - y + var t1 Scalar + t1.Subtract(&x, &y) + + // Compute t2 = -y + x + var t2 Scalar + t2.Negate(&y) + t2.Add(&t2, &x) + + return t1 == t2 && isReduced(&t1) + } + + if err := quick.Check(addLikeSubNeg, quickCheckConfig1024); err != nil { + t.Error(err) + } +} + +func TestScalarNonAdjacentForm(t *testing.T) { + s := Scalar{[32]byte{ + 0x1a, 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d, + 0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8, 0x26, 0x4d, + 0xa7, 0x58, 0xaa, 0x1b, 0x88, 0xe0, 0x40, 0xd1, + 0x58, 0x9e, 0x7b, 0x7f, 0x23, 0x76, 0xef, 0x09, + }} + expectedNaf := [256]int8{ + 0, 13, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, -9, 0, 0, 0, 0, -11, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 9, 0, 0, 0, 0, -5, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 11, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, + -9, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 9, 0, + 0, 0, 0, -15, 0, 0, 0, 0, -7, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, -3, 0, + 0, 0, 0, -11, 0, 0, 0, 0, -7, 0, 0, 0, 0, -13, 0, 0, 0, 0, 11, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, -15, 0, 0, 0, 0, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 13, 0, 0, 0, + 0, 0, 0, 11, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 7, + 0, 0, 0, 0, 0, -15, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + } + + sNaf := s.nonAdjacentForm(5) + + for i := 0; i < 256; i++ { + if expectedNaf[i] != sNaf[i] { + t.Errorf("Wrong digit at position %d, got %d, expected %d", i, sNaf[i], expectedNaf[i]) + } + } +} + +type notZeroScalar Scalar + +func (notZeroScalar) Generate(rand *mathrand.Rand, size int) reflect.Value { + var s Scalar + for s == scZero { + s = Scalar{}.Generate(rand, size).Interface().(Scalar) + } + return reflect.ValueOf(notZeroScalar(s)) +} + +func TestScalarEqual(t *testing.T) { + if scOne.Equal(&scMinusOne) == 1 { + t.Errorf("scOne.Equal(&scMinusOne) is true") + } + if scMinusOne.Equal(&scMinusOne) == 0 { + t.Errorf("scMinusOne.Equal(&scMinusOne) is false") + } +} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/scalarmult.go b/libgo/go/crypto/ed25519/internal/edwards25519/scalarmult.go new file mode 100644 index 0000000..f7ca3ce --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/scalarmult.go @@ -0,0 +1,214 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import "sync" + +// basepointTable is a set of 32 affineLookupTables, where table i is generated +// from 256i * basepoint. It is precomputed the first time it's used. +func basepointTable() *[32]affineLookupTable { + basepointTablePrecomp.initOnce.Do(func() { + p := NewGeneratorPoint() + for i := 0; i < 32; i++ { + basepointTablePrecomp.table[i].FromP3(p) + for j := 0; j < 8; j++ { + p.Add(p, p) + } + } + }) + return &basepointTablePrecomp.table +} + +var basepointTablePrecomp struct { + table [32]affineLookupTable + initOnce sync.Once +} + +// ScalarBaseMult sets v = x * B, where B is the canonical generator, and +// returns v. +// +// The scalar multiplication is done in constant time. +func (v *Point) ScalarBaseMult(x *Scalar) *Point { + basepointTable := basepointTable() + + // Write x = sum(x_i * 16^i) so x*B = sum( B*x_i*16^i ) + // as described in the Ed25519 paper + // + // Group even and odd coefficients + // x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B + // + x_1*16^1*B + x_3*16^3*B + ... + x_63*16^63*B + // x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B + // + 16*( x_1*16^0*B + x_3*16^2*B + ... + x_63*16^62*B) + // + // We use a lookup table for each i to get x_i*16^(2*i)*B + // and do four doublings to multiply by 16. + digits := x.signedRadix16() + + multiple := &affineCached{} + tmp1 := &projP1xP1{} + tmp2 := &projP2{} + + // Accumulate the odd components first + v.Set(NewIdentityPoint()) + for i := 1; i < 64; i += 2 { + basepointTable[i/2].SelectInto(multiple, digits[i]) + tmp1.AddAffine(v, multiple) + v.fromP1xP1(tmp1) + } + + // Multiply by 16 + tmp2.FromP3(v) // tmp2 = v in P2 coords + tmp1.Double(tmp2) // tmp1 = 2*v in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 2*v in P2 coords + tmp1.Double(tmp2) // tmp1 = 4*v in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 4*v in P2 coords + tmp1.Double(tmp2) // tmp1 = 8*v in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 8*v in P2 coords + tmp1.Double(tmp2) // tmp1 = 16*v in P1xP1 coords + v.fromP1xP1(tmp1) // now v = 16*(odd components) + + // Accumulate the even components + for i := 0; i < 64; i += 2 { + basepointTable[i/2].SelectInto(multiple, digits[i]) + tmp1.AddAffine(v, multiple) + v.fromP1xP1(tmp1) + } + + return v +} + +// ScalarMult sets v = x * q, and returns v. +// +// The scalar multiplication is done in constant time. +func (v *Point) ScalarMult(x *Scalar, q *Point) *Point { + checkInitialized(q) + + var table projLookupTable + table.FromP3(q) + + // Write x = sum(x_i * 16^i) + // so x*Q = sum( Q*x_i*16^i ) + // = Q*x_0 + 16*(Q*x_1 + 16*( ... + Q*x_63) ... ) + // <------compute inside out--------- + // + // We use the lookup table to get the x_i*Q values + // and do four doublings to compute 16*Q + digits := x.signedRadix16() + + // Unwrap first loop iteration to save computing 16*identity + multiple := &projCached{} + tmp1 := &projP1xP1{} + tmp2 := &projP2{} + table.SelectInto(multiple, digits[63]) + + v.Set(NewIdentityPoint()) + tmp1.Add(v, multiple) // tmp1 = x_63*Q in P1xP1 coords + for i := 62; i >= 0; i-- { + tmp2.FromP1xP1(tmp1) // tmp2 = (prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 2*(prev) in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 2*(prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 4*(prev) in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 4*(prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 8*(prev) in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 8*(prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 16*(prev) in P1xP1 coords + v.fromP1xP1(tmp1) // v = 16*(prev) in P3 coords + table.SelectInto(multiple, digits[i]) + tmp1.Add(v, multiple) // tmp1 = x_i*Q + 16*(prev) in P1xP1 coords + } + v.fromP1xP1(tmp1) + return v +} + +// basepointNafTable is the nafLookupTable8 for the basepoint. +// It is precomputed the first time it's used. +func basepointNafTable() *nafLookupTable8 { + basepointNafTablePrecomp.initOnce.Do(func() { + basepointNafTablePrecomp.table.FromP3(NewGeneratorPoint()) + }) + return &basepointNafTablePrecomp.table +} + +var basepointNafTablePrecomp struct { + table nafLookupTable8 + initOnce sync.Once +} + +// VarTimeDoubleScalarBaseMult sets v = a * A + b * B, where B is the canonical +// generator, and returns v. +// +// Execution time depends on the inputs. +func (v *Point) VarTimeDoubleScalarBaseMult(a *Scalar, A *Point, b *Scalar) *Point { + checkInitialized(A) + + // Similarly to the single variable-base approach, we compute + // digits and use them with a lookup table. However, because + // we are allowed to do variable-time operations, we don't + // need constant-time lookups or constant-time digit + // computations. + // + // So we use a non-adjacent form of some width w instead of + // radix 16. This is like a binary representation (one digit + // for each binary place) but we allow the digits to grow in + // magnitude up to 2^{w-1} so that the nonzero digits are as + // sparse as possible. Intuitively, this "condenses" the + // "mass" of the scalar onto sparse coefficients (meaning + // fewer additions). + + basepointNafTable := basepointNafTable() + var aTable nafLookupTable5 + aTable.FromP3(A) + // Because the basepoint is fixed, we can use a wider NAF + // corresponding to a bigger table. + aNaf := a.nonAdjacentForm(5) + bNaf := b.nonAdjacentForm(8) + + // Find the first nonzero coefficient. + i := 255 + for j := i; j >= 0; j-- { + if aNaf[j] != 0 || bNaf[j] != 0 { + break + } + } + + multA := &projCached{} + multB := &affineCached{} + tmp1 := &projP1xP1{} + tmp2 := &projP2{} + tmp2.Zero() + + // Move from high to low bits, doubling the accumulator + // at each iteration and checking whether there is a nonzero + // coefficient to look up a multiple of. + for ; i >= 0; i-- { + tmp1.Double(tmp2) + + // Only update v if we have a nonzero coeff to add in. + if aNaf[i] > 0 { + v.fromP1xP1(tmp1) + aTable.SelectInto(multA, aNaf[i]) + tmp1.Add(v, multA) + } else if aNaf[i] < 0 { + v.fromP1xP1(tmp1) + aTable.SelectInto(multA, -aNaf[i]) + tmp1.Sub(v, multA) + } + + if bNaf[i] > 0 { + v.fromP1xP1(tmp1) + basepointNafTable.SelectInto(multB, bNaf[i]) + tmp1.AddAffine(v, multB) + } else if bNaf[i] < 0 { + v.fromP1xP1(tmp1) + basepointNafTable.SelectInto(multB, -bNaf[i]) + tmp1.SubAffine(v, multB) + } + + tmp2.FromP1xP1(tmp1) + } + + v.fromP2(tmp2) + return v +} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/scalarmult_test.go b/libgo/go/crypto/ed25519/internal/edwards25519/scalarmult_test.go new file mode 100644 index 0000000..c2027f5 --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/scalarmult_test.go @@ -0,0 +1,209 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "testing" + "testing/quick" +) + +var ( + // quickCheckConfig32 will make each quickcheck test run (32 * -quickchecks) + // times. The default value of -quickchecks is 100. + quickCheckConfig32 = &quick.Config{MaxCountScale: 1 << 5} + + // a random scalar generated using dalek. + dalekScalar = Scalar{[32]byte{219, 106, 114, 9, 174, 249, 155, 89, 69, 203, 201, 93, 92, 116, 234, 187, 78, 115, 103, 172, 182, 98, 62, 103, 187, 136, 13, 100, 248, 110, 12, 4}} + // the above, times the edwards25519 basepoint. + dalekScalarBasepoint, _ = new(Point).SetBytes([]byte{0xf4, 0xef, 0x7c, 0xa, 0x34, 0x55, 0x7b, 0x9f, 0x72, 0x3b, 0xb6, 0x1e, 0xf9, 0x46, 0x9, 0x91, 0x1c, 0xb9, 0xc0, 0x6c, 0x17, 0x28, 0x2d, 0x8b, 0x43, 0x2b, 0x5, 0x18, 0x6a, 0x54, 0x3e, 0x48}) +) + +func TestScalarMultSmallScalars(t *testing.T) { + var z Scalar + var p Point + p.ScalarMult(&z, B) + if I.Equal(&p) != 1 { + t.Error("0*B != 0") + } + checkOnCurve(t, &p) + + z = Scalar{[32]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}} + p.ScalarMult(&z, B) + if B.Equal(&p) != 1 { + t.Error("1*B != 1") + } + checkOnCurve(t, &p) +} + +func TestScalarMultVsDalek(t *testing.T) { + var p Point + p.ScalarMult(&dalekScalar, B) + if dalekScalarBasepoint.Equal(&p) != 1 { + t.Error("Scalar mul does not match dalek") + } + checkOnCurve(t, &p) +} + +func TestBaseMultVsDalek(t *testing.T) { + var p Point + p.ScalarBaseMult(&dalekScalar) + if dalekScalarBasepoint.Equal(&p) != 1 { + t.Error("Scalar mul does not match dalek") + } + checkOnCurve(t, &p) +} + +func TestVarTimeDoubleBaseMultVsDalek(t *testing.T) { + var p Point + var z Scalar + p.VarTimeDoubleScalarBaseMult(&dalekScalar, B, &z) + if dalekScalarBasepoint.Equal(&p) != 1 { + t.Error("VarTimeDoubleScalarBaseMult fails with b=0") + } + checkOnCurve(t, &p) + p.VarTimeDoubleScalarBaseMult(&z, B, &dalekScalar) + if dalekScalarBasepoint.Equal(&p) != 1 { + t.Error("VarTimeDoubleScalarBaseMult fails with a=0") + } + checkOnCurve(t, &p) +} + +func TestScalarMultDistributesOverAdd(t *testing.T) { + scalarMultDistributesOverAdd := func(x, y Scalar) bool { + var z Scalar + z.Add(&x, &y) + var p, q, r, check Point + p.ScalarMult(&x, B) + q.ScalarMult(&y, B) + r.ScalarMult(&z, B) + check.Add(&p, &q) + checkOnCurve(t, &p, &q, &r, &check) + return check.Equal(&r) == 1 + } + + if err := quick.Check(scalarMultDistributesOverAdd, quickCheckConfig32); err != nil { + t.Error(err) + } +} + +func TestScalarMultNonIdentityPoint(t *testing.T) { + // Check whether p.ScalarMult and q.ScalaBaseMult give the same, + // when p and q are originally set to the base point. + + scalarMultNonIdentityPoint := func(x Scalar) bool { + var p, q Point + p.Set(B) + q.Set(B) + + p.ScalarMult(&x, B) + q.ScalarBaseMult(&x) + + checkOnCurve(t, &p, &q) + + return p.Equal(&q) == 1 + } + + if err := quick.Check(scalarMultNonIdentityPoint, quickCheckConfig32); err != nil { + t.Error(err) + } +} + +func TestBasepointTableGeneration(t *testing.T) { + // The basepoint table is 32 affineLookupTables, + // corresponding to (16^2i)*B for table i. + basepointTable := basepointTable() + + tmp1 := &projP1xP1{} + tmp2 := &projP2{} + tmp3 := &Point{} + tmp3.Set(B) + table := make([]affineLookupTable, 32) + for i := 0; i < 32; i++ { + // Build the table + table[i].FromP3(tmp3) + // Assert equality with the hardcoded one + if table[i] != basepointTable[i] { + t.Errorf("Basepoint table %d does not match", i) + } + + // Set p = (16^2)*p = 256*p = 2^8*p + tmp2.FromP3(tmp3) + for j := 0; j < 7; j++ { + tmp1.Double(tmp2) + tmp2.FromP1xP1(tmp1) + } + tmp1.Double(tmp2) + tmp3.fromP1xP1(tmp1) + checkOnCurve(t, tmp3) + } +} + +func TestScalarMultMatchesBaseMult(t *testing.T) { + scalarMultMatchesBaseMult := func(x Scalar) bool { + var p, q Point + p.ScalarMult(&x, B) + q.ScalarBaseMult(&x) + checkOnCurve(t, &p, &q) + return p.Equal(&q) == 1 + } + + if err := quick.Check(scalarMultMatchesBaseMult, quickCheckConfig32); err != nil { + t.Error(err) + } +} + +func TestBasepointNafTableGeneration(t *testing.T) { + var table nafLookupTable8 + table.FromP3(B) + + if table != *basepointNafTable() { + t.Error("BasepointNafTable does not match") + } +} + +func TestVarTimeDoubleBaseMultMatchesBaseMult(t *testing.T) { + varTimeDoubleBaseMultMatchesBaseMult := func(x, y Scalar) bool { + var p, q1, q2, check Point + + p.VarTimeDoubleScalarBaseMult(&x, B, &y) + + q1.ScalarBaseMult(&x) + q2.ScalarBaseMult(&y) + check.Add(&q1, &q2) + + checkOnCurve(t, &p, &check, &q1, &q2) + return p.Equal(&check) == 1 + } + + if err := quick.Check(varTimeDoubleBaseMultMatchesBaseMult, quickCheckConfig32); err != nil { + t.Error(err) + } +} + +// Benchmarks. + +func BenchmarkScalarBaseMult(t *testing.B) { + var p Point + + for i := 0; i < t.N; i++ { + p.ScalarBaseMult(&dalekScalar) + } +} + +func BenchmarkScalarMult(t *testing.B) { + var p Point + + for i := 0; i < t.N; i++ { + p.ScalarMult(&dalekScalar, B) + } +} + +func BenchmarkVarTimeDoubleScalarBaseMult(t *testing.B) { + var p Point + + for i := 0; i < t.N; i++ { + p.VarTimeDoubleScalarBaseMult(&dalekScalar, B, &dalekScalar) + } +} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/tables.go b/libgo/go/crypto/ed25519/internal/edwards25519/tables.go new file mode 100644 index 0000000..beec956 --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/tables.go @@ -0,0 +1,129 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "crypto/subtle" +) + +// A dynamic lookup table for variable-base, constant-time scalar muls. +type projLookupTable struct { + points [8]projCached +} + +// A precomputed lookup table for fixed-base, constant-time scalar muls. +type affineLookupTable struct { + points [8]affineCached +} + +// A dynamic lookup table for variable-base, variable-time scalar muls. +type nafLookupTable5 struct { + points [8]projCached +} + +// A precomputed lookup table for fixed-base, variable-time scalar muls. +type nafLookupTable8 struct { + points [64]affineCached +} + +// Constructors. + +// Builds a lookup table at runtime. Fast. +func (v *projLookupTable) FromP3(q *Point) { + // Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q + // This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q + v.points[0].FromP3(q) + tmpP3 := Point{} + tmpP1xP1 := projP1xP1{} + for i := 0; i < 7; i++ { + // Compute (i+1)*Q as Q + i*Q and convert to a ProjCached + // This is needlessly complicated because the API has explicit + // recievers instead of creating stack objects and relying on RVO + v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.Add(q, &v.points[i]))) + } +} + +// This is not optimised for speed; fixed-base tables should be precomputed. +func (v *affineLookupTable) FromP3(q *Point) { + // Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q + // This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q + v.points[0].FromP3(q) + tmpP3 := Point{} + tmpP1xP1 := projP1xP1{} + for i := 0; i < 7; i++ { + // Compute (i+1)*Q as Q + i*Q and convert to AffineCached + v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.AddAffine(q, &v.points[i]))) + } +} + +// Builds a lookup table at runtime. Fast. +func (v *nafLookupTable5) FromP3(q *Point) { + // Goal: v.points[i] = (2*i+1)*Q, i.e., Q, 3Q, 5Q, ..., 15Q + // This allows lookup of -15Q, ..., -3Q, -Q, 0, Q, 3Q, ..., 15Q + v.points[0].FromP3(q) + q2 := Point{} + q2.Add(q, q) + tmpP3 := Point{} + tmpP1xP1 := projP1xP1{} + for i := 0; i < 7; i++ { + v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.Add(&q2, &v.points[i]))) + } +} + +// This is not optimised for speed; fixed-base tables should be precomputed. +func (v *nafLookupTable8) FromP3(q *Point) { + v.points[0].FromP3(q) + q2 := Point{} + q2.Add(q, q) + tmpP3 := Point{} + tmpP1xP1 := projP1xP1{} + for i := 0; i < 63; i++ { + v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.AddAffine(&q2, &v.points[i]))) + } +} + +// Selectors. + +// Set dest to x*Q, where -8 <= x <= 8, in constant time. +func (v *projLookupTable) SelectInto(dest *projCached, x int8) { + // Compute xabs = |x| + xmask := x >> 7 + xabs := uint8((x + xmask) ^ xmask) + + dest.Zero() + for j := 1; j <= 8; j++ { + // Set dest = j*Q if |x| = j + cond := subtle.ConstantTimeByteEq(xabs, uint8(j)) + dest.Select(&v.points[j-1], dest, cond) + } + // Now dest = |x|*Q, conditionally negate to get x*Q + dest.CondNeg(int(xmask & 1)) +} + +// Set dest to x*Q, where -8 <= x <= 8, in constant time. +func (v *affineLookupTable) SelectInto(dest *affineCached, x int8) { + // Compute xabs = |x| + xmask := x >> 7 + xabs := uint8((x + xmask) ^ xmask) + + dest.Zero() + for j := 1; j <= 8; j++ { + // Set dest = j*Q if |x| = j + cond := subtle.ConstantTimeByteEq(xabs, uint8(j)) + dest.Select(&v.points[j-1], dest, cond) + } + // Now dest = |x|*Q, conditionally negate to get x*Q + dest.CondNeg(int(xmask & 1)) +} + +// Given odd x with 0 < x < 2^4, return x*Q (in variable time). +func (v *nafLookupTable5) SelectInto(dest *projCached, x int8) { + *dest = v.points[x/2] +} + +// Given odd x with 0 < x < 2^7, return x*Q (in variable time). +func (v *nafLookupTable8) SelectInto(dest *affineCached, x int8) { + *dest = v.points[x/2] +} diff --git a/libgo/go/crypto/ed25519/internal/edwards25519/tables_test.go b/libgo/go/crypto/ed25519/internal/edwards25519/tables_test.go new file mode 100644 index 0000000..b5d161a --- /dev/null +++ b/libgo/go/crypto/ed25519/internal/edwards25519/tables_test.go @@ -0,0 +1,119 @@ +// Copyright (c) 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "testing" +) + +func TestProjLookupTable(t *testing.T) { + var table projLookupTable + table.FromP3(B) + + var tmp1, tmp2, tmp3 projCached + table.SelectInto(&tmp1, 6) + table.SelectInto(&tmp2, -2) + table.SelectInto(&tmp3, -4) + // Expect T1 + T2 + T3 = identity + + var accP1xP1 projP1xP1 + accP3 := NewIdentityPoint() + + accP1xP1.Add(accP3, &tmp1) + accP3.fromP1xP1(&accP1xP1) + accP1xP1.Add(accP3, &tmp2) + accP3.fromP1xP1(&accP1xP1) + accP1xP1.Add(accP3, &tmp3) + accP3.fromP1xP1(&accP1xP1) + + if accP3.Equal(I) != 1 { + t.Errorf("Consistency check on ProjLookupTable.SelectInto failed! %x %x %x", tmp1, tmp2, tmp3) + } +} + +func TestAffineLookupTable(t *testing.T) { + var table affineLookupTable + table.FromP3(B) + + var tmp1, tmp2, tmp3 affineCached + table.SelectInto(&tmp1, 3) + table.SelectInto(&tmp2, -7) + table.SelectInto(&tmp3, 4) + // Expect T1 + T2 + T3 = identity + + var accP1xP1 projP1xP1 + accP3 := NewIdentityPoint() + + accP1xP1.AddAffine(accP3, &tmp1) + accP3.fromP1xP1(&accP1xP1) + accP1xP1.AddAffine(accP3, &tmp2) + accP3.fromP1xP1(&accP1xP1) + accP1xP1.AddAffine(accP3, &tmp3) + accP3.fromP1xP1(&accP1xP1) + + if accP3.Equal(I) != 1 { + t.Errorf("Consistency check on ProjLookupTable.SelectInto failed! %x %x %x", tmp1, tmp2, tmp3) + } +} + +func TestNafLookupTable5(t *testing.T) { + var table nafLookupTable5 + table.FromP3(B) + + var tmp1, tmp2, tmp3, tmp4 projCached + table.SelectInto(&tmp1, 9) + table.SelectInto(&tmp2, 11) + table.SelectInto(&tmp3, 7) + table.SelectInto(&tmp4, 13) + // Expect T1 + T2 = T3 + T4 + + var accP1xP1 projP1xP1 + lhs := NewIdentityPoint() + rhs := NewIdentityPoint() + + accP1xP1.Add(lhs, &tmp1) + lhs.fromP1xP1(&accP1xP1) + accP1xP1.Add(lhs, &tmp2) + lhs.fromP1xP1(&accP1xP1) + + accP1xP1.Add(rhs, &tmp3) + rhs.fromP1xP1(&accP1xP1) + accP1xP1.Add(rhs, &tmp4) + rhs.fromP1xP1(&accP1xP1) + + if lhs.Equal(rhs) != 1 { + t.Errorf("Consistency check on nafLookupTable5 failed") + } +} + +func TestNafLookupTable8(t *testing.T) { + var table nafLookupTable8 + table.FromP3(B) + + var tmp1, tmp2, tmp3, tmp4 affineCached + table.SelectInto(&tmp1, 49) + table.SelectInto(&tmp2, 11) + table.SelectInto(&tmp3, 35) + table.SelectInto(&tmp4, 25) + // Expect T1 + T2 = T3 + T4 + + var accP1xP1 projP1xP1 + lhs := NewIdentityPoint() + rhs := NewIdentityPoint() + + accP1xP1.AddAffine(lhs, &tmp1) + lhs.fromP1xP1(&accP1xP1) + accP1xP1.AddAffine(lhs, &tmp2) + lhs.fromP1xP1(&accP1xP1) + + accP1xP1.AddAffine(rhs, &tmp3) + rhs.fromP1xP1(&accP1xP1) + accP1xP1.AddAffine(rhs, &tmp4) + rhs.fromP1xP1(&accP1xP1) + + if lhs.Equal(rhs) != 1 { + t.Errorf("Consistency check on nafLookupTable8 failed") + } +} diff --git a/libgo/go/crypto/elliptic/elliptic.go b/libgo/go/crypto/elliptic/elliptic.go index f93dc16..f072960 100644 --- a/libgo/go/crypto/elliptic/elliptic.go +++ b/libgo/go/crypto/elliptic/elliptic.go @@ -40,6 +40,15 @@ type Curve interface { ScalarBaseMult(k []byte) (x, y *big.Int) } +func matchesSpecificCurve(params *CurveParams, available ...Curve) (Curve, bool) { + for _, c := range available { + if params == c.Params() { + return c, true + } + } + return nil, false +} + // CurveParams contains the parameters of an elliptic curve and also provides // a generic, non-constant time implementation of Curve. type CurveParams struct { @@ -71,6 +80,12 @@ func (curve *CurveParams) polynomial(x *big.Int) *big.Int { } func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool { + // If there is a dedicated constant-time implementation for this curve operation, + // use that instead of the generic one. + if specific, ok := matchesSpecificCurve(curve, p224, p521); ok { + return specific.IsOnCurve(x, y) + } + // y² = x³ - 3x + b y2 := new(big.Int).Mul(y, y) y2.Mod(y2, curve.P) @@ -108,6 +123,12 @@ func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big. } func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { + // If there is a dedicated constant-time implementation for this curve operation, + // use that instead of the generic one. + if specific, ok := matchesSpecificCurve(curve, p224, p521); ok { + return specific.Add(x1, y1, x2, y2) + } + z1 := zForAffine(x1, y1) z2 := zForAffine(x2, y2) return curve.affineFromJacobian(curve.addJacobian(x1, y1, z1, x2, y2, z2)) @@ -192,6 +213,12 @@ func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int } func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { + // If there is a dedicated constant-time implementation for this curve operation, + // use that instead of the generic one. + if specific, ok := matchesSpecificCurve(curve, p224, p521); ok { + return specific.Double(x1, y1) + } + z1 := zForAffine(x1, y1) return curve.affineFromJacobian(curve.doubleJacobian(x1, y1, z1)) } @@ -258,6 +285,12 @@ func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, } func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) { + // If there is a dedicated constant-time implementation for this curve operation, + // use that instead of the generic one. + if specific, ok := matchesSpecificCurve(curve, p224, p256, p521); ok { + return specific.ScalarMult(Bx, By, k) + } + Bz := new(big.Int).SetInt64(1) x, y, z := new(big.Int), new(big.Int), new(big.Int) @@ -275,6 +308,12 @@ func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big. } func (curve *CurveParams) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { + // If there is a dedicated constant-time implementation for this curve operation, + // use that instead of the generic one. + if specific, ok := matchesSpecificCurve(curve, p224, p256, p521); ok { + return specific.ScalarBaseMult(k) + } + return curve.ScalarMult(curve.Gx, curve.Gy, k) } @@ -390,7 +429,6 @@ func UnmarshalCompressed(curve Curve, data []byte) (x, y *big.Int) { var initonce sync.Once var p384 *CurveParams -var p521 *CurveParams func initAll() { initP224() @@ -410,17 +448,6 @@ func initP384() { p384.BitSize = 384 } -func initP521() { - // See FIPS 186-3, section D.2.5 - p521 = &CurveParams{Name: "P-521"} - p521.P, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", 10) - p521.N, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449", 10) - p521.B, _ = new(big.Int).SetString("051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", 16) - p521.Gx, _ = new(big.Int).SetString("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 16) - p521.Gy, _ = new(big.Int).SetString("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 16) - p521.BitSize = 521 -} - // P256 returns a Curve which implements NIST P-256 (FIPS 186-3, section D.2.3), // also known as secp256r1 or prime256v1. The CurveParams.Name of this Curve is // "P-256". @@ -428,7 +455,7 @@ func initP521() { // Multiple invocations of this function will return the same value, so it can // be used for equality checks and switch statements. // -// The cryptographic operations are implemented using constant-time algorithms. +// ScalarMult and ScalarBaseMult are implemented using constant-time algorithms. func P256() Curve { initonce.Do(initAll) return p256 @@ -452,7 +479,7 @@ func P384() Curve { // Multiple invocations of this function will return the same value, so it can // be used for equality checks and switch statements. // -// The cryptographic operations do not use constant-time algorithms. +// The cryptographic operations are implemented using constant-time algorithms. func P521() Curve { initonce.Do(initAll) return p521 diff --git a/libgo/go/crypto/elliptic/elliptic_test.go b/libgo/go/crypto/elliptic/elliptic_test.go index e80e773..183861a 100644 --- a/libgo/go/crypto/elliptic/elliptic_test.go +++ b/libgo/go/crypto/elliptic/elliptic_test.go @@ -8,414 +8,70 @@ import ( "bytes" "crypto/rand" "encoding/hex" - "fmt" "math/big" "testing" ) -func TestOnCurve(t *testing.T) { - p224 := P224() - if !p224.IsOnCurve(p224.Params().Gx, p224.Params().Gy) { - t.Errorf("FAIL") - } +// genericParamsForCurve returns the dereferenced CurveParams for +// the specified curve. This is used to avoid the logic for +// upgrading a curve to it's specific implementation, forcing +// usage of the generic implementation. This is only relevant +// for the P224, P256, and P521 curves. +func genericParamsForCurve(c Curve) *CurveParams { + d := *(c.Params()) + return &d } -func TestOffCurve(t *testing.T) { - p224 := P224() - x, y := new(big.Int).SetInt64(1), new(big.Int).SetInt64(1) - if p224.IsOnCurve(x, y) { - t.Errorf("FAIL: point off curve is claimed to be on the curve") +func testAllCurves(t *testing.T, f func(*testing.T, Curve)) { + tests := []struct { + name string + curve Curve + }{ + {"P256", P256()}, + {"P256/Params", genericParamsForCurve(P256())}, + {"P224", P224()}, + {"P224/Params", genericParamsForCurve(P224())}, + {"P384", P384()}, + {"P384/Params", genericParamsForCurve(P384())}, + {"P521", P521()}, + {"P521/Params", genericParamsForCurve(P521())}, } - b := Marshal(p224, x, y) - x1, y1 := Unmarshal(p224, b) - if x1 != nil || y1 != nil { - t.Errorf("FAIL: unmarshaling a point not on the curve succeeded") + if testing.Short() { + tests = tests[:1] } -} - -type baseMultTest struct { - k string - x, y string -} - -var p224BaseMultTests = []baseMultTest{ - { - "1", - "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", - "bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", - }, - { - "2", - "706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6", - "1c2b76a7bc25e7702a704fa986892849fca629487acf3709d2e4e8bb", - }, - { - "3", - "df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04", - "a3f7f03cadd0be444c0aa56830130ddf77d317344e1af3591981a925", - }, - { - "4", - "ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301", - "482580a0ec5bc47e88bc8c378632cd196cb3fa058a7114eb03054c9", - }, - { - "5", - "31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa", - "27e8bff1745635ec5ba0c9f1c2ede15414c6507d29ffe37e790a079b", - }, - { - "6", - "1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408", - "89faf0ccb750d99b553c574fad7ecfb0438586eb3952af5b4b153c7e", - }, - { - "7", - "db2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28", - "f3a30085497f2f611ee2517b163ef8c53b715d18bb4e4808d02b963", - }, - { - "8", - "858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550", - "46dcd3ea5c43898c5c5fc4fdac7db39c2f02ebee4e3541d1e78047a", - }, - { - "9", - "2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d", - "371732e4f41bf4f7883035e6a79fcedc0e196eb07b48171697517463", - }, - { - "10", - "aea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd", - "39bb30eab337e0a521b6cba1abe4b2b3a3e524c14a3fe3eb116b655f", - }, - { - "11", - "ef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c", - "20b510004092e96636cfb7e32efded8265c266dfb754fa6d6491a6da", - }, - { - "12", - "6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a", - "207dddf0385bfdeab6e9acda8da06b3bbef224a93ab1e9e036109d13", - }, - { - "13", - "34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca", - "252819f71c7fb7fbcb159be337d37d3336d7feb963724fdfb0ecb767", - }, - { - "14", - "a53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa", - "d5814cd724199c4a5b974a43685fbf5b8bac69459c9469bc8f23ccaf", - }, - { - "15", - "baa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9", - "979a5f4759f80f4fb4ec2e34f5566d595680a11735e7b61046127989", - }, - { - "16", - "b6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d", - "3399d464345906b11b00e363ef429221f2ec720d2f665d7dead5b482", - }, - { - "17", - "b8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc", - "ff149efa6606a6bd20ef7d1b06bd92f6904639dce5174db6cc554a26", - }, - { - "18", - "c9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc", - "ea98d60e5ffc9b8fcf999fab1df7e7ef7084f20ddb61bb045a6ce002", - }, - { - "19", - "a1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c", - "dcf1f6c3db09c70acc25391d492fe25b4a180babd6cea356c04719cd", - }, - { - "20", - "fcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455", - "d5d7110274cba7cdee90e1a8b0d394c376a5573db6be0bf2747f530", - }, - { - "112233445566778899", - "61f077c6f62ed802dad7c2f38f5c67f2cc453601e61bd076bb46179e", - "2272f9e9f5933e70388ee652513443b5e289dd135dcc0d0299b225e4", - }, - { - "112233445566778899112233445566778899", - "29895f0af496bfc62b6ef8d8a65c88c613949b03668aab4f0429e35", - "3ea6e53f9a841f2019ec24bde1a75677aa9b5902e61081c01064de93", - }, - { - "6950511619965839450988900688150712778015737983940691968051900319680", - "ab689930bcae4a4aa5f5cb085e823e8ae30fd365eb1da4aba9cf0379", - "3345a121bbd233548af0d210654eb40bab788a03666419be6fbd34e7", - }, - { - "13479972933410060327035789020509431695094902435494295338570602119423", - "bdb6a8817c1f89da1c2f3dd8e97feb4494f2ed302a4ce2bc7f5f4025", - "4c7020d57c00411889462d77a5438bb4e97d177700bf7243a07f1680", - }, - { - "13479971751745682581351455311314208093898607229429740618390390702079", - "d58b61aa41c32dd5eba462647dba75c5d67c83606c0af2bd928446a9", - "d24ba6a837be0460dd107ae77725696d211446c5609b4595976b16bd", - }, - { - "13479972931865328106486971546324465392952975980343228160962702868479", - "dc9fa77978a005510980e929a1485f63716df695d7a0c18bb518df03", - "ede2b016f2ddffc2a8c015b134928275ce09e5661b7ab14ce0d1d403", - }, - { - "11795773708834916026404142434151065506931607341523388140225443265536", - "499d8b2829cfb879c901f7d85d357045edab55028824d0f05ba279ba", - "bf929537b06e4015919639d94f57838fa33fc3d952598dcdbb44d638", - }, - { - "784254593043826236572847595991346435467177662189391577090", - "8246c999137186632c5f9eddf3b1b0e1764c5e8bd0e0d8a554b9cb77", - "e80ed8660bc1cb17ac7d845be40a7a022d3306f116ae9f81fea65947", - }, - { - "13479767645505654746623887797783387853576174193480695826442858012671", - "6670c20afcceaea672c97f75e2e9dd5c8460e54bb38538ebb4bd30eb", - "f280d8008d07a4caf54271f993527d46ff3ff46fd1190a3f1faa4f74", - }, - { - "205688069665150753842126177372015544874550518966168735589597183", - "eca934247425cfd949b795cb5ce1eff401550386e28d1a4c5a8eb", - "d4c01040dba19628931bc8855370317c722cbd9ca6156985f1c2e9ce", - }, - { - "13479966930919337728895168462090683249159702977113823384618282123295", - "ef353bf5c73cd551b96d596fbc9a67f16d61dd9fe56af19de1fba9cd", - "21771b9cdce3e8430c09b3838be70b48c21e15bc09ee1f2d7945b91f", - }, - { - "50210731791415612487756441341851895584393717453129007497216", - "4036052a3091eb481046ad3289c95d3ac905ca0023de2c03ecd451cf", - "d768165a38a2b96f812586a9d59d4136035d9c853a5bf2e1c86a4993", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368041", - "fcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455", - "f2a28eefd8b345832116f1e574f2c6b2c895aa8c24941f40d8b80ad1", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368042", - "a1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c", - "230e093c24f638f533dac6e2b6d01da3b5e7f45429315ca93fb8e634", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368043", - "c9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc", - "156729f1a003647030666054e208180f8f7b0df2249e44fba5931fff", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368044", - "b8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc", - "eb610599f95942df1082e4f9426d086fb9c6231ae8b24933aab5db", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368045", - "b6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d", - "cc662b9bcba6f94ee4ff1c9c10bd6ddd0d138df2d099a282152a4b7f", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368046", - "baa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9", - "6865a0b8a607f0b04b13d1cb0aa992a5a97f5ee8ca1849efb9ed8678", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368047", - "a53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa", - "2a7eb328dbe663b5a468b5bc97a040a3745396ba636b964370dc3352", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368048", - "34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca", - "dad7e608e380480434ea641cc82c82cbc92801469c8db0204f13489a", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368049", - "6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a", - "df82220fc7a4021549165325725f94c3410ddb56c54e161fc9ef62ee", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368050", - "ef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c", - "df4aefffbf6d1699c930481cd102127c9a3d992048ab05929b6e5927", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368051", - "aea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd", - "c644cf154cc81f5ade49345e541b4d4b5c1adb3eb5c01c14ee949aa2", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368052", - "2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d", - "c8e8cd1b0be40b0877cfca1958603122f1e6914f84b7e8e968ae8b9e", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368053", - "858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550", - "fb9232c15a3bc7673a3a03b0253824c53d0fd1411b1cabe2e187fb87", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368054", - "db2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28", - "f0c5cff7ab680d09ee11dae84e9c1072ac48ea2e744b1b7f72fd469e", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368055", - "1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408", - "76050f3348af2664aac3a8b05281304ebc7a7914c6ad50a4b4eac383", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368056", - "31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa", - "d817400e8ba9ca13a45f360e3d121eaaeb39af82d6001c8186f5f866", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368057", - "ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301", - "fb7da7f5f13a43b81774373c879cd32d6934c05fa758eeb14fcfab38", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368058", - "df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04", - "5c080fc3522f41bbb3f55a97cfecf21f882ce8cbb1e50ca6e67e56dc", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368059", - "706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6", - "e3d4895843da188fd58fb0567976d7b50359d6b78530c8f62d1b1746", - }, - { - "26959946667150639794667015087019625940457807714424391721682722368060", - "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", - "42c89c774a08dc04b3dd201932bc8a5ea5f8b89bbb2a7e667aff81cd", - }, -} - -type scalarMultTest struct { - k string - xIn, yIn string - xOut, yOut string -} - -var p256MultTests = []scalarMultTest{ - { - "2a265f8bcbdcaf94d58519141e578124cb40d64a501fba9c11847b28965bc737", - "023819813ac969847059028ea88a1f30dfbcde03fc791d3a252c6b41211882ea", - "f93e4ae433cc12cf2a43fc0ef26400c0e125508224cdb649380f25479148a4ad", - "4d4de80f1534850d261075997e3049321a0864082d24a917863366c0724f5ae3", - "a22d2b7f7818a3563e0f7a76c9bf0921ac55e06e2e4d11795b233824b1db8cc0", - }, - { - "313f72ff9fe811bf573176231b286a3bdb6f1b14e05c40146590727a71c3bccd", - "cc11887b2d66cbae8f4d306627192522932146b42f01d3c6f92bd5c8ba739b06", - "a2f08a029cd06b46183085bae9248b0ed15b70280c7ef13a457f5af382426031", - "831c3f6b5f762d2f461901577af41354ac5f228c2591f84f8a6e51e2e3f17991", - "93f90934cd0ef2c698cc471c60a93524e87ab31ca2412252337f364513e43684", - }, -} - -func TestBaseMult(t *testing.T) { - p224 := P224() - for i, e := range p224BaseMultTests { - k, ok := new(big.Int).SetString(e.k, 10) - if !ok { - t.Errorf("%d: bad value for k: %s", i, e.k) - } - x, y := p224.ScalarBaseMult(k.Bytes()) - if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y { - t.Errorf("%d: bad output for k=%s: got (%x, %x), want (%s, %s)", i, e.k, x, y, e.x, e.y) - } - if testing.Short() && i > 5 { - break - } + for _, test := range tests { + curve := test.curve + t.Run(test.name, func(t *testing.T) { + t.Parallel() + f(t, curve) + }) } } -func TestGenericBaseMult(t *testing.T) { - // We use the P224 CurveParams directly in order to test the generic implementation. - p224 := P224().Params() - for i, e := range p224BaseMultTests { - k, ok := new(big.Int).SetString(e.k, 10) - if !ok { - t.Errorf("%d: bad value for k: %s", i, e.k) - } - x, y := p224.ScalarBaseMult(k.Bytes()) - if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y { - t.Errorf("%d: bad output for k=%s: got (%x, %x), want (%s, %s)", i, e.k, x, y, e.x, e.y) - } - if testing.Short() && i > 5 { - break +func TestOnCurve(t *testing.T) { + testAllCurves(t, func(t *testing.T, curve Curve) { + if !curve.IsOnCurve(curve.Params().Gx, curve.Params().Gy) { + t.Error("basepoint is not on the curve") } - } + }) } -func TestP256BaseMult(t *testing.T) { - p256 := P256() - p256Generic := p256.Params() - - scalars := make([]*big.Int, 0, len(p224BaseMultTests)+1) - for _, e := range p224BaseMultTests { - k, _ := new(big.Int).SetString(e.k, 10) - scalars = append(scalars, k) - } - k := new(big.Int).SetInt64(1) - k.Lsh(k, 500) - scalars = append(scalars, k) - - for i, k := range scalars { - x, y := p256.ScalarBaseMult(k.Bytes()) - x2, y2 := p256Generic.ScalarBaseMult(k.Bytes()) - if x.Cmp(x2) != 0 || y.Cmp(y2) != 0 { - t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, x, y, x2, y2) +func TestOffCurve(t *testing.T) { + testAllCurves(t, func(t *testing.T, curve Curve) { + x, y := new(big.Int).SetInt64(1), new(big.Int).SetInt64(1) + if curve.IsOnCurve(x, y) { + t.Errorf("point off curve is claimed to be on the curve") } - - if testing.Short() && i > 5 { - break + b := Marshal(curve, x, y) + x1, y1 := Unmarshal(curve, b) + if x1 != nil || y1 != nil { + t.Errorf("unmarshaling a point not on the curve succeeded") } - } + }) } -func TestP256Mult(t *testing.T) { - p256 := P256() - p256Generic := p256.Params() - - for i, e := range p224BaseMultTests { - x, _ := new(big.Int).SetString(e.x, 16) - y, _ := new(big.Int).SetString(e.y, 16) - k, _ := new(big.Int).SetString(e.k, 10) - - xx, yy := p256.ScalarMult(x, y, k.Bytes()) - xx2, yy2 := p256Generic.ScalarMult(x, y, k.Bytes()) - if xx.Cmp(xx2) != 0 || yy.Cmp(yy2) != 0 { - t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, xx2, yy2) - } - if testing.Short() && i > 5 { - break - } - } - - for i, e := range p256MultTests { - x, _ := new(big.Int).SetString(e.xIn, 16) - y, _ := new(big.Int).SetString(e.yIn, 16) - k, _ := new(big.Int).SetString(e.k, 16) - expectedX, _ := new(big.Int).SetString(e.xOut, 16) - expectedY, _ := new(big.Int).SetString(e.yOut, 16) - - xx, yy := p256.ScalarMult(x, y, k.Bytes()) - if xx.Cmp(expectedX) != 0 || yy.Cmp(expectedY) != 0 { - t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, expectedX, expectedY) - } - } +func TestInfinity(t *testing.T) { + testAllCurves(t, testInfinity) } func testInfinity(t *testing.T, curve Curve) { @@ -455,199 +111,66 @@ func testInfinity(t *testing.T, curve Curve) { } } -func TestInfinity(t *testing.T) { - tests := []struct { - name string - curve Curve - }{ - {"P-224", P224()}, - {"P-256", P256()}, - {"P-256/Generic", P256().Params()}, - {"P-384", P384()}, - {"P-521", P521()}, - } - if testing.Short() { - tests = tests[:1] - } - for _, test := range tests { - curve := test.curve - t.Run(test.name, func(t *testing.T) { - testInfinity(t, curve) - }) - } -} - -type synthCombinedMult struct { - Curve -} - -func (s synthCombinedMult) CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) { - x1, y1 := s.ScalarBaseMult(baseScalar) - x2, y2 := s.ScalarMult(bigX, bigY, scalar) - return s.Add(x1, y1, x2, y2) -} - -func TestCombinedMult(t *testing.T) { - type combinedMult interface { - Curve - CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) - } - - p256, ok := P256().(combinedMult) - if !ok { - p256 = &synthCombinedMult{P256()} - } - - gx := p256.Params().Gx - gy := p256.Params().Gy - - zero := make([]byte, 32) - one := make([]byte, 32) - one[31] = 1 - two := make([]byte, 32) - two[31] = 2 - - // 0×G + 0×G = ∞ - x, y := p256.CombinedMult(gx, gy, zero, zero) - if x.Sign() != 0 || y.Sign() != 0 { - t.Errorf("0×G + 0×G = (%d, %d), should be ∞", x, y) - } - - // 1×G + 0×G = G - x, y = p256.CombinedMult(gx, gy, one, zero) - if x.Cmp(gx) != 0 || y.Cmp(gy) != 0 { - t.Errorf("1×G + 0×G = (%d, %d), should be (%d, %d)", x, y, gx, gy) - } - - // 0×G + 1×G = G - x, y = p256.CombinedMult(gx, gy, zero, one) - if x.Cmp(gx) != 0 || y.Cmp(gy) != 0 { - t.Errorf("0×G + 1×G = (%d, %d), should be (%d, %d)", x, y, gx, gy) - } - - // 1×G + 1×G = 2×G - x, y = p256.CombinedMult(gx, gy, one, one) - ggx, ggy := p256.ScalarBaseMult(two) - if x.Cmp(ggx) != 0 || y.Cmp(ggy) != 0 { - t.Errorf("1×G + 1×G = (%d, %d), should be (%d, %d)", x, y, ggx, ggy) - } - - minusOne := new(big.Int).Sub(p256.Params().N, big.NewInt(1)) - // 1×G + (-1)×G = ∞ - x, y = p256.CombinedMult(gx, gy, one, minusOne.Bytes()) - if x.Sign() != 0 || y.Sign() != 0 { - t.Errorf("1×G + (-1)×G = (%d, %d), should be ∞", x, y) - } -} - -func BenchmarkBaseMult(b *testing.B) { - b.ResetTimer() - p224 := P224() - e := p224BaseMultTests[25] - k, _ := new(big.Int).SetString(e.k, 10) - b.ReportAllocs() - b.StartTimer() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - p224.ScalarBaseMult(k.Bytes()) +func TestMarshal(t *testing.T) { + testAllCurves(t, func(t *testing.T, curve Curve) { + _, x, y, err := GenerateKey(curve, rand.Reader) + if err != nil { + t.Fatal(err) } - }) -} - -func BenchmarkBaseMultP256(b *testing.B) { - b.ResetTimer() - p256 := P256() - e := p224BaseMultTests[25] - k, _ := new(big.Int).SetString(e.k, 10) - b.ReportAllocs() - b.StartTimer() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - p256.ScalarBaseMult(k.Bytes()) + serialized := Marshal(curve, x, y) + xx, yy := Unmarshal(curve, serialized) + if xx == nil { + t.Fatal("failed to unmarshal") } - }) -} - -func BenchmarkScalarMultP256(b *testing.B) { - b.ResetTimer() - p256 := P256() - _, x, y, _ := GenerateKey(p256, rand.Reader) - priv, _, _, _ := GenerateKey(p256, rand.Reader) - - b.ReportAllocs() - b.StartTimer() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - p256.ScalarMult(x, y, priv) + if xx.Cmp(x) != 0 || yy.Cmp(y) != 0 { + t.Fatal("unmarshal returned different values") } }) } -func TestMarshal(t *testing.T) { - p224 := P224() - _, x, y, err := GenerateKey(p224, rand.Reader) - if err != nil { - t.Error(err) - return - } - serialized := Marshal(p224, x, y) - xx, yy := Unmarshal(p224, serialized) - if xx == nil { - t.Error("failed to unmarshal") - return - } - if xx.Cmp(x) != 0 || yy.Cmp(y) != 0 { - t.Error("unmarshal returned different values") - return - } -} - -func TestP224Overflow(t *testing.T) { - // This tests for a specific bug in the P224 implementation. - p224 := P224() - pointData, _ := hex.DecodeString("049B535B45FB0A2072398A6831834624C7E32CCFD5A4B933BCEAF77F1DD945E08BBE5178F5EDF5E733388F196D2A631D2E075BB16CBFEEA15B") - x, y := Unmarshal(p224, pointData) - if !p224.IsOnCurve(x, y) { - t.Error("P224 failed to validate a correct point") - } +func TestUnmarshalToLargeCoordinates(t *testing.T) { + // See https://golang.org/issues/20482. + testAllCurves(t, testUnmarshalToLargeCoordinates) } -// See https://golang.org/issues/20482 -func TestUnmarshalToLargeCoordinates(t *testing.T) { - curve := P256() +func testUnmarshalToLargeCoordinates(t *testing.T, curve Curve) { p := curve.Params().P - - invalidX, invalidY := make([]byte, 65), make([]byte, 65) - invalidX[0], invalidY[0] = 4, 4 // uncompressed encoding + byteLen := (p.BitLen() + 7) / 8 // Set x to be greater than curve's parameter P – specifically, to P+5. // Set y to mod_sqrt(x^3 - 3x + B)) so that (x mod P = 5 , y) is on the // curve. x := new(big.Int).Add(p, big.NewInt(5)) - y, _ := new(big.Int).SetString("31468013646237722594854082025316614106172411895747863909393730389177298123724", 10) + y := curve.Params().polynomial(x) + y.ModSqrt(y, p) - copy(invalidX[1:], x.Bytes()) - copy(invalidX[33:], y.Bytes()) + invalid := make([]byte, byteLen*2+1) + invalid[0] = 4 // uncompressed encoding + x.FillBytes(invalid[1 : 1+byteLen]) + y.FillBytes(invalid[1+byteLen:]) - if X, Y := Unmarshal(curve, invalidX); X != nil || Y != nil { + if X, Y := Unmarshal(curve, invalid); X != nil || Y != nil { t.Errorf("Unmarshal accepts invalid X coordinate") } - // This is a point on the curve with a small y value, small enough that we can add p and still be within 32 bytes. - x, _ = new(big.Int).SetString("31931927535157963707678568152204072984517581467226068221761862915403492091210", 10) - y, _ = new(big.Int).SetString("5208467867388784005506817585327037698770365050895731383201516607147", 10) - y.Add(y, p) + if curve == p256 { + // This is a point on the curve with a small y value, small enough that + // we can add p and still be within 32 bytes. + x, _ = new(big.Int).SetString("31931927535157963707678568152204072984517581467226068221761862915403492091210", 10) + y, _ = new(big.Int).SetString("5208467867388784005506817585327037698770365050895731383201516607147", 10) + y.Add(y, p) - if p.Cmp(y) > 0 || y.BitLen() != 256 { - t.Fatal("y not within expected range") - } + if p.Cmp(y) > 0 || y.BitLen() != 256 { + t.Fatal("y not within expected range") + } - // marshal - copy(invalidY[1:], x.Bytes()) - copy(invalidY[33:], y.Bytes()) + // marshal + x.FillBytes(invalid[1 : 1+byteLen]) + y.FillBytes(invalid[1+byteLen:]) - if X, Y := Unmarshal(curve, invalidY); X != nil || Y != nil { - t.Errorf("Unmarshal accepts invalid Y coordinate") + if X, Y := Unmarshal(curve, invalid); X != nil || Y != nil { + t.Errorf("Unmarshal accepts invalid Y coordinate") + } } } @@ -677,27 +200,14 @@ func TestMarshalCompressed(t *testing.T) { t.Skip("skipping other curves on short test") } - t.Run("P-224", func(t *testing.T) { - _, x, y, err := GenerateKey(P224(), rand.Reader) + testAllCurves(t, func(t *testing.T, curve Curve) { + _, x, y, err := GenerateKey(curve, rand.Reader) if err != nil { t.Fatal(err) } - testMarshalCompressed(t, P224(), x, y, nil) - }) - t.Run("P-384", func(t *testing.T) { - _, x, y, err := GenerateKey(P384(), rand.Reader) - if err != nil { - t.Fatal(err) - } - testMarshalCompressed(t, P384(), x, y, nil) - }) - t.Run("P-521", func(t *testing.T) { - _, x, y, err := GenerateKey(P521(), rand.Reader) - if err != nil { - t.Fatal(err) - } - testMarshalCompressed(t, P521(), x, y, nil) + testMarshalCompressed(t, curve, x, y, nil) }) + } func testMarshalCompressed(t *testing.T, curve Curve, x, y *big.Int, want []byte) { @@ -721,3 +231,46 @@ func testMarshalCompressed(t *testing.T, curve Curve, x, y *big.Int, want []byte t.Errorf("point did not round-trip correctly: got (%v, %v), want (%v, %v)", X, Y, x, y) } } + +func benchmarkAllCurves(t *testing.B, f func(*testing.B, Curve)) { + tests := []struct { + name string + curve Curve + }{ + {"P256", P256()}, + {"P224", P224()}, + {"P384", P384()}, + {"P521", P521()}, + } + for _, test := range tests { + curve := test.curve + t.Run(test.name, func(t *testing.B) { + f(t, curve) + }) + } +} + +func BenchmarkScalarBaseMult(b *testing.B) { + benchmarkAllCurves(b, func(b *testing.B, curve Curve) { + priv, _, _, _ := GenerateKey(curve, rand.Reader) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + x, _ := curve.ScalarBaseMult(priv) + // Prevent the compiler from optimizing out the operation. + priv[0] ^= byte(x.Bits()[0]) + } + }) +} + +func BenchmarkScalarMult(b *testing.B) { + benchmarkAllCurves(b, func(b *testing.B, curve Curve) { + _, x, y, _ := GenerateKey(curve, rand.Reader) + priv, _, _, _ := GenerateKey(curve, rand.Reader) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + x, y = curve.ScalarMult(x, y, priv) + } + }) +} diff --git a/libgo/go/crypto/elliptic/fuzz_test.go b/libgo/go/crypto/elliptic/fuzz_test.go index b9209a7..8ff3bf3 100644 --- a/libgo/go/crypto/elliptic/fuzz_test.go +++ b/libgo/go/crypto/elliptic/fuzz_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build amd64 || arm64 || ppc64le // +build amd64 arm64 ppc64le package elliptic @@ -13,7 +14,6 @@ import ( ) func TestFuzz(t *testing.T) { - p256 := P256() p256Generic := p256.Params() diff --git a/libgo/go/crypto/elliptic/internal/fiat/p521.go b/libgo/go/crypto/elliptic/internal/fiat/p521.go new file mode 100644 index 0000000..dc67732 --- /dev/null +++ b/libgo/go/crypto/elliptic/internal/fiat/p521.go @@ -0,0 +1,197 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package fiat implements prime order fields using formally verified algorithms +// from the Fiat Cryptography project. +package fiat + +import ( + "crypto/subtle" + "errors" +) + +// P521Element is an integer modulo 2^521 - 1. +// +// The zero value is a valid zero element. +type P521Element struct { + // This element has the following bounds, which are tighter than + // the output bounds of some operations. Those operations must be + // followed by a carry. + // + // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], + // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], + // [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000] + x [9]uint64 +} + +// One sets e = 1, and returns e. +func (e *P521Element) One() *P521Element { + *e = P521Element{} + e.x[0] = 1 + return e +} + +// Equal returns 1 if e == t, and zero otherwise. +func (e *P521Element) Equal(t *P521Element) int { + eBytes := e.Bytes() + tBytes := t.Bytes() + return subtle.ConstantTimeCompare(eBytes, tBytes) +} + +var p521ZeroEncoding = new(P521Element).Bytes() + +// IsZero returns 1 if e == 0, and zero otherwise. +func (e *P521Element) IsZero() int { + eBytes := e.Bytes() + return subtle.ConstantTimeCompare(eBytes, p521ZeroEncoding) +} + +// Set sets e = t, and returns e. +func (e *P521Element) Set(t *P521Element) *P521Element { + e.x = t.x + return e +} + +// Bytes returns the 66-byte little-endian encoding of e. +func (e *P521Element) Bytes() []byte { + // This function must be inlined to move the allocation to the parent and + // save it from escaping to the heap. + var out [66]byte + p521ToBytes(&out, &e.x) + return out[:] +} + +// SetBytes sets e = v, where v is a little-endian 66-byte encoding, and returns +// e. If v is not 66 bytes or it encodes a value higher than 2^521 - 1, SetBytes +// returns nil and an error, and e is unchanged. +func (e *P521Element) SetBytes(v []byte) (*P521Element, error) { + if len(v) != 66 || v[65] > 1 { + return nil, errors.New("invalid P-521 field encoding") + } + var in [66]byte + copy(in[:], v) + p521FromBytes(&e.x, &in) + return e, nil +} + +// Add sets e = t1 + t2, and returns e. +func (e *P521Element) Add(t1, t2 *P521Element) *P521Element { + p521Add(&e.x, &t1.x, &t2.x) + p521Carry(&e.x, &e.x) + return e +} + +// Sub sets e = t1 - t2, and returns e. +func (e *P521Element) Sub(t1, t2 *P521Element) *P521Element { + p521Sub(&e.x, &t1.x, &t2.x) + p521Carry(&e.x, &e.x) + return e +} + +// Mul sets e = t1 * t2, and returns e. +func (e *P521Element) Mul(t1, t2 *P521Element) *P521Element { + p521CarryMul(&e.x, &t1.x, &t2.x) + return e +} + +// Square sets e = t * t, and returns e. +func (e *P521Element) Square(t *P521Element) *P521Element { + p521CarrySquare(&e.x, &t.x) + return e +} + +// Select sets e to a if cond == 1, and to b if cond == 0. +func (v *P521Element) Select(a, b *P521Element, cond int) *P521Element { + p521Selectznz(&v.x, p521Uint1(cond), &b.x, &a.x) + return v +} + +// Invert sets e = 1/t, and returns e. +// +// If t == 0, Invert returns e = 0. +func (e *P521Element) Invert(t *P521Element) *P521Element { + // Inversion is implemented as exponentiation with exponent p − 2. + // The sequence of multiplications and squarings was generated with + // github.com/mmcloughlin/addchain v0.2.0. + + var t1, t2 = new(P521Element), new(P521Element) + + // _10 = 2 * 1 + t1.Square(t) + + // _11 = 1 + _10 + t1.Mul(t, t1) + + // _1100 = _11 << 2 + t2.Square(t1) + t2.Square(t2) + + // _1111 = _11 + _1100 + t1.Mul(t1, t2) + + // _11110000 = _1111 << 4 + t2.Square(t1) + for i := 0; i < 3; i++ { + t2.Square(t2) + } + + // _11111111 = _1111 + _11110000 + t1.Mul(t1, t2) + + // x16 = _11111111<<8 + _11111111 + t2.Square(t1) + for i := 0; i < 7; i++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + + // x32 = x16<<16 + x16 + t2.Square(t1) + for i := 0; i < 15; i++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + + // x64 = x32<<32 + x32 + t2.Square(t1) + for i := 0; i < 31; i++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + + // x65 = 2*x64 + 1 + t2.Square(t1) + t2.Mul(t2, t) + + // x129 = x65<<64 + x64 + for i := 0; i < 64; i++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + + // x130 = 2*x129 + 1 + t2.Square(t1) + t2.Mul(t2, t) + + // x259 = x130<<129 + x129 + for i := 0; i < 129; i++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + + // x260 = 2*x259 + 1 + t2.Square(t1) + t2.Mul(t2, t) + + // x519 = x260<<259 + x259 + for i := 0; i < 259; i++ { + t2.Square(t2) + } + t1.Mul(t1, t2) + + // return x519<<2 + 1 + t1.Square(t1) + t1.Square(t1) + return e.Mul(t1, t) +} diff --git a/libgo/go/crypto/elliptic/internal/fiat/p521_fiat64.go b/libgo/go/crypto/elliptic/internal/fiat/p521_fiat64.go new file mode 100644 index 0000000..f86283b --- /dev/null +++ b/libgo/go/crypto/elliptic/internal/fiat/p521_fiat64.go @@ -0,0 +1,1856 @@ +// Code generated by Fiat Cryptography. DO NOT EDIT. +// +// Autogenerated: 'fiat-crypto/src/ExtractionOCaml/unsaturated_solinas' --lang Go --no-wide-int --cmovznz-by-mul --internal-static --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --no-prefix-fiat --package-name fiat --doc-text-before-function-name '' --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --doc-newline-before-package-declaration p521 64 9 '2^521 - 1' carry_mul carry_square carry add sub to_bytes from_bytes selectznz +// +// curve description: p521 +// +// machine_wordsize = 64 (from "64") +// +// requested operations: carry_mul, carry_square, carry, add, sub, to_bytes, from_bytes, selectznz +// +// n = 9 (from "9") +// +// s-c = 2^521 - [(1, 1)] (from "2^521 - 1") +// +// tight_bounds_multiplier = 1 (from "") +// +// +// +// Computed values: +// +// carry_chain = [0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1] +// +// eval z = z[0] + (z[1] << 58) + (z[2] << 116) + (z[3] << 174) + (z[4] << 232) + (z[5] << 0x122) + (z[6] << 0x15c) + (z[7] << 0x196) + (z[8] << 0x1d0) +// +// bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) + (z[32] << 256) + (z[33] << 0x108) + (z[34] << 0x110) + (z[35] << 0x118) + (z[36] << 0x120) + (z[37] << 0x128) + (z[38] << 0x130) + (z[39] << 0x138) + (z[40] << 0x140) + (z[41] << 0x148) + (z[42] << 0x150) + (z[43] << 0x158) + (z[44] << 0x160) + (z[45] << 0x168) + (z[46] << 0x170) + (z[47] << 0x178) + (z[48] << 0x180) + (z[49] << 0x188) + (z[50] << 0x190) + (z[51] << 0x198) + (z[52] << 0x1a0) + (z[53] << 0x1a8) + (z[54] << 0x1b0) + (z[55] << 0x1b8) + (z[56] << 0x1c0) + (z[57] << 0x1c8) + (z[58] << 0x1d0) + (z[59] << 0x1d8) + (z[60] << 0x1e0) + (z[61] << 0x1e8) + (z[62] << 0x1f0) + (z[63] << 0x1f8) + (z[64] << 2^9) + (z[65] << 0x208) +// +// balance = [0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x7fffffffffffffe, 0x3fffffffffffffe] + +package fiat + +import "math/bits" + +type p521Uint1 uint8 +type p521Int1 int8 + +// p521AddcarryxU64 is a thin wrapper around bits.Add64 that uses p521Uint1 rather than uint64 +func p521AddcarryxU64(x uint64, y uint64, carry p521Uint1) (uint64, p521Uint1) { + sum, carryOut := bits.Add64(x, y, uint64(carry)) + return sum, p521Uint1(carryOut) +} + +// p521SubborrowxU64 is a thin wrapper around bits.Sub64 that uses p521Uint1 rather than uint64 +func p521SubborrowxU64(x uint64, y uint64, carry p521Uint1) (uint64, p521Uint1) { + sum, carryOut := bits.Sub64(x, y, uint64(carry)) + return sum, p521Uint1(carryOut) +} + +// p521AddcarryxU58 is an addition with carry. +// +// Postconditions: +// out1 = (arg1 + arg2 + arg3) mod 2^58 +// out2 = ⌊(arg1 + arg2 + arg3) / 2^58⌋ +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [0x0 ~> 0x3ffffffffffffff] +// arg3: [0x0 ~> 0x3ffffffffffffff] +// Output Bounds: +// out1: [0x0 ~> 0x3ffffffffffffff] +// out2: [0x0 ~> 0x1] +func p521AddcarryxU58(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) { + x1 := ((uint64(arg1) + arg2) + arg3) + x2 := (x1 & 0x3ffffffffffffff) + x3 := p521Uint1((x1 >> 58)) + *out1 = x2 + *out2 = x3 +} + +// p521SubborrowxU58 is a subtraction with borrow. +// +// Postconditions: +// out1 = (-arg1 + arg2 + -arg3) mod 2^58 +// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^58⌋ +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [0x0 ~> 0x3ffffffffffffff] +// arg3: [0x0 ~> 0x3ffffffffffffff] +// Output Bounds: +// out1: [0x0 ~> 0x3ffffffffffffff] +// out2: [0x0 ~> 0x1] +func p521SubborrowxU58(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) { + x1 := ((int64(arg2) - int64(arg1)) - int64(arg3)) + x2 := p521Int1((x1 >> 58)) + x3 := (uint64(x1) & 0x3ffffffffffffff) + *out1 = x3 + *out2 = (0x0 - p521Uint1(x2)) +} + +// p521AddcarryxU57 is an addition with carry. +// +// Postconditions: +// out1 = (arg1 + arg2 + arg3) mod 2^57 +// out2 = ⌊(arg1 + arg2 + arg3) / 2^57⌋ +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [0x0 ~> 0x1ffffffffffffff] +// arg3: [0x0 ~> 0x1ffffffffffffff] +// Output Bounds: +// out1: [0x0 ~> 0x1ffffffffffffff] +// out2: [0x0 ~> 0x1] +func p521AddcarryxU57(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) { + x1 := ((uint64(arg1) + arg2) + arg3) + x2 := (x1 & 0x1ffffffffffffff) + x3 := p521Uint1((x1 >> 57)) + *out1 = x2 + *out2 = x3 +} + +// p521SubborrowxU57 is a subtraction with borrow. +// +// Postconditions: +// out1 = (-arg1 + arg2 + -arg3) mod 2^57 +// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^57⌋ +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [0x0 ~> 0x1ffffffffffffff] +// arg3: [0x0 ~> 0x1ffffffffffffff] +// Output Bounds: +// out1: [0x0 ~> 0x1ffffffffffffff] +// out2: [0x0 ~> 0x1] +func p521SubborrowxU57(out1 *uint64, out2 *p521Uint1, arg1 p521Uint1, arg2 uint64, arg3 uint64) { + x1 := ((int64(arg2) - int64(arg1)) - int64(arg3)) + x2 := p521Int1((x1 >> 57)) + x3 := (uint64(x1) & 0x1ffffffffffffff) + *out1 = x3 + *out2 = (0x0 - p521Uint1(x2)) +} + +// p521CmovznzU64 is a single-word conditional move. +// +// Postconditions: +// out1 = (if arg1 = 0 then arg2 else arg3) +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [0x0 ~> 0xffffffffffffffff] +// arg3: [0x0 ~> 0xffffffffffffffff] +// Output Bounds: +// out1: [0x0 ~> 0xffffffffffffffff] +func p521CmovznzU64(out1 *uint64, arg1 p521Uint1, arg2 uint64, arg3 uint64) { + x1 := (uint64(arg1) * 0xffffffffffffffff) + x2 := ((x1 & arg3) | ((^x1) & arg2)) + *out1 = x2 +} + +// p521CarryMul multiplies two field elements and reduces the result. +// +// Postconditions: +// eval out1 mod m = (eval arg1 * eval arg2) mod m +// +// Input Bounds: +// arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] +// arg2: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] +// Output Bounds: +// out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +func p521CarryMul(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) { + var x1 uint64 + var x2 uint64 + x2, x1 = bits.Mul64(arg1[8], (arg2[8] * 0x2)) + var x3 uint64 + var x4 uint64 + x4, x3 = bits.Mul64(arg1[8], (arg2[7] * 0x2)) + var x5 uint64 + var x6 uint64 + x6, x5 = bits.Mul64(arg1[8], (arg2[6] * 0x2)) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(arg1[8], (arg2[5] * 0x2)) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(arg1[8], (arg2[4] * 0x2)) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(arg1[8], (arg2[3] * 0x2)) + var x13 uint64 + var x14 uint64 + x14, x13 = bits.Mul64(arg1[8], (arg2[2] * 0x2)) + var x15 uint64 + var x16 uint64 + x16, x15 = bits.Mul64(arg1[8], (arg2[1] * 0x2)) + var x17 uint64 + var x18 uint64 + x18, x17 = bits.Mul64(arg1[7], (arg2[8] * 0x2)) + var x19 uint64 + var x20 uint64 + x20, x19 = bits.Mul64(arg1[7], (arg2[7] * 0x2)) + var x21 uint64 + var x22 uint64 + x22, x21 = bits.Mul64(arg1[7], (arg2[6] * 0x2)) + var x23 uint64 + var x24 uint64 + x24, x23 = bits.Mul64(arg1[7], (arg2[5] * 0x2)) + var x25 uint64 + var x26 uint64 + x26, x25 = bits.Mul64(arg1[7], (arg2[4] * 0x2)) + var x27 uint64 + var x28 uint64 + x28, x27 = bits.Mul64(arg1[7], (arg2[3] * 0x2)) + var x29 uint64 + var x30 uint64 + x30, x29 = bits.Mul64(arg1[7], (arg2[2] * 0x2)) + var x31 uint64 + var x32 uint64 + x32, x31 = bits.Mul64(arg1[6], (arg2[8] * 0x2)) + var x33 uint64 + var x34 uint64 + x34, x33 = bits.Mul64(arg1[6], (arg2[7] * 0x2)) + var x35 uint64 + var x36 uint64 + x36, x35 = bits.Mul64(arg1[6], (arg2[6] * 0x2)) + var x37 uint64 + var x38 uint64 + x38, x37 = bits.Mul64(arg1[6], (arg2[5] * 0x2)) + var x39 uint64 + var x40 uint64 + x40, x39 = bits.Mul64(arg1[6], (arg2[4] * 0x2)) + var x41 uint64 + var x42 uint64 + x42, x41 = bits.Mul64(arg1[6], (arg2[3] * 0x2)) + var x43 uint64 + var x44 uint64 + x44, x43 = bits.Mul64(arg1[5], (arg2[8] * 0x2)) + var x45 uint64 + var x46 uint64 + x46, x45 = bits.Mul64(arg1[5], (arg2[7] * 0x2)) + var x47 uint64 + var x48 uint64 + x48, x47 = bits.Mul64(arg1[5], (arg2[6] * 0x2)) + var x49 uint64 + var x50 uint64 + x50, x49 = bits.Mul64(arg1[5], (arg2[5] * 0x2)) + var x51 uint64 + var x52 uint64 + x52, x51 = bits.Mul64(arg1[5], (arg2[4] * 0x2)) + var x53 uint64 + var x54 uint64 + x54, x53 = bits.Mul64(arg1[4], (arg2[8] * 0x2)) + var x55 uint64 + var x56 uint64 + x56, x55 = bits.Mul64(arg1[4], (arg2[7] * 0x2)) + var x57 uint64 + var x58 uint64 + x58, x57 = bits.Mul64(arg1[4], (arg2[6] * 0x2)) + var x59 uint64 + var x60 uint64 + x60, x59 = bits.Mul64(arg1[4], (arg2[5] * 0x2)) + var x61 uint64 + var x62 uint64 + x62, x61 = bits.Mul64(arg1[3], (arg2[8] * 0x2)) + var x63 uint64 + var x64 uint64 + x64, x63 = bits.Mul64(arg1[3], (arg2[7] * 0x2)) + var x65 uint64 + var x66 uint64 + x66, x65 = bits.Mul64(arg1[3], (arg2[6] * 0x2)) + var x67 uint64 + var x68 uint64 + x68, x67 = bits.Mul64(arg1[2], (arg2[8] * 0x2)) + var x69 uint64 + var x70 uint64 + x70, x69 = bits.Mul64(arg1[2], (arg2[7] * 0x2)) + var x71 uint64 + var x72 uint64 + x72, x71 = bits.Mul64(arg1[1], (arg2[8] * 0x2)) + var x73 uint64 + var x74 uint64 + x74, x73 = bits.Mul64(arg1[8], arg2[0]) + var x75 uint64 + var x76 uint64 + x76, x75 = bits.Mul64(arg1[7], arg2[1]) + var x77 uint64 + var x78 uint64 + x78, x77 = bits.Mul64(arg1[7], arg2[0]) + var x79 uint64 + var x80 uint64 + x80, x79 = bits.Mul64(arg1[6], arg2[2]) + var x81 uint64 + var x82 uint64 + x82, x81 = bits.Mul64(arg1[6], arg2[1]) + var x83 uint64 + var x84 uint64 + x84, x83 = bits.Mul64(arg1[6], arg2[0]) + var x85 uint64 + var x86 uint64 + x86, x85 = bits.Mul64(arg1[5], arg2[3]) + var x87 uint64 + var x88 uint64 + x88, x87 = bits.Mul64(arg1[5], arg2[2]) + var x89 uint64 + var x90 uint64 + x90, x89 = bits.Mul64(arg1[5], arg2[1]) + var x91 uint64 + var x92 uint64 + x92, x91 = bits.Mul64(arg1[5], arg2[0]) + var x93 uint64 + var x94 uint64 + x94, x93 = bits.Mul64(arg1[4], arg2[4]) + var x95 uint64 + var x96 uint64 + x96, x95 = bits.Mul64(arg1[4], arg2[3]) + var x97 uint64 + var x98 uint64 + x98, x97 = bits.Mul64(arg1[4], arg2[2]) + var x99 uint64 + var x100 uint64 + x100, x99 = bits.Mul64(arg1[4], arg2[1]) + var x101 uint64 + var x102 uint64 + x102, x101 = bits.Mul64(arg1[4], arg2[0]) + var x103 uint64 + var x104 uint64 + x104, x103 = bits.Mul64(arg1[3], arg2[5]) + var x105 uint64 + var x106 uint64 + x106, x105 = bits.Mul64(arg1[3], arg2[4]) + var x107 uint64 + var x108 uint64 + x108, x107 = bits.Mul64(arg1[3], arg2[3]) + var x109 uint64 + var x110 uint64 + x110, x109 = bits.Mul64(arg1[3], arg2[2]) + var x111 uint64 + var x112 uint64 + x112, x111 = bits.Mul64(arg1[3], arg2[1]) + var x113 uint64 + var x114 uint64 + x114, x113 = bits.Mul64(arg1[3], arg2[0]) + var x115 uint64 + var x116 uint64 + x116, x115 = bits.Mul64(arg1[2], arg2[6]) + var x117 uint64 + var x118 uint64 + x118, x117 = bits.Mul64(arg1[2], arg2[5]) + var x119 uint64 + var x120 uint64 + x120, x119 = bits.Mul64(arg1[2], arg2[4]) + var x121 uint64 + var x122 uint64 + x122, x121 = bits.Mul64(arg1[2], arg2[3]) + var x123 uint64 + var x124 uint64 + x124, x123 = bits.Mul64(arg1[2], arg2[2]) + var x125 uint64 + var x126 uint64 + x126, x125 = bits.Mul64(arg1[2], arg2[1]) + var x127 uint64 + var x128 uint64 + x128, x127 = bits.Mul64(arg1[2], arg2[0]) + var x129 uint64 + var x130 uint64 + x130, x129 = bits.Mul64(arg1[1], arg2[7]) + var x131 uint64 + var x132 uint64 + x132, x131 = bits.Mul64(arg1[1], arg2[6]) + var x133 uint64 + var x134 uint64 + x134, x133 = bits.Mul64(arg1[1], arg2[5]) + var x135 uint64 + var x136 uint64 + x136, x135 = bits.Mul64(arg1[1], arg2[4]) + var x137 uint64 + var x138 uint64 + x138, x137 = bits.Mul64(arg1[1], arg2[3]) + var x139 uint64 + var x140 uint64 + x140, x139 = bits.Mul64(arg1[1], arg2[2]) + var x141 uint64 + var x142 uint64 + x142, x141 = bits.Mul64(arg1[1], arg2[1]) + var x143 uint64 + var x144 uint64 + x144, x143 = bits.Mul64(arg1[1], arg2[0]) + var x145 uint64 + var x146 uint64 + x146, x145 = bits.Mul64(arg1[0], arg2[8]) + var x147 uint64 + var x148 uint64 + x148, x147 = bits.Mul64(arg1[0], arg2[7]) + var x149 uint64 + var x150 uint64 + x150, x149 = bits.Mul64(arg1[0], arg2[6]) + var x151 uint64 + var x152 uint64 + x152, x151 = bits.Mul64(arg1[0], arg2[5]) + var x153 uint64 + var x154 uint64 + x154, x153 = bits.Mul64(arg1[0], arg2[4]) + var x155 uint64 + var x156 uint64 + x156, x155 = bits.Mul64(arg1[0], arg2[3]) + var x157 uint64 + var x158 uint64 + x158, x157 = bits.Mul64(arg1[0], arg2[2]) + var x159 uint64 + var x160 uint64 + x160, x159 = bits.Mul64(arg1[0], arg2[1]) + var x161 uint64 + var x162 uint64 + x162, x161 = bits.Mul64(arg1[0], arg2[0]) + var x163 uint64 + var x164 p521Uint1 + x163, x164 = p521AddcarryxU64(x29, x15, 0x0) + var x165 uint64 + x165, _ = p521AddcarryxU64(x30, x16, x164) + var x167 uint64 + var x168 p521Uint1 + x167, x168 = p521AddcarryxU64(x41, x163, 0x0) + var x169 uint64 + x169, _ = p521AddcarryxU64(x42, x165, x168) + var x171 uint64 + var x172 p521Uint1 + x171, x172 = p521AddcarryxU64(x51, x167, 0x0) + var x173 uint64 + x173, _ = p521AddcarryxU64(x52, x169, x172) + var x175 uint64 + var x176 p521Uint1 + x175, x176 = p521AddcarryxU64(x59, x171, 0x0) + var x177 uint64 + x177, _ = p521AddcarryxU64(x60, x173, x176) + var x179 uint64 + var x180 p521Uint1 + x179, x180 = p521AddcarryxU64(x65, x175, 0x0) + var x181 uint64 + x181, _ = p521AddcarryxU64(x66, x177, x180) + var x183 uint64 + var x184 p521Uint1 + x183, x184 = p521AddcarryxU64(x69, x179, 0x0) + var x185 uint64 + x185, _ = p521AddcarryxU64(x70, x181, x184) + var x187 uint64 + var x188 p521Uint1 + x187, x188 = p521AddcarryxU64(x71, x183, 0x0) + var x189 uint64 + x189, _ = p521AddcarryxU64(x72, x185, x188) + var x191 uint64 + var x192 p521Uint1 + x191, x192 = p521AddcarryxU64(x161, x187, 0x0) + var x193 uint64 + x193, _ = p521AddcarryxU64(x162, x189, x192) + x195 := ((x191 >> 58) | ((x193 << 6) & 0xffffffffffffffff)) + x196 := (x193 >> 58) + x197 := (x191 & 0x3ffffffffffffff) + var x198 uint64 + var x199 p521Uint1 + x198, x199 = p521AddcarryxU64(x75, x73, 0x0) + var x200 uint64 + x200, _ = p521AddcarryxU64(x76, x74, x199) + var x202 uint64 + var x203 p521Uint1 + x202, x203 = p521AddcarryxU64(x79, x198, 0x0) + var x204 uint64 + x204, _ = p521AddcarryxU64(x80, x200, x203) + var x206 uint64 + var x207 p521Uint1 + x206, x207 = p521AddcarryxU64(x85, x202, 0x0) + var x208 uint64 + x208, _ = p521AddcarryxU64(x86, x204, x207) + var x210 uint64 + var x211 p521Uint1 + x210, x211 = p521AddcarryxU64(x93, x206, 0x0) + var x212 uint64 + x212, _ = p521AddcarryxU64(x94, x208, x211) + var x214 uint64 + var x215 p521Uint1 + x214, x215 = p521AddcarryxU64(x103, x210, 0x0) + var x216 uint64 + x216, _ = p521AddcarryxU64(x104, x212, x215) + var x218 uint64 + var x219 p521Uint1 + x218, x219 = p521AddcarryxU64(x115, x214, 0x0) + var x220 uint64 + x220, _ = p521AddcarryxU64(x116, x216, x219) + var x222 uint64 + var x223 p521Uint1 + x222, x223 = p521AddcarryxU64(x129, x218, 0x0) + var x224 uint64 + x224, _ = p521AddcarryxU64(x130, x220, x223) + var x226 uint64 + var x227 p521Uint1 + x226, x227 = p521AddcarryxU64(x145, x222, 0x0) + var x228 uint64 + x228, _ = p521AddcarryxU64(x146, x224, x227) + var x230 uint64 + var x231 p521Uint1 + x230, x231 = p521AddcarryxU64(x77, x1, 0x0) + var x232 uint64 + x232, _ = p521AddcarryxU64(x78, x2, x231) + var x234 uint64 + var x235 p521Uint1 + x234, x235 = p521AddcarryxU64(x81, x230, 0x0) + var x236 uint64 + x236, _ = p521AddcarryxU64(x82, x232, x235) + var x238 uint64 + var x239 p521Uint1 + x238, x239 = p521AddcarryxU64(x87, x234, 0x0) + var x240 uint64 + x240, _ = p521AddcarryxU64(x88, x236, x239) + var x242 uint64 + var x243 p521Uint1 + x242, x243 = p521AddcarryxU64(x95, x238, 0x0) + var x244 uint64 + x244, _ = p521AddcarryxU64(x96, x240, x243) + var x246 uint64 + var x247 p521Uint1 + x246, x247 = p521AddcarryxU64(x105, x242, 0x0) + var x248 uint64 + x248, _ = p521AddcarryxU64(x106, x244, x247) + var x250 uint64 + var x251 p521Uint1 + x250, x251 = p521AddcarryxU64(x117, x246, 0x0) + var x252 uint64 + x252, _ = p521AddcarryxU64(x118, x248, x251) + var x254 uint64 + var x255 p521Uint1 + x254, x255 = p521AddcarryxU64(x131, x250, 0x0) + var x256 uint64 + x256, _ = p521AddcarryxU64(x132, x252, x255) + var x258 uint64 + var x259 p521Uint1 + x258, x259 = p521AddcarryxU64(x147, x254, 0x0) + var x260 uint64 + x260, _ = p521AddcarryxU64(x148, x256, x259) + var x262 uint64 + var x263 p521Uint1 + x262, x263 = p521AddcarryxU64(x17, x3, 0x0) + var x264 uint64 + x264, _ = p521AddcarryxU64(x18, x4, x263) + var x266 uint64 + var x267 p521Uint1 + x266, x267 = p521AddcarryxU64(x83, x262, 0x0) + var x268 uint64 + x268, _ = p521AddcarryxU64(x84, x264, x267) + var x270 uint64 + var x271 p521Uint1 + x270, x271 = p521AddcarryxU64(x89, x266, 0x0) + var x272 uint64 + x272, _ = p521AddcarryxU64(x90, x268, x271) + var x274 uint64 + var x275 p521Uint1 + x274, x275 = p521AddcarryxU64(x97, x270, 0x0) + var x276 uint64 + x276, _ = p521AddcarryxU64(x98, x272, x275) + var x278 uint64 + var x279 p521Uint1 + x278, x279 = p521AddcarryxU64(x107, x274, 0x0) + var x280 uint64 + x280, _ = p521AddcarryxU64(x108, x276, x279) + var x282 uint64 + var x283 p521Uint1 + x282, x283 = p521AddcarryxU64(x119, x278, 0x0) + var x284 uint64 + x284, _ = p521AddcarryxU64(x120, x280, x283) + var x286 uint64 + var x287 p521Uint1 + x286, x287 = p521AddcarryxU64(x133, x282, 0x0) + var x288 uint64 + x288, _ = p521AddcarryxU64(x134, x284, x287) + var x290 uint64 + var x291 p521Uint1 + x290, x291 = p521AddcarryxU64(x149, x286, 0x0) + var x292 uint64 + x292, _ = p521AddcarryxU64(x150, x288, x291) + var x294 uint64 + var x295 p521Uint1 + x294, x295 = p521AddcarryxU64(x19, x5, 0x0) + var x296 uint64 + x296, _ = p521AddcarryxU64(x20, x6, x295) + var x298 uint64 + var x299 p521Uint1 + x298, x299 = p521AddcarryxU64(x31, x294, 0x0) + var x300 uint64 + x300, _ = p521AddcarryxU64(x32, x296, x299) + var x302 uint64 + var x303 p521Uint1 + x302, x303 = p521AddcarryxU64(x91, x298, 0x0) + var x304 uint64 + x304, _ = p521AddcarryxU64(x92, x300, x303) + var x306 uint64 + var x307 p521Uint1 + x306, x307 = p521AddcarryxU64(x99, x302, 0x0) + var x308 uint64 + x308, _ = p521AddcarryxU64(x100, x304, x307) + var x310 uint64 + var x311 p521Uint1 + x310, x311 = p521AddcarryxU64(x109, x306, 0x0) + var x312 uint64 + x312, _ = p521AddcarryxU64(x110, x308, x311) + var x314 uint64 + var x315 p521Uint1 + x314, x315 = p521AddcarryxU64(x121, x310, 0x0) + var x316 uint64 + x316, _ = p521AddcarryxU64(x122, x312, x315) + var x318 uint64 + var x319 p521Uint1 + x318, x319 = p521AddcarryxU64(x135, x314, 0x0) + var x320 uint64 + x320, _ = p521AddcarryxU64(x136, x316, x319) + var x322 uint64 + var x323 p521Uint1 + x322, x323 = p521AddcarryxU64(x151, x318, 0x0) + var x324 uint64 + x324, _ = p521AddcarryxU64(x152, x320, x323) + var x326 uint64 + var x327 p521Uint1 + x326, x327 = p521AddcarryxU64(x21, x7, 0x0) + var x328 uint64 + x328, _ = p521AddcarryxU64(x22, x8, x327) + var x330 uint64 + var x331 p521Uint1 + x330, x331 = p521AddcarryxU64(x33, x326, 0x0) + var x332 uint64 + x332, _ = p521AddcarryxU64(x34, x328, x331) + var x334 uint64 + var x335 p521Uint1 + x334, x335 = p521AddcarryxU64(x43, x330, 0x0) + var x336 uint64 + x336, _ = p521AddcarryxU64(x44, x332, x335) + var x338 uint64 + var x339 p521Uint1 + x338, x339 = p521AddcarryxU64(x101, x334, 0x0) + var x340 uint64 + x340, _ = p521AddcarryxU64(x102, x336, x339) + var x342 uint64 + var x343 p521Uint1 + x342, x343 = p521AddcarryxU64(x111, x338, 0x0) + var x344 uint64 + x344, _ = p521AddcarryxU64(x112, x340, x343) + var x346 uint64 + var x347 p521Uint1 + x346, x347 = p521AddcarryxU64(x123, x342, 0x0) + var x348 uint64 + x348, _ = p521AddcarryxU64(x124, x344, x347) + var x350 uint64 + var x351 p521Uint1 + x350, x351 = p521AddcarryxU64(x137, x346, 0x0) + var x352 uint64 + x352, _ = p521AddcarryxU64(x138, x348, x351) + var x354 uint64 + var x355 p521Uint1 + x354, x355 = p521AddcarryxU64(x153, x350, 0x0) + var x356 uint64 + x356, _ = p521AddcarryxU64(x154, x352, x355) + var x358 uint64 + var x359 p521Uint1 + x358, x359 = p521AddcarryxU64(x23, x9, 0x0) + var x360 uint64 + x360, _ = p521AddcarryxU64(x24, x10, x359) + var x362 uint64 + var x363 p521Uint1 + x362, x363 = p521AddcarryxU64(x35, x358, 0x0) + var x364 uint64 + x364, _ = p521AddcarryxU64(x36, x360, x363) + var x366 uint64 + var x367 p521Uint1 + x366, x367 = p521AddcarryxU64(x45, x362, 0x0) + var x368 uint64 + x368, _ = p521AddcarryxU64(x46, x364, x367) + var x370 uint64 + var x371 p521Uint1 + x370, x371 = p521AddcarryxU64(x53, x366, 0x0) + var x372 uint64 + x372, _ = p521AddcarryxU64(x54, x368, x371) + var x374 uint64 + var x375 p521Uint1 + x374, x375 = p521AddcarryxU64(x113, x370, 0x0) + var x376 uint64 + x376, _ = p521AddcarryxU64(x114, x372, x375) + var x378 uint64 + var x379 p521Uint1 + x378, x379 = p521AddcarryxU64(x125, x374, 0x0) + var x380 uint64 + x380, _ = p521AddcarryxU64(x126, x376, x379) + var x382 uint64 + var x383 p521Uint1 + x382, x383 = p521AddcarryxU64(x139, x378, 0x0) + var x384 uint64 + x384, _ = p521AddcarryxU64(x140, x380, x383) + var x386 uint64 + var x387 p521Uint1 + x386, x387 = p521AddcarryxU64(x155, x382, 0x0) + var x388 uint64 + x388, _ = p521AddcarryxU64(x156, x384, x387) + var x390 uint64 + var x391 p521Uint1 + x390, x391 = p521AddcarryxU64(x25, x11, 0x0) + var x392 uint64 + x392, _ = p521AddcarryxU64(x26, x12, x391) + var x394 uint64 + var x395 p521Uint1 + x394, x395 = p521AddcarryxU64(x37, x390, 0x0) + var x396 uint64 + x396, _ = p521AddcarryxU64(x38, x392, x395) + var x398 uint64 + var x399 p521Uint1 + x398, x399 = p521AddcarryxU64(x47, x394, 0x0) + var x400 uint64 + x400, _ = p521AddcarryxU64(x48, x396, x399) + var x402 uint64 + var x403 p521Uint1 + x402, x403 = p521AddcarryxU64(x55, x398, 0x0) + var x404 uint64 + x404, _ = p521AddcarryxU64(x56, x400, x403) + var x406 uint64 + var x407 p521Uint1 + x406, x407 = p521AddcarryxU64(x61, x402, 0x0) + var x408 uint64 + x408, _ = p521AddcarryxU64(x62, x404, x407) + var x410 uint64 + var x411 p521Uint1 + x410, x411 = p521AddcarryxU64(x127, x406, 0x0) + var x412 uint64 + x412, _ = p521AddcarryxU64(x128, x408, x411) + var x414 uint64 + var x415 p521Uint1 + x414, x415 = p521AddcarryxU64(x141, x410, 0x0) + var x416 uint64 + x416, _ = p521AddcarryxU64(x142, x412, x415) + var x418 uint64 + var x419 p521Uint1 + x418, x419 = p521AddcarryxU64(x157, x414, 0x0) + var x420 uint64 + x420, _ = p521AddcarryxU64(x158, x416, x419) + var x422 uint64 + var x423 p521Uint1 + x422, x423 = p521AddcarryxU64(x27, x13, 0x0) + var x424 uint64 + x424, _ = p521AddcarryxU64(x28, x14, x423) + var x426 uint64 + var x427 p521Uint1 + x426, x427 = p521AddcarryxU64(x39, x422, 0x0) + var x428 uint64 + x428, _ = p521AddcarryxU64(x40, x424, x427) + var x430 uint64 + var x431 p521Uint1 + x430, x431 = p521AddcarryxU64(x49, x426, 0x0) + var x432 uint64 + x432, _ = p521AddcarryxU64(x50, x428, x431) + var x434 uint64 + var x435 p521Uint1 + x434, x435 = p521AddcarryxU64(x57, x430, 0x0) + var x436 uint64 + x436, _ = p521AddcarryxU64(x58, x432, x435) + var x438 uint64 + var x439 p521Uint1 + x438, x439 = p521AddcarryxU64(x63, x434, 0x0) + var x440 uint64 + x440, _ = p521AddcarryxU64(x64, x436, x439) + var x442 uint64 + var x443 p521Uint1 + x442, x443 = p521AddcarryxU64(x67, x438, 0x0) + var x444 uint64 + x444, _ = p521AddcarryxU64(x68, x440, x443) + var x446 uint64 + var x447 p521Uint1 + x446, x447 = p521AddcarryxU64(x143, x442, 0x0) + var x448 uint64 + x448, _ = p521AddcarryxU64(x144, x444, x447) + var x450 uint64 + var x451 p521Uint1 + x450, x451 = p521AddcarryxU64(x159, x446, 0x0) + var x452 uint64 + x452, _ = p521AddcarryxU64(x160, x448, x451) + var x454 uint64 + var x455 p521Uint1 + x454, x455 = p521AddcarryxU64(x195, x450, 0x0) + var x456 uint64 + x456, _ = p521AddcarryxU64(x196, x452, x455) + x458 := ((x454 >> 58) | ((x456 << 6) & 0xffffffffffffffff)) + x459 := (x456 >> 58) + x460 := (x454 & 0x3ffffffffffffff) + var x461 uint64 + var x462 p521Uint1 + x461, x462 = p521AddcarryxU64(x458, x418, 0x0) + var x463 uint64 + x463, _ = p521AddcarryxU64(x459, x420, x462) + x465 := ((x461 >> 58) | ((x463 << 6) & 0xffffffffffffffff)) + x466 := (x463 >> 58) + x467 := (x461 & 0x3ffffffffffffff) + var x468 uint64 + var x469 p521Uint1 + x468, x469 = p521AddcarryxU64(x465, x386, 0x0) + var x470 uint64 + x470, _ = p521AddcarryxU64(x466, x388, x469) + x472 := ((x468 >> 58) | ((x470 << 6) & 0xffffffffffffffff)) + x473 := (x470 >> 58) + x474 := (x468 & 0x3ffffffffffffff) + var x475 uint64 + var x476 p521Uint1 + x475, x476 = p521AddcarryxU64(x472, x354, 0x0) + var x477 uint64 + x477, _ = p521AddcarryxU64(x473, x356, x476) + x479 := ((x475 >> 58) | ((x477 << 6) & 0xffffffffffffffff)) + x480 := (x477 >> 58) + x481 := (x475 & 0x3ffffffffffffff) + var x482 uint64 + var x483 p521Uint1 + x482, x483 = p521AddcarryxU64(x479, x322, 0x0) + var x484 uint64 + x484, _ = p521AddcarryxU64(x480, x324, x483) + x486 := ((x482 >> 58) | ((x484 << 6) & 0xffffffffffffffff)) + x487 := (x484 >> 58) + x488 := (x482 & 0x3ffffffffffffff) + var x489 uint64 + var x490 p521Uint1 + x489, x490 = p521AddcarryxU64(x486, x290, 0x0) + var x491 uint64 + x491, _ = p521AddcarryxU64(x487, x292, x490) + x493 := ((x489 >> 58) | ((x491 << 6) & 0xffffffffffffffff)) + x494 := (x491 >> 58) + x495 := (x489 & 0x3ffffffffffffff) + var x496 uint64 + var x497 p521Uint1 + x496, x497 = p521AddcarryxU64(x493, x258, 0x0) + var x498 uint64 + x498, _ = p521AddcarryxU64(x494, x260, x497) + x500 := ((x496 >> 58) | ((x498 << 6) & 0xffffffffffffffff)) + x501 := (x498 >> 58) + x502 := (x496 & 0x3ffffffffffffff) + var x503 uint64 + var x504 p521Uint1 + x503, x504 = p521AddcarryxU64(x500, x226, 0x0) + var x505 uint64 + x505, _ = p521AddcarryxU64(x501, x228, x504) + x507 := ((x503 >> 57) | ((x505 << 7) & 0xffffffffffffffff)) + x508 := (x505 >> 57) + x509 := (x503 & 0x1ffffffffffffff) + var x510 uint64 + var x511 p521Uint1 + x510, x511 = p521AddcarryxU64(x197, x507, 0x0) + x512 := (uint64(x511) + x508) + x513 := ((x510 >> 58) | ((x512 << 6) & 0xffffffffffffffff)) + x514 := (x510 & 0x3ffffffffffffff) + x515 := (x513 + x460) + x516 := p521Uint1((x515 >> 58)) + x517 := (x515 & 0x3ffffffffffffff) + x518 := (uint64(x516) + x467) + out1[0] = x514 + out1[1] = x517 + out1[2] = x518 + out1[3] = x474 + out1[4] = x481 + out1[5] = x488 + out1[6] = x495 + out1[7] = x502 + out1[8] = x509 +} + +// p521CarrySquare squares a field element and reduces the result. +// +// Postconditions: +// eval out1 mod m = (eval arg1 * eval arg1) mod m +// +// Input Bounds: +// arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] +// Output Bounds: +// out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +func p521CarrySquare(out1 *[9]uint64, arg1 *[9]uint64) { + x1 := arg1[8] + x2 := (x1 * 0x2) + x3 := (arg1[8] * 0x2) + x4 := arg1[7] + x5 := (x4 * 0x2) + x6 := (arg1[7] * 0x2) + x7 := arg1[6] + x8 := (x7 * 0x2) + x9 := (arg1[6] * 0x2) + x10 := arg1[5] + x11 := (x10 * 0x2) + x12 := (arg1[5] * 0x2) + x13 := (arg1[4] * 0x2) + x14 := (arg1[3] * 0x2) + x15 := (arg1[2] * 0x2) + x16 := (arg1[1] * 0x2) + var x17 uint64 + var x18 uint64 + x18, x17 = bits.Mul64(arg1[8], (x1 * 0x2)) + var x19 uint64 + var x20 uint64 + x20, x19 = bits.Mul64(arg1[7], (x2 * 0x2)) + var x21 uint64 + var x22 uint64 + x22, x21 = bits.Mul64(arg1[7], (x4 * 0x2)) + var x23 uint64 + var x24 uint64 + x24, x23 = bits.Mul64(arg1[6], (x2 * 0x2)) + var x25 uint64 + var x26 uint64 + x26, x25 = bits.Mul64(arg1[6], (x5 * 0x2)) + var x27 uint64 + var x28 uint64 + x28, x27 = bits.Mul64(arg1[6], (x7 * 0x2)) + var x29 uint64 + var x30 uint64 + x30, x29 = bits.Mul64(arg1[5], (x2 * 0x2)) + var x31 uint64 + var x32 uint64 + x32, x31 = bits.Mul64(arg1[5], (x5 * 0x2)) + var x33 uint64 + var x34 uint64 + x34, x33 = bits.Mul64(arg1[5], (x8 * 0x2)) + var x35 uint64 + var x36 uint64 + x36, x35 = bits.Mul64(arg1[5], (x10 * 0x2)) + var x37 uint64 + var x38 uint64 + x38, x37 = bits.Mul64(arg1[4], (x2 * 0x2)) + var x39 uint64 + var x40 uint64 + x40, x39 = bits.Mul64(arg1[4], (x5 * 0x2)) + var x41 uint64 + var x42 uint64 + x42, x41 = bits.Mul64(arg1[4], (x8 * 0x2)) + var x43 uint64 + var x44 uint64 + x44, x43 = bits.Mul64(arg1[4], (x11 * 0x2)) + var x45 uint64 + var x46 uint64 + x46, x45 = bits.Mul64(arg1[4], arg1[4]) + var x47 uint64 + var x48 uint64 + x48, x47 = bits.Mul64(arg1[3], (x2 * 0x2)) + var x49 uint64 + var x50 uint64 + x50, x49 = bits.Mul64(arg1[3], (x5 * 0x2)) + var x51 uint64 + var x52 uint64 + x52, x51 = bits.Mul64(arg1[3], (x8 * 0x2)) + var x53 uint64 + var x54 uint64 + x54, x53 = bits.Mul64(arg1[3], x12) + var x55 uint64 + var x56 uint64 + x56, x55 = bits.Mul64(arg1[3], x13) + var x57 uint64 + var x58 uint64 + x58, x57 = bits.Mul64(arg1[3], arg1[3]) + var x59 uint64 + var x60 uint64 + x60, x59 = bits.Mul64(arg1[2], (x2 * 0x2)) + var x61 uint64 + var x62 uint64 + x62, x61 = bits.Mul64(arg1[2], (x5 * 0x2)) + var x63 uint64 + var x64 uint64 + x64, x63 = bits.Mul64(arg1[2], x9) + var x65 uint64 + var x66 uint64 + x66, x65 = bits.Mul64(arg1[2], x12) + var x67 uint64 + var x68 uint64 + x68, x67 = bits.Mul64(arg1[2], x13) + var x69 uint64 + var x70 uint64 + x70, x69 = bits.Mul64(arg1[2], x14) + var x71 uint64 + var x72 uint64 + x72, x71 = bits.Mul64(arg1[2], arg1[2]) + var x73 uint64 + var x74 uint64 + x74, x73 = bits.Mul64(arg1[1], (x2 * 0x2)) + var x75 uint64 + var x76 uint64 + x76, x75 = bits.Mul64(arg1[1], x6) + var x77 uint64 + var x78 uint64 + x78, x77 = bits.Mul64(arg1[1], x9) + var x79 uint64 + var x80 uint64 + x80, x79 = bits.Mul64(arg1[1], x12) + var x81 uint64 + var x82 uint64 + x82, x81 = bits.Mul64(arg1[1], x13) + var x83 uint64 + var x84 uint64 + x84, x83 = bits.Mul64(arg1[1], x14) + var x85 uint64 + var x86 uint64 + x86, x85 = bits.Mul64(arg1[1], x15) + var x87 uint64 + var x88 uint64 + x88, x87 = bits.Mul64(arg1[1], arg1[1]) + var x89 uint64 + var x90 uint64 + x90, x89 = bits.Mul64(arg1[0], x3) + var x91 uint64 + var x92 uint64 + x92, x91 = bits.Mul64(arg1[0], x6) + var x93 uint64 + var x94 uint64 + x94, x93 = bits.Mul64(arg1[0], x9) + var x95 uint64 + var x96 uint64 + x96, x95 = bits.Mul64(arg1[0], x12) + var x97 uint64 + var x98 uint64 + x98, x97 = bits.Mul64(arg1[0], x13) + var x99 uint64 + var x100 uint64 + x100, x99 = bits.Mul64(arg1[0], x14) + var x101 uint64 + var x102 uint64 + x102, x101 = bits.Mul64(arg1[0], x15) + var x103 uint64 + var x104 uint64 + x104, x103 = bits.Mul64(arg1[0], x16) + var x105 uint64 + var x106 uint64 + x106, x105 = bits.Mul64(arg1[0], arg1[0]) + var x107 uint64 + var x108 p521Uint1 + x107, x108 = p521AddcarryxU64(x51, x43, 0x0) + var x109 uint64 + x109, _ = p521AddcarryxU64(x52, x44, x108) + var x111 uint64 + var x112 p521Uint1 + x111, x112 = p521AddcarryxU64(x61, x107, 0x0) + var x113 uint64 + x113, _ = p521AddcarryxU64(x62, x109, x112) + var x115 uint64 + var x116 p521Uint1 + x115, x116 = p521AddcarryxU64(x73, x111, 0x0) + var x117 uint64 + x117, _ = p521AddcarryxU64(x74, x113, x116) + var x119 uint64 + var x120 p521Uint1 + x119, x120 = p521AddcarryxU64(x105, x115, 0x0) + var x121 uint64 + x121, _ = p521AddcarryxU64(x106, x117, x120) + x123 := ((x119 >> 58) | ((x121 << 6) & 0xffffffffffffffff)) + x124 := (x121 >> 58) + x125 := (x119 & 0x3ffffffffffffff) + var x126 uint64 + var x127 p521Uint1 + x126, x127 = p521AddcarryxU64(x53, x45, 0x0) + var x128 uint64 + x128, _ = p521AddcarryxU64(x54, x46, x127) + var x130 uint64 + var x131 p521Uint1 + x130, x131 = p521AddcarryxU64(x63, x126, 0x0) + var x132 uint64 + x132, _ = p521AddcarryxU64(x64, x128, x131) + var x134 uint64 + var x135 p521Uint1 + x134, x135 = p521AddcarryxU64(x75, x130, 0x0) + var x136 uint64 + x136, _ = p521AddcarryxU64(x76, x132, x135) + var x138 uint64 + var x139 p521Uint1 + x138, x139 = p521AddcarryxU64(x89, x134, 0x0) + var x140 uint64 + x140, _ = p521AddcarryxU64(x90, x136, x139) + var x142 uint64 + var x143 p521Uint1 + x142, x143 = p521AddcarryxU64(x55, x17, 0x0) + var x144 uint64 + x144, _ = p521AddcarryxU64(x56, x18, x143) + var x146 uint64 + var x147 p521Uint1 + x146, x147 = p521AddcarryxU64(x65, x142, 0x0) + var x148 uint64 + x148, _ = p521AddcarryxU64(x66, x144, x147) + var x150 uint64 + var x151 p521Uint1 + x150, x151 = p521AddcarryxU64(x77, x146, 0x0) + var x152 uint64 + x152, _ = p521AddcarryxU64(x78, x148, x151) + var x154 uint64 + var x155 p521Uint1 + x154, x155 = p521AddcarryxU64(x91, x150, 0x0) + var x156 uint64 + x156, _ = p521AddcarryxU64(x92, x152, x155) + var x158 uint64 + var x159 p521Uint1 + x158, x159 = p521AddcarryxU64(x57, x19, 0x0) + var x160 uint64 + x160, _ = p521AddcarryxU64(x58, x20, x159) + var x162 uint64 + var x163 p521Uint1 + x162, x163 = p521AddcarryxU64(x67, x158, 0x0) + var x164 uint64 + x164, _ = p521AddcarryxU64(x68, x160, x163) + var x166 uint64 + var x167 p521Uint1 + x166, x167 = p521AddcarryxU64(x79, x162, 0x0) + var x168 uint64 + x168, _ = p521AddcarryxU64(x80, x164, x167) + var x170 uint64 + var x171 p521Uint1 + x170, x171 = p521AddcarryxU64(x93, x166, 0x0) + var x172 uint64 + x172, _ = p521AddcarryxU64(x94, x168, x171) + var x174 uint64 + var x175 p521Uint1 + x174, x175 = p521AddcarryxU64(x23, x21, 0x0) + var x176 uint64 + x176, _ = p521AddcarryxU64(x24, x22, x175) + var x178 uint64 + var x179 p521Uint1 + x178, x179 = p521AddcarryxU64(x69, x174, 0x0) + var x180 uint64 + x180, _ = p521AddcarryxU64(x70, x176, x179) + var x182 uint64 + var x183 p521Uint1 + x182, x183 = p521AddcarryxU64(x81, x178, 0x0) + var x184 uint64 + x184, _ = p521AddcarryxU64(x82, x180, x183) + var x186 uint64 + var x187 p521Uint1 + x186, x187 = p521AddcarryxU64(x95, x182, 0x0) + var x188 uint64 + x188, _ = p521AddcarryxU64(x96, x184, x187) + var x190 uint64 + var x191 p521Uint1 + x190, x191 = p521AddcarryxU64(x29, x25, 0x0) + var x192 uint64 + x192, _ = p521AddcarryxU64(x30, x26, x191) + var x194 uint64 + var x195 p521Uint1 + x194, x195 = p521AddcarryxU64(x71, x190, 0x0) + var x196 uint64 + x196, _ = p521AddcarryxU64(x72, x192, x195) + var x198 uint64 + var x199 p521Uint1 + x198, x199 = p521AddcarryxU64(x83, x194, 0x0) + var x200 uint64 + x200, _ = p521AddcarryxU64(x84, x196, x199) + var x202 uint64 + var x203 p521Uint1 + x202, x203 = p521AddcarryxU64(x97, x198, 0x0) + var x204 uint64 + x204, _ = p521AddcarryxU64(x98, x200, x203) + var x206 uint64 + var x207 p521Uint1 + x206, x207 = p521AddcarryxU64(x31, x27, 0x0) + var x208 uint64 + x208, _ = p521AddcarryxU64(x32, x28, x207) + var x210 uint64 + var x211 p521Uint1 + x210, x211 = p521AddcarryxU64(x37, x206, 0x0) + var x212 uint64 + x212, _ = p521AddcarryxU64(x38, x208, x211) + var x214 uint64 + var x215 p521Uint1 + x214, x215 = p521AddcarryxU64(x85, x210, 0x0) + var x216 uint64 + x216, _ = p521AddcarryxU64(x86, x212, x215) + var x218 uint64 + var x219 p521Uint1 + x218, x219 = p521AddcarryxU64(x99, x214, 0x0) + var x220 uint64 + x220, _ = p521AddcarryxU64(x100, x216, x219) + var x222 uint64 + var x223 p521Uint1 + x222, x223 = p521AddcarryxU64(x39, x33, 0x0) + var x224 uint64 + x224, _ = p521AddcarryxU64(x40, x34, x223) + var x226 uint64 + var x227 p521Uint1 + x226, x227 = p521AddcarryxU64(x47, x222, 0x0) + var x228 uint64 + x228, _ = p521AddcarryxU64(x48, x224, x227) + var x230 uint64 + var x231 p521Uint1 + x230, x231 = p521AddcarryxU64(x87, x226, 0x0) + var x232 uint64 + x232, _ = p521AddcarryxU64(x88, x228, x231) + var x234 uint64 + var x235 p521Uint1 + x234, x235 = p521AddcarryxU64(x101, x230, 0x0) + var x236 uint64 + x236, _ = p521AddcarryxU64(x102, x232, x235) + var x238 uint64 + var x239 p521Uint1 + x238, x239 = p521AddcarryxU64(x41, x35, 0x0) + var x240 uint64 + x240, _ = p521AddcarryxU64(x42, x36, x239) + var x242 uint64 + var x243 p521Uint1 + x242, x243 = p521AddcarryxU64(x49, x238, 0x0) + var x244 uint64 + x244, _ = p521AddcarryxU64(x50, x240, x243) + var x246 uint64 + var x247 p521Uint1 + x246, x247 = p521AddcarryxU64(x59, x242, 0x0) + var x248 uint64 + x248, _ = p521AddcarryxU64(x60, x244, x247) + var x250 uint64 + var x251 p521Uint1 + x250, x251 = p521AddcarryxU64(x103, x246, 0x0) + var x252 uint64 + x252, _ = p521AddcarryxU64(x104, x248, x251) + var x254 uint64 + var x255 p521Uint1 + x254, x255 = p521AddcarryxU64(x123, x250, 0x0) + var x256 uint64 + x256, _ = p521AddcarryxU64(x124, x252, x255) + x258 := ((x254 >> 58) | ((x256 << 6) & 0xffffffffffffffff)) + x259 := (x256 >> 58) + x260 := (x254 & 0x3ffffffffffffff) + var x261 uint64 + var x262 p521Uint1 + x261, x262 = p521AddcarryxU64(x258, x234, 0x0) + var x263 uint64 + x263, _ = p521AddcarryxU64(x259, x236, x262) + x265 := ((x261 >> 58) | ((x263 << 6) & 0xffffffffffffffff)) + x266 := (x263 >> 58) + x267 := (x261 & 0x3ffffffffffffff) + var x268 uint64 + var x269 p521Uint1 + x268, x269 = p521AddcarryxU64(x265, x218, 0x0) + var x270 uint64 + x270, _ = p521AddcarryxU64(x266, x220, x269) + x272 := ((x268 >> 58) | ((x270 << 6) & 0xffffffffffffffff)) + x273 := (x270 >> 58) + x274 := (x268 & 0x3ffffffffffffff) + var x275 uint64 + var x276 p521Uint1 + x275, x276 = p521AddcarryxU64(x272, x202, 0x0) + var x277 uint64 + x277, _ = p521AddcarryxU64(x273, x204, x276) + x279 := ((x275 >> 58) | ((x277 << 6) & 0xffffffffffffffff)) + x280 := (x277 >> 58) + x281 := (x275 & 0x3ffffffffffffff) + var x282 uint64 + var x283 p521Uint1 + x282, x283 = p521AddcarryxU64(x279, x186, 0x0) + var x284 uint64 + x284, _ = p521AddcarryxU64(x280, x188, x283) + x286 := ((x282 >> 58) | ((x284 << 6) & 0xffffffffffffffff)) + x287 := (x284 >> 58) + x288 := (x282 & 0x3ffffffffffffff) + var x289 uint64 + var x290 p521Uint1 + x289, x290 = p521AddcarryxU64(x286, x170, 0x0) + var x291 uint64 + x291, _ = p521AddcarryxU64(x287, x172, x290) + x293 := ((x289 >> 58) | ((x291 << 6) & 0xffffffffffffffff)) + x294 := (x291 >> 58) + x295 := (x289 & 0x3ffffffffffffff) + var x296 uint64 + var x297 p521Uint1 + x296, x297 = p521AddcarryxU64(x293, x154, 0x0) + var x298 uint64 + x298, _ = p521AddcarryxU64(x294, x156, x297) + x300 := ((x296 >> 58) | ((x298 << 6) & 0xffffffffffffffff)) + x301 := (x298 >> 58) + x302 := (x296 & 0x3ffffffffffffff) + var x303 uint64 + var x304 p521Uint1 + x303, x304 = p521AddcarryxU64(x300, x138, 0x0) + var x305 uint64 + x305, _ = p521AddcarryxU64(x301, x140, x304) + x307 := ((x303 >> 57) | ((x305 << 7) & 0xffffffffffffffff)) + x308 := (x305 >> 57) + x309 := (x303 & 0x1ffffffffffffff) + var x310 uint64 + var x311 p521Uint1 + x310, x311 = p521AddcarryxU64(x125, x307, 0x0) + x312 := (uint64(x311) + x308) + x313 := ((x310 >> 58) | ((x312 << 6) & 0xffffffffffffffff)) + x314 := (x310 & 0x3ffffffffffffff) + x315 := (x313 + x260) + x316 := p521Uint1((x315 >> 58)) + x317 := (x315 & 0x3ffffffffffffff) + x318 := (uint64(x316) + x267) + out1[0] = x314 + out1[1] = x317 + out1[2] = x318 + out1[3] = x274 + out1[4] = x281 + out1[5] = x288 + out1[6] = x295 + out1[7] = x302 + out1[8] = x309 +} + +// p521Carry reduces a field element. +// +// Postconditions: +// eval out1 mod m = eval arg1 mod m +// +// Input Bounds: +// arg1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] +// Output Bounds: +// out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +func p521Carry(out1 *[9]uint64, arg1 *[9]uint64) { + x1 := arg1[0] + x2 := ((x1 >> 58) + arg1[1]) + x3 := ((x2 >> 58) + arg1[2]) + x4 := ((x3 >> 58) + arg1[3]) + x5 := ((x4 >> 58) + arg1[4]) + x6 := ((x5 >> 58) + arg1[5]) + x7 := ((x6 >> 58) + arg1[6]) + x8 := ((x7 >> 58) + arg1[7]) + x9 := ((x8 >> 58) + arg1[8]) + x10 := ((x1 & 0x3ffffffffffffff) + (x9 >> 57)) + x11 := (uint64(p521Uint1((x10 >> 58))) + (x2 & 0x3ffffffffffffff)) + x12 := (x10 & 0x3ffffffffffffff) + x13 := (x11 & 0x3ffffffffffffff) + x14 := (uint64(p521Uint1((x11 >> 58))) + (x3 & 0x3ffffffffffffff)) + x15 := (x4 & 0x3ffffffffffffff) + x16 := (x5 & 0x3ffffffffffffff) + x17 := (x6 & 0x3ffffffffffffff) + x18 := (x7 & 0x3ffffffffffffff) + x19 := (x8 & 0x3ffffffffffffff) + x20 := (x9 & 0x1ffffffffffffff) + out1[0] = x12 + out1[1] = x13 + out1[2] = x14 + out1[3] = x15 + out1[4] = x16 + out1[5] = x17 + out1[6] = x18 + out1[7] = x19 + out1[8] = x20 +} + +// p521Add adds two field elements. +// +// Postconditions: +// eval out1 mod m = (eval arg1 + eval arg2) mod m +// +// Input Bounds: +// arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +// arg2: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +// Output Bounds: +// out1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] +func p521Add(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) { + x1 := (arg1[0] + arg2[0]) + x2 := (arg1[1] + arg2[1]) + x3 := (arg1[2] + arg2[2]) + x4 := (arg1[3] + arg2[3]) + x5 := (arg1[4] + arg2[4]) + x6 := (arg1[5] + arg2[5]) + x7 := (arg1[6] + arg2[6]) + x8 := (arg1[7] + arg2[7]) + x9 := (arg1[8] + arg2[8]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 + out1[6] = x7 + out1[7] = x8 + out1[8] = x9 +} + +// p521Sub subtracts two field elements. +// +// Postconditions: +// eval out1 mod m = (eval arg1 - eval arg2) mod m +// +// Input Bounds: +// arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +// arg2: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +// Output Bounds: +// out1: [[0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0xc00000000000000], [0x0 ~> 0x600000000000000]] +func p521Sub(out1 *[9]uint64, arg1 *[9]uint64, arg2 *[9]uint64) { + x1 := ((0x7fffffffffffffe + arg1[0]) - arg2[0]) + x2 := ((0x7fffffffffffffe + arg1[1]) - arg2[1]) + x3 := ((0x7fffffffffffffe + arg1[2]) - arg2[2]) + x4 := ((0x7fffffffffffffe + arg1[3]) - arg2[3]) + x5 := ((0x7fffffffffffffe + arg1[4]) - arg2[4]) + x6 := ((0x7fffffffffffffe + arg1[5]) - arg2[5]) + x7 := ((0x7fffffffffffffe + arg1[6]) - arg2[6]) + x8 := ((0x7fffffffffffffe + arg1[7]) - arg2[7]) + x9 := ((0x3fffffffffffffe + arg1[8]) - arg2[8]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 + out1[6] = x7 + out1[7] = x8 + out1[8] = x9 +} + +// p521ToBytes serializes a field element to bytes in little-endian order. +// +// Postconditions: +// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..65] +// +// Input Bounds: +// arg1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +// Output Bounds: +// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1]] +func p521ToBytes(out1 *[66]uint8, arg1 *[9]uint64) { + var x1 uint64 + var x2 p521Uint1 + p521SubborrowxU58(&x1, &x2, 0x0, arg1[0], 0x3ffffffffffffff) + var x3 uint64 + var x4 p521Uint1 + p521SubborrowxU58(&x3, &x4, x2, arg1[1], 0x3ffffffffffffff) + var x5 uint64 + var x6 p521Uint1 + p521SubborrowxU58(&x5, &x6, x4, arg1[2], 0x3ffffffffffffff) + var x7 uint64 + var x8 p521Uint1 + p521SubborrowxU58(&x7, &x8, x6, arg1[3], 0x3ffffffffffffff) + var x9 uint64 + var x10 p521Uint1 + p521SubborrowxU58(&x9, &x10, x8, arg1[4], 0x3ffffffffffffff) + var x11 uint64 + var x12 p521Uint1 + p521SubborrowxU58(&x11, &x12, x10, arg1[5], 0x3ffffffffffffff) + var x13 uint64 + var x14 p521Uint1 + p521SubborrowxU58(&x13, &x14, x12, arg1[6], 0x3ffffffffffffff) + var x15 uint64 + var x16 p521Uint1 + p521SubborrowxU58(&x15, &x16, x14, arg1[7], 0x3ffffffffffffff) + var x17 uint64 + var x18 p521Uint1 + p521SubborrowxU57(&x17, &x18, x16, arg1[8], 0x1ffffffffffffff) + var x19 uint64 + p521CmovznzU64(&x19, x18, uint64(0x0), 0xffffffffffffffff) + var x20 uint64 + var x21 p521Uint1 + p521AddcarryxU58(&x20, &x21, 0x0, x1, (x19 & 0x3ffffffffffffff)) + var x22 uint64 + var x23 p521Uint1 + p521AddcarryxU58(&x22, &x23, x21, x3, (x19 & 0x3ffffffffffffff)) + var x24 uint64 + var x25 p521Uint1 + p521AddcarryxU58(&x24, &x25, x23, x5, (x19 & 0x3ffffffffffffff)) + var x26 uint64 + var x27 p521Uint1 + p521AddcarryxU58(&x26, &x27, x25, x7, (x19 & 0x3ffffffffffffff)) + var x28 uint64 + var x29 p521Uint1 + p521AddcarryxU58(&x28, &x29, x27, x9, (x19 & 0x3ffffffffffffff)) + var x30 uint64 + var x31 p521Uint1 + p521AddcarryxU58(&x30, &x31, x29, x11, (x19 & 0x3ffffffffffffff)) + var x32 uint64 + var x33 p521Uint1 + p521AddcarryxU58(&x32, &x33, x31, x13, (x19 & 0x3ffffffffffffff)) + var x34 uint64 + var x35 p521Uint1 + p521AddcarryxU58(&x34, &x35, x33, x15, (x19 & 0x3ffffffffffffff)) + var x36 uint64 + var x37 p521Uint1 + p521AddcarryxU57(&x36, &x37, x35, x17, (x19 & 0x1ffffffffffffff)) + x38 := (x34 << 6) + x39 := (x32 << 4) + x40 := (x30 << 2) + x41 := (x26 << 6) + x42 := (x24 << 4) + x43 := (x22 << 2) + x44 := (uint8(x20) & 0xff) + x45 := (x20 >> 8) + x46 := (uint8(x45) & 0xff) + x47 := (x45 >> 8) + x48 := (uint8(x47) & 0xff) + x49 := (x47 >> 8) + x50 := (uint8(x49) & 0xff) + x51 := (x49 >> 8) + x52 := (uint8(x51) & 0xff) + x53 := (x51 >> 8) + x54 := (uint8(x53) & 0xff) + x55 := (x53 >> 8) + x56 := (uint8(x55) & 0xff) + x57 := uint8((x55 >> 8)) + x58 := (x43 + uint64(x57)) + x59 := (uint8(x58) & 0xff) + x60 := (x58 >> 8) + x61 := (uint8(x60) & 0xff) + x62 := (x60 >> 8) + x63 := (uint8(x62) & 0xff) + x64 := (x62 >> 8) + x65 := (uint8(x64) & 0xff) + x66 := (x64 >> 8) + x67 := (uint8(x66) & 0xff) + x68 := (x66 >> 8) + x69 := (uint8(x68) & 0xff) + x70 := (x68 >> 8) + x71 := (uint8(x70) & 0xff) + x72 := uint8((x70 >> 8)) + x73 := (x42 + uint64(x72)) + x74 := (uint8(x73) & 0xff) + x75 := (x73 >> 8) + x76 := (uint8(x75) & 0xff) + x77 := (x75 >> 8) + x78 := (uint8(x77) & 0xff) + x79 := (x77 >> 8) + x80 := (uint8(x79) & 0xff) + x81 := (x79 >> 8) + x82 := (uint8(x81) & 0xff) + x83 := (x81 >> 8) + x84 := (uint8(x83) & 0xff) + x85 := (x83 >> 8) + x86 := (uint8(x85) & 0xff) + x87 := uint8((x85 >> 8)) + x88 := (x41 + uint64(x87)) + x89 := (uint8(x88) & 0xff) + x90 := (x88 >> 8) + x91 := (uint8(x90) & 0xff) + x92 := (x90 >> 8) + x93 := (uint8(x92) & 0xff) + x94 := (x92 >> 8) + x95 := (uint8(x94) & 0xff) + x96 := (x94 >> 8) + x97 := (uint8(x96) & 0xff) + x98 := (x96 >> 8) + x99 := (uint8(x98) & 0xff) + x100 := (x98 >> 8) + x101 := (uint8(x100) & 0xff) + x102 := uint8((x100 >> 8)) + x103 := (uint8(x28) & 0xff) + x104 := (x28 >> 8) + x105 := (uint8(x104) & 0xff) + x106 := (x104 >> 8) + x107 := (uint8(x106) & 0xff) + x108 := (x106 >> 8) + x109 := (uint8(x108) & 0xff) + x110 := (x108 >> 8) + x111 := (uint8(x110) & 0xff) + x112 := (x110 >> 8) + x113 := (uint8(x112) & 0xff) + x114 := (x112 >> 8) + x115 := (uint8(x114) & 0xff) + x116 := uint8((x114 >> 8)) + x117 := (x40 + uint64(x116)) + x118 := (uint8(x117) & 0xff) + x119 := (x117 >> 8) + x120 := (uint8(x119) & 0xff) + x121 := (x119 >> 8) + x122 := (uint8(x121) & 0xff) + x123 := (x121 >> 8) + x124 := (uint8(x123) & 0xff) + x125 := (x123 >> 8) + x126 := (uint8(x125) & 0xff) + x127 := (x125 >> 8) + x128 := (uint8(x127) & 0xff) + x129 := (x127 >> 8) + x130 := (uint8(x129) & 0xff) + x131 := uint8((x129 >> 8)) + x132 := (x39 + uint64(x131)) + x133 := (uint8(x132) & 0xff) + x134 := (x132 >> 8) + x135 := (uint8(x134) & 0xff) + x136 := (x134 >> 8) + x137 := (uint8(x136) & 0xff) + x138 := (x136 >> 8) + x139 := (uint8(x138) & 0xff) + x140 := (x138 >> 8) + x141 := (uint8(x140) & 0xff) + x142 := (x140 >> 8) + x143 := (uint8(x142) & 0xff) + x144 := (x142 >> 8) + x145 := (uint8(x144) & 0xff) + x146 := uint8((x144 >> 8)) + x147 := (x38 + uint64(x146)) + x148 := (uint8(x147) & 0xff) + x149 := (x147 >> 8) + x150 := (uint8(x149) & 0xff) + x151 := (x149 >> 8) + x152 := (uint8(x151) & 0xff) + x153 := (x151 >> 8) + x154 := (uint8(x153) & 0xff) + x155 := (x153 >> 8) + x156 := (uint8(x155) & 0xff) + x157 := (x155 >> 8) + x158 := (uint8(x157) & 0xff) + x159 := (x157 >> 8) + x160 := (uint8(x159) & 0xff) + x161 := uint8((x159 >> 8)) + x162 := (uint8(x36) & 0xff) + x163 := (x36 >> 8) + x164 := (uint8(x163) & 0xff) + x165 := (x163 >> 8) + x166 := (uint8(x165) & 0xff) + x167 := (x165 >> 8) + x168 := (uint8(x167) & 0xff) + x169 := (x167 >> 8) + x170 := (uint8(x169) & 0xff) + x171 := (x169 >> 8) + x172 := (uint8(x171) & 0xff) + x173 := (x171 >> 8) + x174 := (uint8(x173) & 0xff) + x175 := p521Uint1((x173 >> 8)) + out1[0] = x44 + out1[1] = x46 + out1[2] = x48 + out1[3] = x50 + out1[4] = x52 + out1[5] = x54 + out1[6] = x56 + out1[7] = x59 + out1[8] = x61 + out1[9] = x63 + out1[10] = x65 + out1[11] = x67 + out1[12] = x69 + out1[13] = x71 + out1[14] = x74 + out1[15] = x76 + out1[16] = x78 + out1[17] = x80 + out1[18] = x82 + out1[19] = x84 + out1[20] = x86 + out1[21] = x89 + out1[22] = x91 + out1[23] = x93 + out1[24] = x95 + out1[25] = x97 + out1[26] = x99 + out1[27] = x101 + out1[28] = x102 + out1[29] = x103 + out1[30] = x105 + out1[31] = x107 + out1[32] = x109 + out1[33] = x111 + out1[34] = x113 + out1[35] = x115 + out1[36] = x118 + out1[37] = x120 + out1[38] = x122 + out1[39] = x124 + out1[40] = x126 + out1[41] = x128 + out1[42] = x130 + out1[43] = x133 + out1[44] = x135 + out1[45] = x137 + out1[46] = x139 + out1[47] = x141 + out1[48] = x143 + out1[49] = x145 + out1[50] = x148 + out1[51] = x150 + out1[52] = x152 + out1[53] = x154 + out1[54] = x156 + out1[55] = x158 + out1[56] = x160 + out1[57] = x161 + out1[58] = x162 + out1[59] = x164 + out1[60] = x166 + out1[61] = x168 + out1[62] = x170 + out1[63] = x172 + out1[64] = x174 + out1[65] = uint8(x175) +} + +// p521FromBytes deserializes a field element from bytes in little-endian order. +// +// Postconditions: +// eval out1 mod m = bytes_eval arg1 mod m +// +// Input Bounds: +// arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1]] +// Output Bounds: +// out1: [[0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x400000000000000], [0x0 ~> 0x200000000000000]] +func p521FromBytes(out1 *[9]uint64, arg1 *[66]uint8) { + x1 := (uint64(p521Uint1(arg1[65])) << 56) + x2 := (uint64(arg1[64]) << 48) + x3 := (uint64(arg1[63]) << 40) + x4 := (uint64(arg1[62]) << 32) + x5 := (uint64(arg1[61]) << 24) + x6 := (uint64(arg1[60]) << 16) + x7 := (uint64(arg1[59]) << 8) + x8 := arg1[58] + x9 := (uint64(arg1[57]) << 50) + x10 := (uint64(arg1[56]) << 42) + x11 := (uint64(arg1[55]) << 34) + x12 := (uint64(arg1[54]) << 26) + x13 := (uint64(arg1[53]) << 18) + x14 := (uint64(arg1[52]) << 10) + x15 := (uint64(arg1[51]) << 2) + x16 := (uint64(arg1[50]) << 52) + x17 := (uint64(arg1[49]) << 44) + x18 := (uint64(arg1[48]) << 36) + x19 := (uint64(arg1[47]) << 28) + x20 := (uint64(arg1[46]) << 20) + x21 := (uint64(arg1[45]) << 12) + x22 := (uint64(arg1[44]) << 4) + x23 := (uint64(arg1[43]) << 54) + x24 := (uint64(arg1[42]) << 46) + x25 := (uint64(arg1[41]) << 38) + x26 := (uint64(arg1[40]) << 30) + x27 := (uint64(arg1[39]) << 22) + x28 := (uint64(arg1[38]) << 14) + x29 := (uint64(arg1[37]) << 6) + x30 := (uint64(arg1[36]) << 56) + x31 := (uint64(arg1[35]) << 48) + x32 := (uint64(arg1[34]) << 40) + x33 := (uint64(arg1[33]) << 32) + x34 := (uint64(arg1[32]) << 24) + x35 := (uint64(arg1[31]) << 16) + x36 := (uint64(arg1[30]) << 8) + x37 := arg1[29] + x38 := (uint64(arg1[28]) << 50) + x39 := (uint64(arg1[27]) << 42) + x40 := (uint64(arg1[26]) << 34) + x41 := (uint64(arg1[25]) << 26) + x42 := (uint64(arg1[24]) << 18) + x43 := (uint64(arg1[23]) << 10) + x44 := (uint64(arg1[22]) << 2) + x45 := (uint64(arg1[21]) << 52) + x46 := (uint64(arg1[20]) << 44) + x47 := (uint64(arg1[19]) << 36) + x48 := (uint64(arg1[18]) << 28) + x49 := (uint64(arg1[17]) << 20) + x50 := (uint64(arg1[16]) << 12) + x51 := (uint64(arg1[15]) << 4) + x52 := (uint64(arg1[14]) << 54) + x53 := (uint64(arg1[13]) << 46) + x54 := (uint64(arg1[12]) << 38) + x55 := (uint64(arg1[11]) << 30) + x56 := (uint64(arg1[10]) << 22) + x57 := (uint64(arg1[9]) << 14) + x58 := (uint64(arg1[8]) << 6) + x59 := (uint64(arg1[7]) << 56) + x60 := (uint64(arg1[6]) << 48) + x61 := (uint64(arg1[5]) << 40) + x62 := (uint64(arg1[4]) << 32) + x63 := (uint64(arg1[3]) << 24) + x64 := (uint64(arg1[2]) << 16) + x65 := (uint64(arg1[1]) << 8) + x66 := arg1[0] + x67 := (x65 + uint64(x66)) + x68 := (x64 + x67) + x69 := (x63 + x68) + x70 := (x62 + x69) + x71 := (x61 + x70) + x72 := (x60 + x71) + x73 := (x59 + x72) + x74 := (x73 & 0x3ffffffffffffff) + x75 := uint8((x73 >> 58)) + x76 := (x58 + uint64(x75)) + x77 := (x57 + x76) + x78 := (x56 + x77) + x79 := (x55 + x78) + x80 := (x54 + x79) + x81 := (x53 + x80) + x82 := (x52 + x81) + x83 := (x82 & 0x3ffffffffffffff) + x84 := uint8((x82 >> 58)) + x85 := (x51 + uint64(x84)) + x86 := (x50 + x85) + x87 := (x49 + x86) + x88 := (x48 + x87) + x89 := (x47 + x88) + x90 := (x46 + x89) + x91 := (x45 + x90) + x92 := (x91 & 0x3ffffffffffffff) + x93 := uint8((x91 >> 58)) + x94 := (x44 + uint64(x93)) + x95 := (x43 + x94) + x96 := (x42 + x95) + x97 := (x41 + x96) + x98 := (x40 + x97) + x99 := (x39 + x98) + x100 := (x38 + x99) + x101 := (x36 + uint64(x37)) + x102 := (x35 + x101) + x103 := (x34 + x102) + x104 := (x33 + x103) + x105 := (x32 + x104) + x106 := (x31 + x105) + x107 := (x30 + x106) + x108 := (x107 & 0x3ffffffffffffff) + x109 := uint8((x107 >> 58)) + x110 := (x29 + uint64(x109)) + x111 := (x28 + x110) + x112 := (x27 + x111) + x113 := (x26 + x112) + x114 := (x25 + x113) + x115 := (x24 + x114) + x116 := (x23 + x115) + x117 := (x116 & 0x3ffffffffffffff) + x118 := uint8((x116 >> 58)) + x119 := (x22 + uint64(x118)) + x120 := (x21 + x119) + x121 := (x20 + x120) + x122 := (x19 + x121) + x123 := (x18 + x122) + x124 := (x17 + x123) + x125 := (x16 + x124) + x126 := (x125 & 0x3ffffffffffffff) + x127 := uint8((x125 >> 58)) + x128 := (x15 + uint64(x127)) + x129 := (x14 + x128) + x130 := (x13 + x129) + x131 := (x12 + x130) + x132 := (x11 + x131) + x133 := (x10 + x132) + x134 := (x9 + x133) + x135 := (x7 + uint64(x8)) + x136 := (x6 + x135) + x137 := (x5 + x136) + x138 := (x4 + x137) + x139 := (x3 + x138) + x140 := (x2 + x139) + x141 := (x1 + x140) + out1[0] = x74 + out1[1] = x83 + out1[2] = x92 + out1[3] = x100 + out1[4] = x108 + out1[5] = x117 + out1[6] = x126 + out1[7] = x134 + out1[8] = x141 +} + +// p521Selectznz is a multi-limb conditional select. +// +// Postconditions: +// eval out1 = (if arg1 = 0 then eval arg2 else eval arg3) +// +// Input Bounds: +// arg1: [0x0 ~> 0x1] +// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// Output Bounds: +// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +func p521Selectznz(out1 *[9]uint64, arg1 p521Uint1, arg2 *[9]uint64, arg3 *[9]uint64) { + var x1 uint64 + p521CmovznzU64(&x1, arg1, arg2[0], arg3[0]) + var x2 uint64 + p521CmovznzU64(&x2, arg1, arg2[1], arg3[1]) + var x3 uint64 + p521CmovznzU64(&x3, arg1, arg2[2], arg3[2]) + var x4 uint64 + p521CmovznzU64(&x4, arg1, arg2[3], arg3[3]) + var x5 uint64 + p521CmovznzU64(&x5, arg1, arg2[4], arg3[4]) + var x6 uint64 + p521CmovznzU64(&x6, arg1, arg2[5], arg3[5]) + var x7 uint64 + p521CmovznzU64(&x7, arg1, arg2[6], arg3[6]) + var x8 uint64 + p521CmovznzU64(&x8, arg1, arg2[7], arg3[7]) + var x9 uint64 + p521CmovznzU64(&x9, arg1, arg2[8], arg3[8]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 + out1[4] = x5 + out1[5] = x6 + out1[6] = x7 + out1[7] = x8 + out1[8] = x9 +} diff --git a/libgo/go/crypto/elliptic/internal/fiat/p521_test.go b/libgo/go/crypto/elliptic/internal/fiat/p521_test.go new file mode 100644 index 0000000..661bde3 --- /dev/null +++ b/libgo/go/crypto/elliptic/internal/fiat/p521_test.go @@ -0,0 +1,37 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fiat_test + +import ( + "crypto/elliptic/internal/fiat" + "crypto/rand" + "testing" +) + +func p521Random(t *testing.T) *fiat.P521Element { + buf := make([]byte, 66) + if _, err := rand.Read(buf); err != nil { + t.Fatal(err) + } + buf[65] &= 1 + e, err := new(fiat.P521Element).SetBytes(buf) + if err != nil { + t.Fatal(err) + } + return e +} + +func TestP521Invert(t *testing.T) { + a := p521Random(t) + inv := new(fiat.P521Element).Invert(a) + one := new(fiat.P521Element).Mul(a, inv) + if new(fiat.P521Element).One().Equal(one) != 1 { + t.Errorf("a * 1/a != 1; got %x for %x", one.Bytes(), a.Bytes()) + } + inv.Invert(new(fiat.P521Element)) + if new(fiat.P521Element).Equal(inv) != 1 { + t.Errorf("1/0 != 0; got %x", inv.Bytes()) + } +} diff --git a/libgo/go/crypto/elliptic/p224_test.go b/libgo/go/crypto/elliptic/p224_test.go index c3141b6..b213b27 100644 --- a/libgo/go/crypto/elliptic/p224_test.go +++ b/libgo/go/crypto/elliptic/p224_test.go @@ -5,6 +5,8 @@ package elliptic import ( + "encoding/hex" + "fmt" "math/big" "math/bits" "math/rand" @@ -312,3 +314,316 @@ func TestP224Invert(t *testing.T) { t.Errorf("p224Invert(a) * a = %x, expected 1", out) } } + +type baseMultTest struct { + k string + x, y string +} + +var p224BaseMultTests = []baseMultTest{ + { + "1", + "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", + "bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", + }, + { + "2", + "706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6", + "1c2b76a7bc25e7702a704fa986892849fca629487acf3709d2e4e8bb", + }, + { + "3", + "df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04", + "a3f7f03cadd0be444c0aa56830130ddf77d317344e1af3591981a925", + }, + { + "4", + "ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301", + "482580a0ec5bc47e88bc8c378632cd196cb3fa058a7114eb03054c9", + }, + { + "5", + "31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa", + "27e8bff1745635ec5ba0c9f1c2ede15414c6507d29ffe37e790a079b", + }, + { + "6", + "1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408", + "89faf0ccb750d99b553c574fad7ecfb0438586eb3952af5b4b153c7e", + }, + { + "7", + "db2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28", + "f3a30085497f2f611ee2517b163ef8c53b715d18bb4e4808d02b963", + }, + { + "8", + "858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550", + "46dcd3ea5c43898c5c5fc4fdac7db39c2f02ebee4e3541d1e78047a", + }, + { + "9", + "2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d", + "371732e4f41bf4f7883035e6a79fcedc0e196eb07b48171697517463", + }, + { + "10", + "aea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd", + "39bb30eab337e0a521b6cba1abe4b2b3a3e524c14a3fe3eb116b655f", + }, + { + "11", + "ef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c", + "20b510004092e96636cfb7e32efded8265c266dfb754fa6d6491a6da", + }, + { + "12", + "6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a", + "207dddf0385bfdeab6e9acda8da06b3bbef224a93ab1e9e036109d13", + }, + { + "13", + "34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca", + "252819f71c7fb7fbcb159be337d37d3336d7feb963724fdfb0ecb767", + }, + { + "14", + "a53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa", + "d5814cd724199c4a5b974a43685fbf5b8bac69459c9469bc8f23ccaf", + }, + { + "15", + "baa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9", + "979a5f4759f80f4fb4ec2e34f5566d595680a11735e7b61046127989", + }, + { + "16", + "b6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d", + "3399d464345906b11b00e363ef429221f2ec720d2f665d7dead5b482", + }, + { + "17", + "b8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc", + "ff149efa6606a6bd20ef7d1b06bd92f6904639dce5174db6cc554a26", + }, + { + "18", + "c9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc", + "ea98d60e5ffc9b8fcf999fab1df7e7ef7084f20ddb61bb045a6ce002", + }, + { + "19", + "a1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c", + "dcf1f6c3db09c70acc25391d492fe25b4a180babd6cea356c04719cd", + }, + { + "20", + "fcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455", + "d5d7110274cba7cdee90e1a8b0d394c376a5573db6be0bf2747f530", + }, + { + "112233445566778899", + "61f077c6f62ed802dad7c2f38f5c67f2cc453601e61bd076bb46179e", + "2272f9e9f5933e70388ee652513443b5e289dd135dcc0d0299b225e4", + }, + { + "112233445566778899112233445566778899", + "29895f0af496bfc62b6ef8d8a65c88c613949b03668aab4f0429e35", + "3ea6e53f9a841f2019ec24bde1a75677aa9b5902e61081c01064de93", + }, + { + "6950511619965839450988900688150712778015737983940691968051900319680", + "ab689930bcae4a4aa5f5cb085e823e8ae30fd365eb1da4aba9cf0379", + "3345a121bbd233548af0d210654eb40bab788a03666419be6fbd34e7", + }, + { + "13479972933410060327035789020509431695094902435494295338570602119423", + "bdb6a8817c1f89da1c2f3dd8e97feb4494f2ed302a4ce2bc7f5f4025", + "4c7020d57c00411889462d77a5438bb4e97d177700bf7243a07f1680", + }, + { + "13479971751745682581351455311314208093898607229429740618390390702079", + "d58b61aa41c32dd5eba462647dba75c5d67c83606c0af2bd928446a9", + "d24ba6a837be0460dd107ae77725696d211446c5609b4595976b16bd", + }, + { + "13479972931865328106486971546324465392952975980343228160962702868479", + "dc9fa77978a005510980e929a1485f63716df695d7a0c18bb518df03", + "ede2b016f2ddffc2a8c015b134928275ce09e5661b7ab14ce0d1d403", + }, + { + "11795773708834916026404142434151065506931607341523388140225443265536", + "499d8b2829cfb879c901f7d85d357045edab55028824d0f05ba279ba", + "bf929537b06e4015919639d94f57838fa33fc3d952598dcdbb44d638", + }, + { + "784254593043826236572847595991346435467177662189391577090", + "8246c999137186632c5f9eddf3b1b0e1764c5e8bd0e0d8a554b9cb77", + "e80ed8660bc1cb17ac7d845be40a7a022d3306f116ae9f81fea65947", + }, + { + "13479767645505654746623887797783387853576174193480695826442858012671", + "6670c20afcceaea672c97f75e2e9dd5c8460e54bb38538ebb4bd30eb", + "f280d8008d07a4caf54271f993527d46ff3ff46fd1190a3f1faa4f74", + }, + { + "205688069665150753842126177372015544874550518966168735589597183", + "eca934247425cfd949b795cb5ce1eff401550386e28d1a4c5a8eb", + "d4c01040dba19628931bc8855370317c722cbd9ca6156985f1c2e9ce", + }, + { + "13479966930919337728895168462090683249159702977113823384618282123295", + "ef353bf5c73cd551b96d596fbc9a67f16d61dd9fe56af19de1fba9cd", + "21771b9cdce3e8430c09b3838be70b48c21e15bc09ee1f2d7945b91f", + }, + { + "50210731791415612487756441341851895584393717453129007497216", + "4036052a3091eb481046ad3289c95d3ac905ca0023de2c03ecd451cf", + "d768165a38a2b96f812586a9d59d4136035d9c853a5bf2e1c86a4993", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368041", + "fcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455", + "f2a28eefd8b345832116f1e574f2c6b2c895aa8c24941f40d8b80ad1", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368042", + "a1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c", + "230e093c24f638f533dac6e2b6d01da3b5e7f45429315ca93fb8e634", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368043", + "c9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc", + "156729f1a003647030666054e208180f8f7b0df2249e44fba5931fff", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368044", + "b8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc", + "eb610599f95942df1082e4f9426d086fb9c6231ae8b24933aab5db", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368045", + "b6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d", + "cc662b9bcba6f94ee4ff1c9c10bd6ddd0d138df2d099a282152a4b7f", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368046", + "baa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9", + "6865a0b8a607f0b04b13d1cb0aa992a5a97f5ee8ca1849efb9ed8678", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368047", + "a53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa", + "2a7eb328dbe663b5a468b5bc97a040a3745396ba636b964370dc3352", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368048", + "34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca", + "dad7e608e380480434ea641cc82c82cbc92801469c8db0204f13489a", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368049", + "6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a", + "df82220fc7a4021549165325725f94c3410ddb56c54e161fc9ef62ee", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368050", + "ef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c", + "df4aefffbf6d1699c930481cd102127c9a3d992048ab05929b6e5927", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368051", + "aea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd", + "c644cf154cc81f5ade49345e541b4d4b5c1adb3eb5c01c14ee949aa2", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368052", + "2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d", + "c8e8cd1b0be40b0877cfca1958603122f1e6914f84b7e8e968ae8b9e", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368053", + "858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550", + "fb9232c15a3bc7673a3a03b0253824c53d0fd1411b1cabe2e187fb87", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368054", + "db2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28", + "f0c5cff7ab680d09ee11dae84e9c1072ac48ea2e744b1b7f72fd469e", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368055", + "1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408", + "76050f3348af2664aac3a8b05281304ebc7a7914c6ad50a4b4eac383", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368056", + "31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa", + "d817400e8ba9ca13a45f360e3d121eaaeb39af82d6001c8186f5f866", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368057", + "ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301", + "fb7da7f5f13a43b81774373c879cd32d6934c05fa758eeb14fcfab38", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368058", + "df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04", + "5c080fc3522f41bbb3f55a97cfecf21f882ce8cbb1e50ca6e67e56dc", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368059", + "706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6", + "e3d4895843da188fd58fb0567976d7b50359d6b78530c8f62d1b1746", + }, + { + "26959946667150639794667015087019625940457807714424391721682722368060", + "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", + "42c89c774a08dc04b3dd201932bc8a5ea5f8b89bbb2a7e667aff81cd", + }, +} + +func TestP224BaseMult(t *testing.T) { + p224 := P224() + for i, e := range p224BaseMultTests { + k, ok := new(big.Int).SetString(e.k, 10) + if !ok { + t.Errorf("%d: bad value for k: %s", i, e.k) + } + x, y := p224.ScalarBaseMult(k.Bytes()) + if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y { + t.Errorf("%d: bad output for k=%s: got (%x, %x), want (%s, %s)", i, e.k, x, y, e.x, e.y) + } + if testing.Short() && i > 5 { + break + } + } +} + +func TestP224GenericBaseMult(t *testing.T) { + // We use the P224 CurveParams directly in order to test the generic implementation. + p224 := P224().Params() + for i, e := range p224BaseMultTests { + k, ok := new(big.Int).SetString(e.k, 10) + if !ok { + t.Errorf("%d: bad value for k: %s", i, e.k) + } + x, y := p224.ScalarBaseMult(k.Bytes()) + if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y { + t.Errorf("%d: bad output for k=%s: got (%x, %x), want (%s, %s)", i, e.k, x, y, e.x, e.y) + } + if testing.Short() && i > 5 { + break + } + } +} + +func TestP224Overflow(t *testing.T) { + // This tests for a specific bug in the P224 implementation. + p224 := P224() + pointData, _ := hex.DecodeString("049B535B45FB0A2072398A6831834624C7E32CCFD5A4B933BCEAF77F1DD945E08BBE5178F5EDF5E733388F196D2A631D2E075BB16CBFEEA15B") + x, y := Unmarshal(p224, pointData) + if !p224.IsOnCurve(x, y) { + t.Error("P224 failed to validate a correct point") + } +} diff --git a/libgo/go/crypto/elliptic/p256.go b/libgo/go/crypto/elliptic/p256.go index 3ad8e72..b05febd 100644 --- a/libgo/go/crypto/elliptic/p256.go +++ b/libgo/go/crypto/elliptic/p256.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//-go:build !amd64 && !arm64 // -build !amd64,!arm64 package elliptic @@ -326,7 +327,7 @@ func p256ReduceDegree(out *[p256Limbs]uint32, tmp [17]uint64) { var tmp2 [18]uint32 var carry, x, xMask uint32 - // tmp contains 64-bit words with the same 29,28,29-bit positions as an + // tmp contains 64-bit words with the same 29,28,29-bit positions as a // field element. So the top of an element of tmp might overlap with // another element two positions down. The following loop eliminates // this overlap. diff --git a/libgo/go/crypto/elliptic/p256_asm.go b/libgo/go/crypto/elliptic/p256_asm.go index aee065b..f530178 100644 --- a/libgo/go/crypto/elliptic/p256_asm.go +++ b/libgo/go/crypto/elliptic/p256_asm.go @@ -10,14 +10,13 @@ // https://link.springer.com/article/10.1007%2Fs13389-014-0090-x // https://eprint.iacr.org/2013/816.pdf -// +build ignore_for_gccgo -// +build amd64 arm64 +//go:build ignore +// +build ignore package elliptic import ( "math/big" - "sync" ) type ( @@ -30,11 +29,7 @@ type ( } ) -var ( - p256 p256Curve - p256Precomputed *[43][32 * 8]uint64 - precomputeOnce sync.Once -) +var p256 p256Curve func initP256() { // See FIPS 186-3, section D.2.3 @@ -412,53 +407,7 @@ func boothW6(in uint) (int, int) { return int(d), int(s & 1) } -func initTable() { - p256Precomputed = new([43][32 * 8]uint64) - - basePoint := []uint64{ - 0x79e730d418a9143c, 0x75ba95fc5fedb601, 0x79fb732b77622510, 0x18905f76a53755c6, - 0xddf25357ce95560a, 0x8b4ab8e4ba19e45c, 0xd2e88688dd21f325, 0x8571ff1825885d85, - 0x0000000000000001, 0xffffffff00000000, 0xffffffffffffffff, 0x00000000fffffffe, - } - t1 := make([]uint64, 12) - t2 := make([]uint64, 12) - copy(t2, basePoint) - - zInv := make([]uint64, 4) - zInvSq := make([]uint64, 4) - for j := 0; j < 32; j++ { - copy(t1, t2) - for i := 0; i < 43; i++ { - // The window size is 6 so we need to double 6 times. - if i != 0 { - for k := 0; k < 6; k++ { - p256PointDoubleAsm(t1, t1) - } - } - // Convert the point to affine form. (Its values are - // still in Montgomery form however.) - p256Inverse(zInv, t1[8:12]) - p256Sqr(zInvSq, zInv, 1) - p256Mul(zInv, zInv, zInvSq) - - p256Mul(t1[:4], t1[:4], zInvSq) - p256Mul(t1[4:8], t1[4:8], zInv) - - copy(t1[8:12], basePoint[8:12]) - // Update the table entry - copy(p256Precomputed[i][j*8:], t1[:8]) - } - if j == 0 { - p256PointDoubleAsm(t2, basePoint) - } else { - p256PointAddAsm(t2, t2, basePoint) - } - } -} - func (p *p256Point) p256BaseMult(scalar []uint64) { - precomputeOnce.Do(initTable) - wvalue := (scalar[0] << 1) & 0x7f sel, sign := boothW6(uint(wvalue)) p256SelectBase(p.xyz[0:8], p256Precomputed[0][0:], sel) diff --git a/libgo/go/crypto/elliptic/p256_asm_table.go b/libgo/go/crypto/elliptic/p256_asm_table.go new file mode 100644 index 0000000..1d957bb --- /dev/null +++ b/libgo/go/crypto/elliptic/p256_asm_table.go @@ -0,0 +1,1473 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore +// +build ignore + +package elliptic + +var p256Precomputed = &[43][32 * 8]uint64{ + { + 8784043285714375740, 8483257759279461889, 8789745728267363600, 1770019616739251654, 15992936863339206154, 10037038012062884956, 15197544864945402661, 9615747158586711429, + 9583737883674400333, 12279877754802111101, 8296198976379850969, 17778859909846088251, 3401986641240187301, 1525831644595056632, 1849003687033449918, 8702493044913179195, + 18423170064697770279, 12693387071620743675, 7398701556189346968, 2779682216903406718, 12703629940499916779, 6358598532389273114, 8683512038509439374, 15415938252666293255, + 8408419572923862476, 5066733120953500019, 926242532005776114, 6301489109130024811, 3285079390283344806, 1685054835664548935, 7740622190510199342, 9561507292862134371, + 13698695174800826869, 10442832251048252285, 10672604962207744524, 14485711676978308040, 16947216143812808464, 8342189264337602603, 3837253281927274344, 8331789856935110934, + 4627808394696681034, 6174000022702321214, 15351247319787348909, 1371147458593240691, 10651965436787680331, 2998319090323362997, 17592419471314886417, 11874181791118522207, + 524165018444839759, 3157588572894920951, 17599692088379947784, 1421537803477597699, 2902517390503550285, 7440776657136679901, 17263207614729765269, 16928425260420958311, + 2878166099891431311, 5056053391262430293, 10345032411278802027, 13214556496570163981, 17698482058276194679, 2441850938900527637, 1314061001345252336, 6263402014353842038, + 8487436533858443496, 12386798851261442113, 3224748875345095424, 16166568617729909099, 2213369110503306004, 6246347469485852131, 3129440554298978074, 605269941184323483, + 3177531230451277512, 11022989490494865721, 8321856985295555401, 14727273563873821327, 876865438755954294, 14139765236890058248, 6880705719513638354, 8678887646434118325, + 16896703203004244996, 11377226897030111200, 2302364246994590389, 4499255394192625779, 1906858144627445384, 2670515414718439880, 868537809054295101, 7535366755622172814, + 339769604981749608, 12384581172556225075, 2596838235904096350, 5684069910326796630, 913125548148611907, 1661497269948077623, 2892028918424825190, 9220412792897768138, + 14754959387565938441, 1023838193204581133, 13599978343236540433, 8323909593307920217, 3852032956982813055, 7526785533690696419, 8993798556223495105, 18140648187477079959, + 11692087196810962506, 1328079167955601379, 1664008958165329504, 18063501818261063470, 2861243404839114859, 13702578580056324034, 16781565866279299035, 1524194541633674171, + 8267721299596412251, 273633183929630283, 17164190306640434032, 16332882679719778825, 4663567915067622493, 15521151801790569253, 7273215397645141911, 2324445691280731636, + 9262509587234749312, 6377906816499461739, 15415592259881792841, 6113140067088447267, 17505803833889144731, 3922849788840338823, 6180172597177093790, 7272741317181956640, + 10883262735810583709, 17399134577381480315, 12750035195491397119, 13953097270363313998, 2485196748577282439, 393430759246706702, 3408702096065201083, 16993508724217005008, + 6863012803048745338, 5403358912802668606, 12029756355518540153, 7447472859343023066, 7395681837001497117, 5416243410959797052, 2749045697176435642, 7813683613416962381, + 18350218749545913064, 7509253999860752750, 13295789896366834092, 18326374111226872828, 3258048562491844971, 6342797029666289605, 9612474478300039361, 17807494771134060923, + 9986610307523639857, 6419466267862117340, 324428332031706042, 16344106992423140174, 9434790811884847197, 11733262517030341550, 10475871084940451430, 6836751077061091536, + 6209985515928007176, 8422208926220809341, 7866188125456775984, 17071696982741312252, 17482363193291892153, 1949968206030126177, 8823961512355572132, 13873010936602132387, + 1136614876084383862, 14528605954969250458, 7641208364604111421, 18286716654189762724, 10711679476846124804, 7209187038097309348, 11378652158954714549, 8736575389915992180, + 17651988839102959720, 4019365809979531118, 15024676458991206505, 12622721674297982786, 243375780477240745, 16572583194372185930, 5189991834753707889, 9498206494038386287, + 7870185149723322393, 7858065912377481781, 7050328012468471455, 17977001023138181397, 11912539230960339911, 1290924823368819542, 8532615064753763585, 6439520053123840906, + 11863354073576605599, 8052916203396229040, 16399182063316628399, 10837704607074036270, 5444229620349428264, 10866168931038804304, 1298875461760659950, 8904898233335519592, + 7053953350607273992, 16629865408105641272, 1929728580699289339, 11046110151029488400, 9569890690274721816, 6501378768832742664, 1512621765961532661, 17084264658609527495, + 300662505135603380, 15234062183651308307, 5319536121171934679, 11496182741145732970, 10520610739189276272, 4310163027157056344, 3285324287508696251, 3261468597637865009, + 5427469457023618335, 8296698312021944466, 10882999905197052907, 16825284839961451415, 2106903142647479713, 12008841566652934760, 5361688498494289694, 12228623597691228792, + 6799789383171367218, 17419525584795621504, 10685476378747845090, 16314000862057872712, 11014509959317588121, 10396318154903722147, 9986284919279346079, 4005974039875805723, + 12980531573372269379, 11790791377897350561, 14264262096731994829, 14999393269362129980, 15405842559289002684, 13147503876582120266, 15449556979080143937, 5047767509783027570, + 16354606995222167433, 15941889353688553446, 10301254747221876749, 10704428461746587572, 15702361407127630489, 3283718562982354984, 18081088275079496700, 17549094608770385733, + 15620168851912893400, 13762314693487747007, 13577625382054330775, 4116976667540664996, 712200332640207605, 9098568002202933512, 8905476951567380032, 7075673514150314660, + }, + { + 15811459837282651008, 4038049993244767161, 9054218236388056577, 10807376403937048775, 11113869110590438959, 10336442539492421506, 9228056645601479672, 2983388754829658480, + 7189376137127712298, 9147574701720272724, 3983921661449444789, 12479790317447783959, 13221020976679959405, 13001868979553711359, 17918176319017234744, 18030393246529651080, + 13903368497828271814, 8050546449078305498, 6932373216915935575, 16010012759059004304, 15451708272653450375, 211711129247219149, 10435723642185827585, 17790507800712341232, + 5218985848865375996, 5835476376320976237, 9096499658845542933, 8952489298840360492, 16605895184424459659, 505731104315931813, 17784248872812610986, 4151555707609374291, + 2650786429127545939, 15186825834659456704, 6983758297535957561, 1268007525252235269, 11433489869282443481, 12352824209154665189, 14555720778982121964, 3578659908492218328, + 4038120750249579469, 8304001815287976437, 251700810512667658, 17170873737273596918, 12809642145843734737, 5765073376623244019, 7923401246629348462, 5401634486288115286, + 12830329023522940651, 1302336131164509751, 7011936976469244509, 8446680306499168806, 1386043952588989461, 9057741950701319559, 6719607413978812889, 17371065020414280890, + 4963953120977916566, 6585250545846301109, 4490972754776862709, 10674499592300479120, 17494988318349821345, 1814042777264686189, 8938395423478059768, 9062966010283426056, + 4683683785459765575, 8782133909400988812, 7201726172249963453, 16855412996123591560, 12016536526053703526, 6004686128951599125, 4323130180079993082, 7578596978943754924, + 13272384473390546409, 15052793429857194942, 3597944793474963009, 5659515835454510338, 18013102402609680655, 15096936721974473248, 9096406212198787674, 948405832772983882, + 7533214627823316056, 8009521942734148665, 15370181949218639901, 17395801240657257383, 13217990616373936619, 16323510521919428293, 10737557422966235859, 11113837024463125316, + 3879469818714011415, 11493820457829716643, 10091807027724827301, 5032134849078736052, 18015749204009276046, 9667758283246223357, 4629693773460610802, 3807196436109718946, + 3214144211600931504, 9454007581819416365, 15275469051811991033, 18196204074031746058, 14853793468372596948, 7707818604949749658, 3266782539036976530, 12810995382868348472, + 17461133192060813135, 16870745208936545685, 5903437034120721004, 9683544852742219696, 7903581348090948266, 13461951083275541722, 2454715926022970060, 11781268272016425522, + 3026443193966185195, 8027125782547146632, 17998666917527163386, 17214321347454260227, 10230244243647560419, 8728893474426972780, 16205038544687771303, 13771356055080873468, + 5724217930909760221, 15420221591912350415, 9910465013739250802, 12511683773790779491, 2841532862707547306, 16614426471009646589, 407574220261191228, 17422057170120224031, + 17151505459068312604, 2041124098660595410, 3221606782120899146, 1382742171848704850, 17222534050501711510, 3195635935311449393, 17295393886051199723, 6296241746423654238, + 16510537668852450348, 15650518534057329304, 475704671950317376, 782416820485820540, 10970369699990900408, 16601298147057372792, 1599283701215392453, 8464446359559369186, + 602848212987973622, 9275953159572178443, 15133444738457385545, 7264639569553811785, 14831517002293569763, 4277078717758211028, 12880437544322007232, 16339691585101354857, + 3725101809714764432, 2995111022132376824, 9338883729618021504, 8824923738291347476, 3745497072215538317, 3576446898425965872, 2350077748663612773, 15793255155885543355, + 8020669822852194733, 5865488997462325879, 13508617967776537887, 12934930135071898613, 11708185641249600577, 14265801329217514207, 10451671488560352734, 13251349632343744236, + 10155392082337432799, 16725751190167983672, 17791070776350679280, 6653785531179322348, 10087876256887835780, 8422365820961469204, 13614411778251983480, 11687935452237305960, + 6094298050768263419, 13949448434836272414, 14194554169090099223, 2625524360834828424, 2823844915913169919, 14077211807091283985, 15592587505996634401, 6562949920171518305, + 12904339001067417585, 1972265247859388742, 8908590936681392405, 10320719400504224158, 8298368064038407143, 2105745729886511647, 16509751074757847095, 15156289751671616565, + 13922601558154971179, 10541544592627074316, 9996345160543671471, 2956094548427827774, 3384122842786043431, 7003441038438960180, 11945730502649377204, 14797331669618433927, + 533287349958250211, 13929395807878461602, 10036169742264959424, 18402398814900480008, 8793706913568807269, 4438954128288889267, 13996827050589647592, 6637236830429213437, + 4308464751705576538, 12193581114161194913, 7322672375339219540, 329737085274484939, 15312435499764491079, 1530264129038944128, 1545025965426980152, 14559433923601957161, + 885617946245226760, 17871561572095909264, 16413308527330544768, 2938750343525834336, 6332736376778563648, 16772687696658236231, 9760470695949399178, 17420556823805232882, + 15040671962589188567, 5841393164221253498, 8923415548773111750, 17449640982747951473, 541686588805328549, 9579487672246868564, 12793813917570150236, 5744918442591934533, + 12406806484060734474, 4655292039647906135, 5745141229449178147, 12923621608907306732, 1329768221522217568, 16293616079741201891, 16309603918079351385, 8282635243638078478, + 10842935462043546322, 9397166878596340773, 5807145729199489911, 17083242467628861919, 11473470924584853882, 15220945465200609206, 10470712526179658906, 8129601297261864071, + 4407657041250297528, 13832960959347315977, 15056546959967740939, 4350443362134191429, 8013419913016572733, 8888684099801298477, 15401479253620745715, 18279947201669400847, + }, + { + 7454214833719424418, 2128900810399984335, 8254953962723841408, 5341529923812819418, 11486532916552139238, 4528331821405917357, 5048485034448492541, 4189495710753944825, + 9223539587116638677, 879142711399260546, 2878829560233905572, 13081522393987952773, 3067261963348061547, 16008150780594711643, 5466468631453287640, 16659147898971349582, + 8047766502132608624, 8715815570878148809, 9093649079884580138, 3437267783531715968, 17562225708466062266, 3512667182749067601, 9223059995161026858, 1366690634827047376, + 17929132376737482163, 5565926714491294456, 5252303555134107501, 8169975563698132305, 1829326230943509100, 13780918661853274468, 17736665596871232627, 4246797342334307384, + 5113556452592134569, 7304867793218750141, 6016631926489320290, 16471860203547627727, 3444471410714850041, 16571738096215232488, 2003912224952639024, 4203884000388032492, + 16858425223672505353, 3192567884201479579, 1688923188642613263, 4159042130811153987, 14900413503869744297, 7521485042788722327, 14038093805562042641, 14713051866364662650, + 3738774192924465076, 14037618828827556145, 12882915396530927286, 10882862194263941815, 13115222579444494605, 18244214260845794346, 17217867059738274194, 2458870331386500577, + 8768788172344064509, 2761897497254272960, 1400167175024837359, 2591319596670212133, 1499652044223484974, 6820326453941021707, 9701009499879906773, 6897435972338565418, + 8314355711464256163, 8435944020779763783, 1814803522962187872, 1875253356755380905, 8214588085484192137, 18062045700553127821, 6649947905482043494, 3119726140944397531, + 11881571666857493523, 6300786026612414187, 4928573492087752294, 18343550313462089203, 6770642120472453960, 11296815027803718740, 17312916793783562794, 13028515123652649961, + 583508939637547757, 3195115082527873085, 8497784022800549923, 15135719419829981016, 1180291993378114150, 5447281494912347899, 4710517655176242215, 606503081693490000, + 17732293765863716052, 853971165248416821, 2022886284923413326, 7522564752651732633, 1417954193520965954, 5046659528429172066, 11426939225844711305, 17687206690616539318, + 6518552374736169438, 7940416740434530770, 15228615103587329007, 10662504584317997513, 18370800756791469891, 5564085264882124489, 51043856061444814, 11996026931884728651, + 7009195269496826002, 18330778751427846129, 7903886241001925539, 8198930484643879628, 5453546027419466587, 10378692433982210944, 2242412603379120569, 14762161396393277464, + 6146718865488327808, 8559779132928137805, 14001994895150170346, 9915701789711858841, 17119408219089522083, 4345363585985782988, 7559492126634131602, 17074565022279033371, + 1081257522368061155, 16144982029632101790, 2280210790959566458, 5000326950136078873, 10441086845859171982, 5717080014740953823, 16816253740467637151, 5185838557034755093, + 5835900675852976641, 14850646160621635240, 7784412869482958370, 2550282385659033114, 5102457400165153071, 16480738116286616710, 10726825595752219296, 3297564208881065856, + 1801069609044825811, 12940364451588241698, 11725236374887225564, 4731241880784054295, 8874695411069669852, 10719836334830130110, 12983549127094653526, 3498884940869443564, + 5044718241380586525, 9152928988998314956, 13274353997717834972, 5731942246653336838, 9453579625340936273, 6013700107129234092, 8535405089994224035, 12024982282827680252, + 8296339816955798913, 17352704937535250450, 11768204246645005024, 263391795317009517, 6622964609352808474, 14563414288208376628, 17887389278697258458, 1552357122641071119, + 13193447428787140357, 6701071088186218635, 17090465712567125397, 13844922841372559745, 4526664599449630663, 11321311100342816810, 2490532976442445147, 12506579957986846905, + 15880983134955361922, 12396434033732989105, 16113831675045409693, 2288598422068078002, 2992425583703267972, 5056435264545116829, 12961420259857080621, 3600697676136115398, + 12817090821406743193, 18109694174173693756, 17050997692981853333, 15796663317536421728, 15462568940214327094, 15151767385082666402, 17711108405932879054, 4030072071760424157, + 15725012875727498089, 7622633481063722008, 2241559275264867670, 4018985714167034871, 6507661741395512701, 13435865773135624096, 9564553262368888543, 2283482276790194513, + 2968718708369505078, 5001470555537559034, 985353756026354700, 3145435598301843880, 16410370922030326027, 13981261173663429189, 12565590835494971812, 222252377400865123, + 3096505383227168071, 9129898186148780825, 13266305466206099845, 16135309871416543685, 17993464782237414425, 8124413037611692960, 8497190057115012501, 16568064870411415344, + 7703394153241465824, 2740794419858297964, 4228931976096177316, 11207299659959318490, 3319492324515199082, 15611937984154016609, 3431896575019701337, 10686234123352138088, + 9979039962499030832, 11759414020433216431, 15164411293105859178, 2834464820255498467, 10716371968480406389, 2722055037405581557, 9240657586762413776, 267811388229104916, + 8385388272348876655, 16035999427286017211, 11255427708348651444, 18402964994101916340, 17964277099260928049, 16377129731672778885, 12034488763192562427, 15854195461740399790, + 14134352329607480415, 2406779189916280288, 1148342927890148438, 15859735140823564382, 12055096645840568482, 16044304241162505738, 7466809979198503617, 4519925955244504432, + 576546655711744206, 7729660311499709518, 16864252562359023573, 10537888397995064025, 11828992107618549830, 875843272290362538, 5328675038336932433, 3162100370899364658, + 3897734650128449985, 3892478283047854402, 153850176068596076, 4448963435449755938, 9911011406822436713, 6379744721342779297, 360324666931028426, 8002086405015565067, + }, + { + 18068291112584812890, 10288580446655316879, 16866690514199445805, 15458664010538199871, 17175925202246173890, 12208778610361755998, 927739404697616036, 10330183209424493139, + 17095781462759061506, 13984950766342782369, 7038608479806172868, 7073471193601880894, 9212126909381119712, 15865851343492198107, 3874039137971369196, 15366505242302572319, + 3235058267792568155, 8030551941244615429, 12851363585510555514, 9786973022560471711, 4901414898060251968, 13240438628487941170, 4707852389766057435, 6503805666511566831, + 12081034000518110752, 2773740877021737013, 6429475399936543899, 6804412599792308979, 16082860502313571182, 10013838454082912732, 7176778953927883654, 8065751639278576331, + 2577328127707636877, 17299987330349518428, 15104751346159263209, 15422444943335124822, 7934601464470854115, 2803659700354182364, 186161376356596699, 10049927908892587253, + 14226302346438044875, 11259466681405724608, 3945860952925292329, 3287876564263331089, 9461394118536996000, 12404803552046013762, 16569223065554335449, 15881973563254196893, + 6665552777203645232, 5302850683863152336, 7778922028047389493, 14212904863357452615, 15966527672828304861, 3802704091320278344, 10517530714917238300, 3742971938824724276, + 17741525051518363144, 1374267330336191942, 4677891169679898540, 9639823611685431337, 5482431056894095950, 6629146695374718376, 3884574854221819712, 13266790928096813258, + 16028684877412556061, 13405436055762225966, 12268280467958284214, 17956874998292211440, 8610745336676661311, 2945210828327041653, 7889492068658434371, 8032335517518163423, + 17096678157067198548, 11751872841896846778, 14951591239724148110, 14946797103632354342, 15001812923533485850, 1354666869219009884, 15934246013528228877, 17674533676709494379, + 5120889077991995845, 1349360562851394781, 7965752316528770369, 16276575673105864366, 16613052983770261287, 11454051240568463780, 16146905806612132291, 15806571503343623359, + 17505459029376928465, 14087658194607915364, 12240552390931686885, 1809009366037859941, 9468395484396723291, 9446052656478984520, 3720796795453397330, 18035355127900871187, + 10937782812576841853, 2203021845094443505, 9622750764486021477, 5518948515641487288, 8021555402800950130, 8884074473434139094, 3925095588129480413, 6199533424090268508, + 3824657730049729815, 4646911366274335188, 5283751816651713473, 16396970607630079440, 9102362834410101425, 3641728106404110497, 5923630184251416230, 13179374259571264822, + 656781601862662976, 13284523818709348938, 14255949685810234815, 17662122984572331094, 14005272187244763785, 2769973460677437621, 9745740172208222044, 4399769039990314590, + 18221138344920380175, 16761112742545021198, 14421639991115588619, 9419167563943683547, 6237248361283446238, 889754338720059891, 2289880386545166424, 4280148734121099084, + 8456687949810928719, 6224977199672540221, 9826855484829367341, 10345583292656523462, 715642447678891171, 10791247680314230673, 4390153264475025171, 6710036254773432312, + 11434352627810350015, 2720291857616706675, 15035363195148805272, 2358906741960696657, 9439888337759970778, 9654563570832962181, 6013570511081660799, 12742404245236356978, + 16538557679183724426, 6137267799072203525, 13879005145532324670, 14569289845201353615, 13784903266526414562, 1051135786146476033, 9343275973150690259, 18338317230916899584, + 5259165122317589354, 6306061166879114159, 2622163270351284906, 15212813592118086979, 11497359168652342849, 7085380391293263482, 11799059272489792659, 4912160901181298022, + 10956239956289671191, 12649697329483184719, 17174497942073298839, 16454040570484021598, 1964314354536023134, 15533681501854792750, 11384243972598433754, 14387731385073008825, + 1627256545355657442, 9010013556811110994, 14616120598404631231, 8391972858400276155, 244817907132802237, 1484397967210729699, 2663560284299448875, 4820353472962713985, + 6567121006858416952, 17119959301239619281, 3965303761563489817, 10211688306206007722, 724618943950031080, 16749575186941231354, 9181397347361086360, 470616631211702666, + 10512473611770099290, 11735037909076331019, 2922606398008539984, 2599799834378751770, 10226702495047936424, 6109026252412854338, 15572556822827169237, 11993701786788749663, + 12951512375864063487, 9270845327881823041, 13198171264747338719, 9240466821667660686, 14918848310897324032, 10111918274408213257, 9869937817792431868, 11316967879062014936, + 5691364106926740802, 2782311978438620206, 13067832493996441150, 12682941211395745221, 10515041347274706648, 9910726429809603026, 10540072260993990483, 15078586909891471233, + 10892036011159420575, 9833543566604313963, 15176473361412960115, 14504845496732895720, 15845034940445278100, 5364672156984348678, 308167090528488415, 12390239901799634313, + 5106897453764491321, 10540479232768400094, 3938246597140945859, 13156157265138481529, 4932443191001849637, 11374218582626530502, 2907557293167002437, 6807344711257391317, + 5413712686694380670, 13147753106081951274, 2960292187746417883, 13977097845105551070, 17642067093469099040, 7699556298723812469, 11597002672863564976, 12392265705126521509, + 4607947077536257852, 17763906282816835996, 11288463953418287893, 18299911648497821660, 3194698850612319839, 13371221457376435780, 10047718724723936081, 4488868185988157408, + 13742985513958274859, 14201726926009534105, 2183997556320958457, 2564950343266657518, 8846625471673389624, 10147673280504740463, 186524308060896613, 16409126738088317791, + 3993197157612782947, 14810882170056329119, 3476738916713041107, 1512933700383846542, 17820889751141311776, 9132720567660500233, 17598924894608972696, 9704537908665702455, + }, + { + 15695265447782578013, 15506558718447241194, 12341861439298989232, 18400958156300100845, 13704811286967591150, 5802260047239067846, 3266013253411255445, 9892957742319181954, + 6053458788987550519, 3243549259991905443, 17990025476026266205, 3918149716414968130, 562225565996136148, 12175287017902713154, 16317970834262634990, 5431198806775607012, + 15123186170178367264, 3054913246068400920, 8130663466272395280, 2852812622149318730, 6747630551931917110, 18302049774259156971, 3663865061939346221, 12340091610704678811, + 17453312277789785069, 1148609799196055657, 5931758962926317381, 5297597381576544508, 9136842287749269744, 3007653173299649609, 12364677607049679091, 3656932227466449489, + 17732801126130995365, 16093023291975796560, 17028512234142609413, 6293028118993952199, 4019599708379609715, 3557632583507755601, 16737140015288442165, 7041678499288317736, + 5187842645752673199, 14914432544387315508, 4944360914161982641, 4177329533692612281, 18423887817846407126, 11935898134550505219, 9191754399457615042, 962223885189306707, + 5467152559317256227, 13407023128339380091, 656806207084558176, 10823228592509573890, 282802378108427873, 13003319652664166176, 11501612671901244594, 8595770155487539951, + 1805255869285898834, 11676967700876044626, 3486630203654875772, 8366336693945605431, 17874084888474647879, 8803709150655606891, 680993178667234696, 1603785777136148315, + 3637712241808318043, 1673622542455477465, 14468899013751477571, 6607241816357171779, 2332200248940843815, 14077155355848738174, 17298155509321457563, 13624623885136011130, + 12550073596584561722, 13898852145577133829, 31360866049197404, 12629522544897401454, 4563446134761510332, 7272813487383198495, 16767195814334178362, 13600498026689482359, + 5170414136067325373, 10875290278133558518, 7331268231382198947, 4082234313337835514, 11725295114019619895, 6488017511603508543, 11399466652931338200, 2898113599278666684, + 7553418756944942759, 2324485560009697358, 16004009784734101843, 8345371056076551939, 7377284629098981027, 11049718262343754276, 8021605820736410979, 8175349759714152494, + 805625092558946929, 11996029844853502332, 1725029464967101849, 8189609560660709539, 10396089572662865065, 1756007811373736605, 7645529329516777410, 2608132938055260111, + 17014595621244604813, 1574499958190108567, 8684546755761322906, 9997538531915911005, 5652402150243592363, 6315865356369667235, 8687115108443972047, 12369176255146729475, + 5117004045853299762, 2238407612548002914, 12392667457861900490, 10614312910576266709, 6446577503758597410, 3767883614425995197, 17954966454260719539, 5233322901463099, + 9194523390605857831, 2335161171394626054, 12290490336543843159, 12464172604156286188, 15842196578033029974, 9081285134201585379, 6123406461662038242, 5504260508195082396, + 5345718195770885739, 10397124463462860788, 13439280718993427040, 15556816356929214653, 17286785976489019906, 13891416634083443852, 16346644312573564447, 917629419222512011, + 7892626957952656865, 11229871638807701267, 5249460237065799805, 9529842808650392581, 11803106868201977918, 4600784567377577444, 7178870186583927975, 13829108773971861655, + 1289703927368007546, 16175369390684210381, 2195306032582966573, 11284704298115036296, 4385727852306374408, 6915138269030006111, 13440775052829788601, 7742359656861485339, + 1418252737937945274, 10664598666472920539, 5146625453081549320, 7716408631061669307, 15481216546649435253, 9087869057854823101, 8438781502742166926, 16066665509570633845, + 13091912700111633391, 15443255616678375884, 11338466119311799740, 9641919445273031117, 12359044485240987114, 7665168466660756789, 13845183791692700257, 10700410793152785934, + 8528578803314347534, 18126789418189181716, 6819229450418907940, 10542951903574211724, 10335954505229790439, 773396809431100386, 763679854573261611, 7782804492252573047, + 14102889564247144327, 15479515297699126743, 6400257822506917934, 12400211936189844586, 8190162441518233318, 16489757979266243333, 11074854544980782334, 5650848136444824725, + 49299995316533601, 1658812626798186796, 14321322055030354, 1062750633396640947, 11458188738562323084, 10319462683954522885, 15398455357851813321, 9473384090828584828, + 17723857482947114516, 17563952877363564604, 3160294749187111891, 15485369139883303866, 7487527166185553604, 9661144290316674030, 16387431126208996705, 7499766964252214921, + 18331281993562501191, 16034836629143884193, 11149238385567891503, 1413880911197321245, 513884082842080653, 462183409527465946, 404977499728878854, 1459875951423441439, + 17249202826373649180, 11151860661862313351, 13606113651347187963, 13653298062695357606, 12346841931589648448, 10659825520992339734, 17857177794617595021, 12846976930859175746, + 7421386827645898229, 4567141110780940726, 9022716764262477732, 7287282267953917487, 12950322172330872807, 2675202024861592519, 18339036521791481203, 7003909904344391740, + 13539440097944399044, 7108271818419613260, 13229113021954558930, 14920952138366964142, 11082363944167072746, 16156446445495173622, 15515349862819133984, 12359827931233605745, + 17013104138257181849, 6982996767213561282, 16259302607976830987, 1579942890487532721, 8635464047344487404, 10435012080572068738, 2976844365866972753, 9471858478345924179, + 2347775782107812070, 311367032040459687, 10852128873404113998, 1338612296059509077, 1599132038614432432, 11533828746166635650, 14264087792956755961, 13004615331499537807, + 9599159247384506427, 13011559959971256245, 6331802547989957841, 2642320882309956905, 9140255367820630480, 6883541786494880896, 9560822438260750771, 9273862677291701694, + }, + { + 6185067974942684922, 6452325785873503452, 15247257292915812252, 3689324664200339196, 3264129576054154137, 14977721630214750038, 10720913377937894256, 15914487080763816378, + 5498621600689515064, 11498885804037952971, 12697073118321478539, 13999008478737234463, 4324885099420360642, 14021182496192299466, 10763088992583373843, 12898585157666243299, + 11622402383521841588, 18271726976204770291, 4805501248621435402, 13483122453682180759, 9288143526654965614, 4688427612851085031, 3280806057528512375, 2249349779106893174, + 2317249352525369754, 15030797481081533168, 12237590576308284360, 15660076992611440873, 11341015819700735887, 8280257602754365719, 9212501234696283343, 9673375202141178099, + 1576552382781604867, 14644873134348781157, 9860879950368557094, 12941927431704225849, 11959666739052502184, 16171152369226594315, 18364294470656574060, 15172859394935215584, + 7521577570681641021, 410124023045579310, 13806534589183327176, 2731801491329207875, 9959087943014269549, 16205635445474657221, 12069145915768935630, 14906463509471682144, + 13803661539609326912, 3233094883493439444, 13409742688319755923, 4298169788674760921, 12847636671560067434, 6702365884489797170, 5650404576647289813, 7380374625644226212, + 9762534010701623728, 15349113802811029024, 8305297169667044246, 18013018210154476198, 18414050009163335761, 2190126859433916996, 5444481274452218807, 13415988647365667724, + 12538763466834894269, 1385338113050483955, 17489001033590767373, 12734464941837886525, 5762578105750980174, 1466528690684075875, 4231060025049573530, 11218444849081704286, + 13520439252664960951, 3770430920651384098, 18274623217805904547, 11545267616883260257, 4084783424859113779, 13863968977657663867, 10237835480648574698, 7395611844854084274, + 12891185742908997266, 2889148203703402614, 663579373261619221, 7616112456816883701, 9002890885722034437, 10753730807791931375, 3553894671829778441, 4368240432504457389, + 11641532224340210206, 71261001011952801, 2321745415903209397, 6595984444855093239, 10341299657770272718, 11529878689049370930, 14381510695605158203, 6869272773579747365, + 18407769999912340511, 13801873415230385184, 8080153703167941484, 14143463895182697871, 5248006623352376562, 9271982788122934275, 11225161179021692620, 5076519449784098178, + 2388868518767189674, 381125256886459269, 11316805024982236485, 11671355336111917711, 3564177948445768908, 5245093046097324328, 16144139891410041039, 1201010948447708436, + 16591032462856670656, 533850935988668408, 2263232738784171066, 5572124915367282948, 12583782854491678471, 15015562207264407653, 1167486851113549964, 2987176661273439670, + 1073778278665127828, 301289653767944933, 11482324780950168317, 10626716202328004967, 7258024014655363102, 12597648090458567878, 2617914106162603499, 12324652644266476584, + 3803745429517922765, 1699256829990081513, 2179986933466617785, 4330084096014112280, 10403896221616386733, 11682369673591069651, 3879392495596713886, 17249085256521020624, + 13938687445393525296, 13822790166673492712, 13216892716897321740, 2165870280409061482, 9147830602451471293, 16339144108911449834, 17837507766320968023, 15340710005345158245, + 4485838034764604283, 8426970493386126530, 7709201418726935942, 13468796449943783583, 16441091014185628843, 2374269830239737237, 13423059086148485716, 17132218391020520330, + 13957732574177025801, 1100344278733481546, 12156946932617203965, 2007756425747006287, 16454508610548016441, 18058668363064769203, 15619001054652658323, 1201476243910931863, + 1292412381963708933, 10908631677673353277, 15138649576688192753, 10741579086621436813, 16534963566169304684, 10228646729525192055, 4256608246548223655, 16176814322718522963, + 3012125536603284881, 5466178753014623970, 16598422155702380175, 9902071731736699653, 13861556771123036741, 9534711573278556274, 9805898455743897538, 14683694395093520838, + 9125214754744730198, 143353181770418225, 8976042597473555858, 13405481215779362056, 2863125481657826330, 12333764090388731260, 15250359513836914002, 5086706595778559056, + 16341334571424533804, 4657494880554316004, 18092783076286521475, 19832895869027143, 8667365497283429486, 11501953273367138162, 5832487631687776985, 664754160781757174, + 13604774408440609080, 12660956565879820101, 4535452877362385626, 8063311919592303330, 4591511734775484245, 5164119991271568303, 5282209033000495913, 15181017218549722334, + 5070228782679699429, 277881850788922387, 17424210585510719837, 13586569401109299583, 16661809787463692974, 11543434536078774133, 2062889565117549061, 14261113517104795690, + 17683343658262519228, 13727986689138309987, 9352982220536939533, 7578301410191413286, 7970586266869249410, 14357824150096386968, 4381700479561442130, 13217807763329274501, + 13524719886605363170, 11553593166914861649, 12034020205580665813, 985175984881624722, 11040631342644137311, 12107496606245418129, 7328748654066365904, 14741972847454326011, + 9790251609380109406, 2449588380962781369, 4694893010228180943, 5172145489692928848, 5411277023198532852, 12752098113265127406, 4559500999103209672, 14921033543082064351, + 2248082728820243864, 8720404853152831367, 12431505213690884811, 14883031570121462817, 2278273022936639560, 14988529405400451352, 16732922988142595529, 1071232319627396164, + 8793441611217807824, 13198147137434605751, 8167936709747999601, 7685928882032231744, 8779182451658438210, 8059106577297479923, 18394590909567718507, 15508315617300242773, + 12828567388121500364, 2264959796189127526, 6222205589523394088, 8827682270015065013, 2619170858745203321, 14835030117099398518, 5960028394532808010, 2233397097850889639, + }, + { + 16319476863352440541, 10283930715856640343, 17675054544532098447, 11261132162985242084, 13712716897981761400, 2681907143459288706, 6930256922080133347, 1445069157579547822, + 16928574868467385886, 166417019993787654, 5882811520342817815, 14106304179344008065, 3747123724781081800, 197109533566874475, 14303280595714789450, 15457633026018307066, + 10773597511592584859, 12552868588431074640, 13500771767160426835, 8002499270056378440, 13792839099998553174, 12949371255843262119, 1713974340992291550, 16150173130483658061, + 14745984256428057001, 9333707338036985191, 15365925315303462, 11789129028059619744, 7873100217437235208, 5289763977161829145, 17731215200358323788, 8876377479309635703, + 265950821974454804, 5047467530470542278, 17523044368516619801, 10054436503372765176, 10321185867287373431, 1212061937729015591, 15311258419138633926, 11236518538207084768, + 10904693956407098222, 9013418755007070130, 15510005599846320670, 995378633446250700, 12234095025518917836, 6689106237771514188, 2809193993744369126, 548124799387888260, + 267350765778774337, 2853877351938464055, 3677119082593358544, 7685335121077514739, 6491980094762370981, 1384870316654548002, 10568872345228996498, 241629538659623878, + 5839400175629113441, 5238299193248381245, 16787876416022887315, 6051613843621920008, 9219569873668974552, 5916753090530931032, 13390630214643423749, 3265335490455191268, + 1507475744849985303, 2597075068965622770, 14968669113917266926, 597606442423659891, 44293923912414886, 3832651144752540816, 17438860065613195810, 782112340603343331, + 9050896199196733903, 6427608033444590004, 13787696679536621857, 9682087046920409188, 4519093754155995429, 13564098392055667371, 10512507082236058799, 5289934424008191746, + 3477191607403300916, 18283244229745029067, 8462159792484018099, 3056576498976014760, 7259283167233712785, 12530251965039903998, 10232104933720625111, 14190745998092156987, + 15759362035410895911, 16075598437961371531, 4651513528876405575, 7694151626503869614, 14468862724637972284, 1838601521755586245, 4168957446435305706, 8694905613027663664, + 14825552838983151434, 8639609968952840931, 15547914584352392016, 2313507499500708287, 6902543375698033684, 9987468886016348918, 9068175779860656258, 6899641689193116297, + 7449110402827616954, 5689206471789540768, 12722069021950813669, 16017131401246233663, 2240977975275954837, 4794705713606614946, 5734937900461809607, 118285984764445639, + 13917685647531721740, 2432096911145792817, 17733637484624159521, 3848601825403209903, 8192433211051054683, 17388066421914150767, 14336306308847565282, 7501625553608785022, + 9844707592410952215, 8167497709587672711, 18115463401502884199, 8471563375691441535, 17525405040226359165, 2460181803833371342, 3375780580907171205, 3024376384135966552, + 15446204978718816914, 10131769697256428720, 10937168660849553757, 12174257400309926241, 4774490771219074715, 13764876998736771340, 14299051476546774038, 11409551629093945893, + 5471366060803425265, 5927845172343647238, 13321967429805195545, 1981489848211999240, 3657997933879283852, 1341488083977381854, 11001000434984172675, 12666440712128450303, + 2127920575549495889, 8861781778185702064, 10501256952986753134, 8967441017586595593, 12224364761159418844, 11856305587178745520, 8176487286367052930, 4988165299911239066, + 12279712962388998309, 7552494563001503282, 7388800608466198128, 15704167671257743517, 17781278773093632973, 6688613358271814698, 12261263098366698895, 2585757657252460656, + 17064077609211627595, 14437064866605257652, 14386408901468621215, 14935685266532365200, 16350265985491822570, 5195856143474093260, 4623415440658404410, 2936315929072503688, + 18399447684263070219, 11294713679768342649, 1600242588657342501, 2841752419388937826, 15111313732750279467, 8179471361906256467, 10611923788752807866, 10823997080784081293, + 15607034385960553579, 6934034624930683639, 13318618594774430459, 7552865293216027192, 13692640408995992185, 11143313220936824014, 16721999332340829387, 6993089466645938014, + 1749509641415861857, 8597876492914031095, 17942224190138398306, 1760222146515426983, 1030117883582412628, 6655464189981098460, 14222900139576809037, 13041171493967200019, + 12415333505074758067, 16988669193263876033, 10482573641416551070, 368049292090348794, 16109255925523895167, 4949934055388640387, 12038479532506656790, 10829864449693781036, + 8355401100656399994, 16963696462538033761, 10131652431024537917, 4166156454906166144, 12888240412190236596, 8396312458335953166, 445297814986468978, 10512295830234020744, + 14405236772348157690, 6950094157338825845, 13379457125020057613, 11396720859761560260, 14063367153572826959, 4476298515903789197, 12708437873915498860, 8163633089770520638, + 6432708226771955694, 7524978005081948959, 6442046223716866789, 4082077252385606982, 13626979819841658005, 4264573835620574342, 14788317690584235128, 4710414518172449402, + 9592766374657389840, 3206081438027351157, 16013702689312533501, 15788528722601567812, 18314198451066123850, 13236688692074994659, 3229858297074852748, 2968037605940641303, + 148470760067500612, 10319937899190593880, 7185467485673911733, 13041030391924988650, 17119842693824847662, 10989053172849710331, 16048294708726813099, 6612710923681979611, + 17408606709137505005, 4263600430695220256, 8941719936291239640, 6115030817534063286, 838024703679813150, 9772071103323550178, 14394690179107421621, 8621372196164819917, + 18138724984190926809, 4154767406604950048, 5209478936276366634, 15469512148904762872, 3613429290324777670, 12631812917445459751, 10280179062385049041, 19656860716268566, + }, + { + 12030193727051241373, 13981191132445467472, 18205169646206905593, 12162181194046583886, 10929925499200074058, 15291772758590352491, 8452344520852919320, 8199821440451878776, + 9876482463501409337, 17331045017548147052, 17542726936580732548, 8299195336372136083, 12891767721269002608, 14062358772374813347, 4165127680073507756, 16350672737379495431, + 7595271959296927018, 15286771623821390629, 980612661413312852, 5738158184597378995, 6972117550390447038, 6246497134979772260, 2935831443692029059, 12837371529160496660, + 10228366644420455452, 12084265406352277347, 10265869676493821892, 3560143954870272139, 14368775225608592689, 13173522067191372913, 3592475039513249949, 11243554718624931135, + 15959892157814064696, 1882528744932347842, 3354709518288681174, 14147909176429982637, 12969888425264095514, 12509610747258602648, 10437226619684632037, 7605683691113295811, + 5697384515599291245, 14896081221061315030, 4329502046122948975, 16301954510440819492, 5191621061031169335, 12944691824816066027, 8080452646904372453, 793075614214301908, + 2662373477940179766, 8950125653339535995, 15717799081080898304, 7088593450282143511, 11723351531494404904, 38673945663198753, 5289769381065195334, 1742280067441486108, + 6543255501112359319, 6063422531520498671, 17228726254778244409, 7570754775709645369, 18222396492501523182, 14903937974816691813, 1216646642383641441, 7602781158453005929, + 3007861146695764376, 8267227185027440857, 3177625538211272080, 3144345182124760000, 9215753228267875296, 1342253891473772992, 8185239004636232247, 14951188427081280984, + 10569785547248986188, 3109435167722572449, 13661123218513357442, 4646373703143839998, 9712828426076586682, 11389514152975496268, 9796826623781200498, 234067627740956181, + 2188380882990542468, 9914251329861595119, 13616219875099353594, 16135919125023820218, 10732193797566088293, 7172996278550642736, 8531638916719074975, 14749121691457005349, + 14568782576170814716, 17582848432122737506, 1079387064102681806, 17278567874821675408, 3094302191119669899, 3730448048895347901, 3508894590334961422, 14091660942919228106, + 8414395549498864629, 370884714015114625, 9859130251236103342, 17120282094084970181, 15213286581037020029, 2737545283554254673, 12422648607044275574, 10601123825482591606, + 7332173975514924017, 6689389428877729175, 15162654177270425320, 17333672210015736765, 10717615330136876266, 15245080807947386155, 9830331968044142933, 16156512094344185621, + 9151817936103586393, 3495709317444898385, 10881665308947458223, 7087755261386867019, 18372828768905212167, 12873774245490293443, 12750361906770763255, 17688389897350887716, + 13329033749048978810, 4765695903433858377, 4452680451529163940, 5638854187414651620, 7897503022043776206, 17187635538005569019, 17766753195497526986, 13201529234556380285, + 3638940913491383692, 16533217388164981609, 4668956005988168087, 14053696531704823982, 12029006663244142834, 12043309283447175601, 7840964186868745782, 5691369519440953069, + 8500871974974230561, 6371833132372813539, 4002756625312698938, 7281624589760047276, 8813214993155334737, 7738842112797657395, 12616064385239668311, 11875709199633531753, + 13080663957403320059, 7305658810888170771, 12002632153917673214, 14713338572031413494, 11629178662016777533, 11669230410217642326, 6563025945717173284, 15889630204666511658, + 8934119620399766972, 4226481091885914732, 16000709195004445297, 14687868180928846933, 16269913392757896907, 18294005838441325342, 17625669613551023126, 10864307042201644469, + 1539179629859629979, 3357767843775461146, 2101360073251832751, 17234081431682678130, 10847284171622250162, 2314478515498414576, 17530153382031867644, 16210890762511619844, + 16932765725476234252, 17974885539458965712, 40892050255466590, 13934027942808790590, 6621543269907021363, 11796852321134174354, 16673775773384613137, 3370296079966463186, + 16962514259432373133, 4639769064050336100, 16965148588326727680, 2922022742538957808, 16752379982369550296, 12896050752492664079, 2708685629936199207, 17894058559833424187, + 14722530431277419104, 12333728409662476827, 4162946257347548625, 7052045338975163666, 16435875989376103923, 527141841571514699, 8480360258792897962, 4322786951393806781, + 17366230017999184054, 3121469063237497918, 16903979375392804254, 8204447732627807538, 10469007462907301028, 1938243801077680483, 10156223751968769092, 14290141776757271674, + 2576841693080637380, 17952976066680364360, 4927209893946473523, 12406446420948698970, 18104668447274679200, 11321546081935789882, 11763004760954725540, 7488613143173641394, + 7566233859107262691, 14065899052643539237, 17156645465457086529, 11936850757897686493, 17529993825395532749, 17145245039398670236, 17597009579379584432, 3472628483897995694, + 14380803034817149259, 11042134597430846555, 9992762805140200547, 9895143575678511242, 3228768306004664915, 16153114680219541243, 12036181641761325912, 491369524302296324, + 6378343037075212083, 4634622317247307316, 3415247351446435530, 5939760313513758783, 9540802244218497398, 2134082884335789009, 15623633842188443713, 6824600547587227473, + 2021901489047050575, 4365578779519871721, 8603845379677060773, 8929020214929242215, 13010370953605249273, 8071113541575997356, 10681914788594101574, 13369522272664029829, + 4241327321249984516, 12810477007632864750, 16880581634097860698, 3630333431846970294, 3439918565119627078, 6613942714960548236, 8647431674406387604, 13352599355545805355, + 12320933424684960076, 8906954611339502145, 16931708732547376267, 6446897311644431583, 13749563256713530203, 11522599770043814384, 14455556215959342791, 9022955938835504923, + }, + { + 14734199666349771791, 4159865781008764547, 4413963548436270853, 4489431649937855880, 2824856157476907519, 5111945927271461159, 9825486821405155220, 7657332565522279292, + 8798422177670065832, 1250388939918922012, 5145324733132743026, 3716299737175574168, 14387202892738514375, 10255681359895407489, 8563822744122397080, 18430417713920116013, + 7857399215288147901, 2593284350589299949, 10086687882410147351, 14407837835956327624, 4469878646287387405, 6845712208092605310, 3019047164798827279, 2760591274816994522, + 10930605176025081830, 5850835312463207607, 9603163404664606781, 15623771803942139684, 4096748595672894276, 13060617166821837740, 11222939712741281346, 18445178894593253710, + 7976335583419810431, 16568954524837045521, 5581116346602990350, 18369129318179031997, 1930478946186473631, 14255806344323769850, 5302512325798050097, 10008570767203424472, + 929118050943456183, 445163760697913504, 7208246135487165437, 13565354217377841149, 3835063466770003968, 8214155842021576753, 2078717035803259674, 12502657820500987763, + 17741004372977419914, 16320851348541958575, 11853008901690968430, 9954777341381304447, 14274892887030297417, 10721339848307167540, 8731332510371325649, 13676383433520290197, + 6251805914672095769, 1063060143452094078, 16647397170554915088, 15454955736319919321, 11509235104607349098, 8441647766544589978, 956121464218389431, 10752793912033728149, + 14879603883666664508, 11158422912437249402, 8667988090392051507, 12702057193823135575, 13234479167199208223, 13752955092077643608, 1117550756888145931, 1184967682872965330, + 7004802666964716824, 395433501626287206, 16674151908279399004, 2279551165611331131, 18032555740803644790, 3573953642384243989, 9892480504006025100, 2397759375236735831, + 15032723931727013905, 4176673226777913017, 7270920367565154969, 8867675920919464620, 8174119413251699506, 15030539680120439131, 12325981936900309518, 2932283844656871802, + 3227890727136855788, 10772277744280338071, 10065219931092397730, 17233706446636791341, 1372997838851103811, 14430098741859995846, 3290287064497023581, 13054133915521430696, + 3404625123065318735, 11884832674715736469, 16513753127836546671, 2355202492840722899, 2182039060332057784, 17942518439766613327, 16731345075928062112, 5501869092504492134, + 15704211025163561149, 14596679078416770266, 10262177146233936833, 12443005669252298316, 1541294166390346144, 2952804996209068760, 15358481016273272880, 1321729586231860999, + 6862865331233391228, 15106279167311639122, 3283008666555627541, 13405610967904725343, 9845239597399801983, 10764942720093673542, 6506992344666983370, 2483131164245259278, + 9508384588323002196, 4786531415304518048, 2690306308552249535, 12208815515689370850, 5145548243685871201, 1536915039528215765, 709289946127949333, 7152734178531880864, + 1555309551759198315, 13156609441579560529, 3264147002083956017, 13629162110016732793, 10295903344220946201, 13835148808782379287, 15646840234722388037, 5850505683234532491, + 13348528763144385986, 8174978337870000956, 261860806345683810, 4561309263594732686, 973813267913726588, 5812176512716041479, 14361848397565071235, 9009461390894364897, + 4179825720483458009, 3146850391122074949, 16612045757277946305, 5253713786583408340, 5426943015912173764, 17275032103121420023, 8467860410750483621, 18150546576917688519, + 12762630566060098764, 9762645120146998728, 3635705124656800121, 3295681695622364165, 1764654124266477879, 16610065552429288987, 12182970194869512424, 1144643512390613083, + 10286763540130161498, 3400614528650953395, 16801086752981339314, 5746334081386875705, 4489937467701177898, 9249554406360134002, 8258038249111147700, 1922443676251769427, + 5981893063992017591, 11780456280008557800, 6865399120670384939, 6192294124015342683, 12388377965276278882, 754882660516751393, 13476094069874573591, 1000347292494612314, + 12753947115797128456, 1864834899756446490, 12873792436322150068, 15420857687427067065, 6214698061215951246, 11174167031334850459, 16378107708672199269, 13073812080094584194, + 3531275996684891316, 11764951512033875164, 12239314899306115751, 12701224435273087197, 152051042384837402, 47099568832954431, 766394328496626388, 666084094458729910, + 145223485883456390, 2445564470200462527, 6482144922631612251, 2316071592874761856, 16548688346252111305, 342430477320199814, 17819268336019413198, 9112976726726029531, + 8272548370610798443, 13910434751574602849, 4252192981011400377, 9590519351704710983, 4172183866405471444, 5567646223402949380, 6059725713353637560, 7169982539312028092, + 8422701298619809502, 5749403137850675219, 16696307763582818287, 7683947097864552851, 8685161999810728314, 15931494353777534155, 21629333141204286, 14374464903502564030, + 2354260355218724624, 2822702976206523812, 15817484232297668127, 8389777239766813455, 7962301702220496539, 8489354871723216960, 6637394823950686331, 5853452396705295777, + 5949957329602421631, 18059540496274524007, 301304345046470155, 15775279105880040289, 15979581939040500554, 7142046514802237176, 9965619645220287167, 14369754349691428035, + 8777708254369249245, 17882304730732025188, 3127583543205765491, 17274466425160820249, 12870181470212293464, 5881181695848312122, 15338161852429951632, 7245877162563127935, + 2634466441339054819, 13057158409330115380, 7410310056430957860, 16362149248469660371, 1435827663585128427, 8005375008235415486, 10865470829924734253, 3177600727860863968, + 9627905753364576437, 12776456422166281355, 2851899644189834214, 16998174196920379994, 9001602524188761177, 8960294999163663712, 6580949973363012183, 7568306074815116797, + }, + { + 13345381996769253014, 6278048669175242345, 15990349685835870151, 16358261962292186792, 8505261070637963021, 9396725065098564446, 15331953351049782155, 16194796339208321205, + 7076257175157660597, 13221730879315432464, 4499548735964119085, 7559253754663705944, 10196808438730350168, 2391718471837563931, 914409564589897387, 6649744842278078706, + 5502356275170104522, 12750322860129485966, 9581277511584938955, 3872282844937972630, 13668854758739140874, 15020438121087800965, 4581631138384430657, 13296613956093963588, + 14380343880230315251, 6834909096379668102, 15975839936772635678, 7738230945027714388, 7971648870467745046, 8320128435052726628, 10820026056424631461, 7058118462476293754, + 7264036154081699231, 1304060579978677195, 18166928140052040308, 12593450560996175288, 16027666629366472835, 3677101504316839585, 1477956412235870359, 11566116495906585190, + 5990066097615398579, 2092999434824845091, 774626818169813708, 12815491981614523669, 6993666706115136402, 17707947501239782961, 4907798919001453899, 8644498548438963907, + 10893744790193607860, 5425031394266373727, 7829758685118664025, 11448863214220512751, 12538690882574195219, 5021176303769859871, 5820297470465439264, 5119144562842414323, + 11165438517321289842, 8661037418831619311, 4401480924846865713, 9355650368902126256, 14352422544185763829, 12268031594529744663, 17607497268577344783, 12698954426769962214, + 5383780168621648368, 3613813760948797485, 5757643543708300439, 11434310585555684688, 2345981080034027974, 17817292757133028083, 18327982597027759229, 3812144950722314021, + 8792386854586041066, 18039588893139878329, 5501406599000558473, 17117814302557684702, 7341401626090786647, 13233670006052290433, 2192568639640447778, 8946253989965365943, + 16557600339807647183, 3024845786116641335, 415867109882960964, 5024769423994345740, 6707880221250244075, 1889203596997453159, 2063004021323938442, 15149146696320496954, + 5091534986326281709, 8005812102849517353, 17366496686564185717, 3658878980438307796, 8455810244524637026, 7649393961871195909, 8629386422022530934, 507133797409068858, + 8757568869745664865, 18237318628906764926, 3340648953867756474, 561136277959994100, 7271097445297070958, 2011054670254573698, 5452809131990689118, 13469888024447314143, + 609640447772904263, 18299734743899574512, 9082773418653747144, 17312950936823165983, 8565594704932296493, 366163155689429929, 12596423288683198842, 6787120926470876217, + 18404298100226778075, 8425329164435445437, 7431919288426595458, 10680902470574406179, 7944931189168061880, 9822761000408762356, 794258562727155839, 14627123549563592012, + 10098955144981013765, 4095621933458866623, 313357785962326778, 14880249056209398407, 10605627454111004262, 7841561005378789988, 5015399193497762029, 5818383539901203899, + 486788682374900660, 17535646661984222270, 10786441143551223569, 9744277172896797168, 3600223448942144865, 8847805713765285452, 15255336563751266306, 14792236445425212896, + 1569380763811592357, 16850350231819425451, 14974316825768144065, 2974893813338477794, 16726324408135381195, 15000665607479486464, 886632233152598796, 3783793991897659851, + 17267037371866619240, 16498595171305365582, 6453906744948258368, 17267405673163971478, 1676214913570622682, 5051819157163581842, 4315279707026326708, 15525840981760267164, + 829322392873083372, 3459913121476606612, 4547714508342797986, 5801286056105229312, 11591136160675314269, 17965845487226778560, 7022309609363885527, 5990586084398664157, + 17415594387520595717, 1453256163777911406, 8242859112004661961, 17561205531134219898, 4881570838375824387, 8392772608437744175, 8797957464506597080, 3142154188155936579, + 6248409301753564092, 912147011448492506, 10413108318416902948, 3349445377400918439, 15887909530347096066, 5138859116738406557, 10990929831134698266, 5911273060564729281, + 5197581879950405305, 3001975514736631403, 1919678782193534342, 16811100109848336275, 13086769249238533805, 4351245282425706500, 18281601243717625371, 16799537683941038764, + 6288277991521986035, 12231480617236286340, 8633990423689180869, 13535190275290488690, 13419223868164389899, 17622732596713666209, 10071779220640400024, 9451660464882303005, + 14029940454474238624, 4957972603307996503, 6311878080193524221, 7485203809274562760, 14450074580092843779, 16845073066403496624, 15870387052570816676, 15700883809468229388, + 6623653867803819118, 1037643671564549885, 1236506073247459642, 2997396263933967582, 6182371056378366305, 9773995232878719062, 3356495419149379609, 10710833980055523526, + 9965766500412107699, 16895652751136174589, 7310937934566947318, 17649841370865305295, 5052693369483848536, 8093060855248113928, 15777336335257114359, 4642979535698186085, + 11761084765182152401, 9226969173242076459, 5445719591917489914, 9371133174853825566, 18381867235964583187, 17262888224001222346, 1934253649802391267, 3574888052111089863, + 7862401495691359736, 674970329153306547, 14447324101549742216, 15408908436196428001, 5339840774639473099, 15542473999923245378, 17353380999887736706, 17787369898686553525, + 2301964326759931592, 17775852221342579469, 345763078096690431, 5079606662887837532, 14863722102334084051, 8905941255852264870, 3806200576416892831, 6668327519801544161, + 3672519063263749482, 11898207454593385701, 2364050348970898536, 3761861796987022528, 8159458273489411574, 3231262679605967088, 17179214124164291006, 8770284079122589350, + 15270079546607712667, 8471883658965202468, 10333206241569264742, 7414741159725097798, 7709713706668701850, 4461310100162632915, 10099194304024685274, 4760203118683828795, + }, + { + 7237168574323016859, 17908810107504968137, 16225708127838178121, 11127095986977103648, 9346291308317410251, 7381283458277047010, 15168602815371846943, 9193719743691734294, + 9607254959726458411, 16837156817186931862, 16178143308706847393, 10970721795101931539, 10840376278605273092, 8298765077094727469, 15520543037910966843, 11484620381947762562, + 17395070963094117711, 7608132718922490881, 6531178971071758016, 1302814667007331361, 4002629363862769670, 14649492495298089937, 6868174210142585697, 15456170652716048683, + 3688308493559609536, 5123828159813683938, 6245436817220183971, 13062234263274605325, 1313395302496832996, 4961840797708687855, 4990192311341859196, 5283131006216350959, + 16952735659396950704, 1249482796824289329, 17859504101404809981, 13260403650830168625, 1583343855370236084, 11389120333403185826, 13676599385745755008, 5066667130137739346, + 4799264864906918301, 18347145714884655971, 17034125441088681346, 11828378178487279470, 1759038296522081901, 9582407833575609381, 4195817009050503354, 12618256395967210055, + 6486755100213398364, 5270923715575268322, 9268255346880651103, 3147724493117082267, 16710318779269985633, 1240462642985509644, 2400811796254219369, 13670743068809614358, + 11437779990773246594, 13609113239383378152, 31268927496646090, 11618772705165035208, 3078024460365036167, 12138983306908962712, 4779157919015181380, 11901698850260672002, + 14642787507945832432, 16258081639927585935, 2560321462542164242, 16286882196975458174, 4328159372518768969, 14313553865397841147, 13769372656320240568, 8950675126435331579, + 1309709344837422378, 18403288028608342631, 17102350491414677993, 1133523394849437315, 12526496222782003755, 5447309058259018864, 17311120581405946631, 3760058661125144368, + 17891474172606596407, 320094264574086461, 93927075222964142, 14355817838636249140, 1777882427773785068, 8237021421587560510, 11520559469641852991, 10567910693910023157, + 9164300764173563614, 12322279811717869943, 2768902015676238485, 7761799112151133995, 5740162933856370894, 8043946608495226840, 8923704438836381869, 15189322655373943849, + 12046275966378825708, 5909386969214935556, 1201990704907881028, 12128549009950617306, 10773478878317625320, 4554854625564648958, 14029736945871573056, 1353247251064221090, + 11909123603272307101, 5517949035179831783, 3295386484950432959, 5605137795524476293, 10718654547602473221, 4984952409581272095, 883267724006996723, 17328431094026829348, + 13671210467347025770, 9980617617519781731, 8339868735163579231, 2150724314757661915, 8571153021065445899, 9146903697769397191, 9122246102814640373, 7744779513085605450, + 5733697799130763963, 962857090393715865, 10538932452511329419, 3413281437172590207, 6635428480179771287, 4404718679994229138, 329074170931436370, 17746708206910902139, + 465623292609655544, 12740391094094156750, 15600221933467635716, 10712500242632508096, 4760789577759901270, 408323003115848014, 464706673403009712, 11801112998381624421, + 5545681129476190458, 8725689673989867696, 2143812364199804063, 12133065347666807143, 14072918710585286097, 9027361966934517640, 12608281386782336413, 2053972384317260152, + 11862793362110657447, 2615766363986534825, 5065170482898519596, 2878903691735623036, 5204682974850023849, 3382494556217615091, 15421437169807703253, 14936317525837021790, + 12363228588136583724, 15035239525394825264, 16312817933687103988, 5294641777817034798, 1197907056067071148, 13084871057903003628, 5240492218216802394, 13798739245031559476, + 16167519903361647970, 13106036157861122437, 2112866661358918425, 941609107359251234, 7240286582201258992, 17783018133711208779, 10433192833270769862, 4303514224506582113, + 1549168540255262874, 7958641388293572779, 17867057222043259063, 1752211085999288773, 11828273580240483781, 11712913016012991853, 2373360154803731890, 6779610934665321824, + 6633997178003959408, 145323909693817907, 2198452664824754574, 2920221908918689777, 11047294234593305837, 16840329825128198329, 5479733463453508239, 14054694221361300990, + 7908792292118068471, 2703859967221946473, 6268006869726038724, 9406994672213611166, 12424098071734234719, 11900750387777467409, 10724482893673149484, 3191937460539390989, + 7635348735946750413, 15019610708452651937, 107671898858364780, 16808612119435524257, 6120109999123152232, 2251481693156523545, 10792076820325151003, 12924551065805570215, + 11225852067204798645, 7665324911993544151, 10402215331683389905, 2856131542917118235, 14152013119539822346, 12731746180172488022, 16402457225039188820, 11129045951416314666, + 13009066459618795885, 9636541685854928780, 4783713672495759319, 13224924194053497016, 8044695420996588716, 4054951559323242873, 8718047667110955699, 13479622910466265834, + 4333570709684826136, 3188483692974505359, 17976757824852085147, 12585927226835238762, 16665346689006249776, 14033419552450595393, 12216049696243171604, 447536030797427204, + 14100792221456700414, 11757964686555543320, 3971513799111193530, 224065891283865758, 1282520657830780512, 9120233956471705454, 13711191981326748211, 3725543277190035504, + 12094220323799678341, 16876894723130932646, 14806566188177921577, 2283878370700345373, 12254260799985999571, 12764268124075139223, 2425316412794046071, 2088679341162220742, + 172600248248909168, 4338060849169481673, 12046085844143054569, 16220699277291497444, 10358794035289405365, 6739081270984238196, 16079387007561085178, 13471688054064884318, + 179238781994802586, 9017860544212172426, 16179187983079961859, 1380105261896053495, 6187003332254463653, 9896593306091975718, 17181949235068293496, 6820143159816507763, + }, + { + 11156900805411912784, 1737275748212365168, 16993486692205800040, 12538938066475152524, 13167476167764338790, 17373319366642541595, 6054831428930905282, 7118452124011953000, + 743288751022377974, 9226164090128370715, 17669221687181604232, 1117842260351396541, 17697784451833850722, 14382209306891991103, 16951372733687268016, 188390802712613066, + 13268209255833199938, 16633146482265079265, 6044233937395578074, 1733872861371247406, 14239198956565602758, 4036306057099495106, 1778912298053970082, 6174082695927204648, + 6390361653475754940, 1093882175267357438, 3784079074949811167, 17343872969822169769, 3359715652121662979, 16808529787251986583, 5169730697018536870, 52766949850965558, + 1403521870654810721, 11668153767441183906, 12890534559297323775, 13255750643204945388, 8838011266491753399, 8488733891344199335, 7468199299966346977, 10645543722243906719, + 17019046551094178629, 3055711824867115856, 10841870683594132444, 382072777978364200, 725450988418371589, 12501774248954630111, 10130164067258601487, 7823254091037946722, + 1866199290196467180, 554488389245696218, 15654194385091454776, 6131785419830586829, 17856850737824439617, 17602611196814472081, 18244498160243832872, 5819736122106091373, + 13147212495082910072, 5628914243538540648, 439989514095330941, 7620472329041817834, 4272251824771633288, 16564977601507013119, 5441117136715882317, 5622571730905974389, + 8706277077547369587, 4848592786700984858, 11350018329458740004, 143688324288835298, 16536982722430328270, 6522962371020150117, 9511378862712142567, 18221873727623821967, + 3985496688414455558, 11118602672015528143, 5383196298446424580, 6116994806363767576, 4051800833472889243, 12236802048340231756, 2619572929682123355, 6008593592518397571, + 18159379849046931840, 11283007389905902377, 7465803490016928282, 7730454089227756796, 3569936088077890000, 2804205711716327520, 14107136042131448408, 12050401455009236937, + 4207421531032215145, 7924589143024019458, 5496622772676523695, 7061817399179278712, 7371689806847905735, 8282663810521090335, 11422487361383982601, 6397294642072086677, + 15924576759579234055, 9923512276109397968, 6142441356128988365, 11189756906743802872, 17790684027455851021, 14143953977451478354, 4002828116425422775, 7521923183240026608, + 8349314793194266723, 8850246337652136896, 16635419760398709839, 12466509089914036008, 2686508850003621675, 15822032015692543407, 2211302095278204426, 12550915236378020964, + 3844358527917324404, 15045102416646491178, 558560187822263769, 119801275176287297, 15593003307431898979, 12817356186703401527, 531419248069516921, 7957931139148417935, + 960381383357168877, 16774709963697143275, 17896181076874992240, 1150415168189819777, 5498481130530161530, 6895900060791069290, 2079514944189747822, 3428689507902936354, + 8525743843643076774, 6014251588524085384, 16423924202355808346, 2605496565158241796, 16676209604549923678, 4870342652354143869, 8337072895802905281, 2478197702680510974, + 17076629945963768258, 7647523525256473652, 3999707005939039144, 9578933944626939348, 10469359763046002307, 17515033080264359276, 14272203721184987484, 9979666177276073145, + 3896303254672567310, 17167309259158926479, 13231865857998180315, 2260217573257466310, 15465674863730076330, 4460025914284098438, 718707264700157542, 7215235109325196153, + 12056920178557394302, 5131253251712581899, 16251877995882633963, 10883064494054484051, 9473274815269607947, 8874308005470196739, 4412709653190846630, 16469366225886156991, + 13309932065155297376, 11504232979548718747, 14366229841750030472, 12797870458094162590, 12894694064456675527, 16977997035748966590, 15080606548583635864, 9292471759789693596, + 1226107676031264801, 2683510924831720521, 4344623677417870872, 6581244316153602113, 12516966236091151915, 6758725397469564403, 3190083750600883646, 13018714111448482165, + 877612159223846777, 1550479938877814973, 11850498481046386377, 18144061425551419288, 6811504328538189985, 16351446194603329949, 14495016749549056145, 15394017693349630053, + 3547198835521135552, 9940690805769919242, 15170549880149605690, 10701681269101530298, 5914809102954412895, 15790219349994701461, 13664049285300230863, 5735249081148743651, + 12395092509541605535, 2320592554345067500, 14213227630916688382, 12847883717490005600, 10192971941898238362, 18392117086623245662, 14369915478097042954, 9636190568462370402, + 13308009076055104849, 9679299541833059768, 1512845037409468381, 18211703514703978816, 8337549295001075127, 15882458005321062689, 1212364284844818969, 13856780176955551126, + 7602636613718406141, 2678224565451628558, 6976331354727208830, 7414684104929828967, 13536889690553324858, 13086024708711030952, 3748455179863046304, 1853373561223967487, + 14753645881295168970, 9410794713982813264, 13485977523338061503, 14267793994973767571, 15813187206361118954, 16449603969001878152, 17705410933007144731, 10960511750491378082, + 42380674434071200, 10068881872338405083, 14327149378182272744, 18264050153181932597, 8600790433943161385, 2952021171158508784, 13461070885471956301, 9633226987835715039, + 10360728550079953555, 8471248683929284652, 6673003382103023756, 8972723925695500528, 5941683993959582947, 13500073059240140624, 17856131583218769324, 16799784995825923732, + 7292102941225494742, 4807816512907139693, 11271815982004383122, 1065441269547643077, 5279915279332961503, 12100441009657772185, 10448964764090871372, 2944169874578456259, + 4669722990542640772, 10017368027073540045, 13392819319228640800, 1070815632453829996, 7274130058405640448, 4460835865761538026, 15283885107956150892, 5815884817303156137, + }, + { + 987127652983079722, 6872208513691823695, 10110578719299008714, 16457381243184327116, 10779072738879347999, 5965282398006505989, 18251577267494363268, 9321323379108563422, + 6119049170407437179, 12938407708038792521, 10105420405825346383, 3416306788177016826, 330648587825212481, 125568991290568141, 13857127346570918649, 4376080986981308805, + 5930434126597036589, 11240994623469578584, 839346533006694594, 10015087329724081709, 6285097815938761787, 17244606485954860090, 11523249727882012981, 7178451948850151803, + 16733615335426327004, 14833564736134873977, 15736159435317472941, 17560193966711884894, 4670172300306758374, 9477713670983496835, 14243955354032737980, 6459864769649694970, + 16053517698989562256, 2069464650596796670, 18305730134729303993, 1090863611964008044, 10595928817546105363, 11743183506441120484, 8584767248013363683, 9187452830514379903, + 6938579711827578880, 16268282168771714072, 4567473305742437221, 754548046014059669, 7773636946295303572, 8132380485366854656, 5054542590195827722, 6074347500754248128, + 3955857908381474930, 11852678900999621852, 13783017203403417097, 13616745777931267488, 13189924588414196918, 14519927295809952876, 9334100965942760501, 15172548734242885286, + 4869852132020793901, 14921212823114724347, 14342559113353033349, 13336827701782657309, 11168346789878684452, 9790480725902426052, 9171116079841529936, 9268902731763220711, + 4417372365016540659, 17280138652899703220, 6650972319709075180, 11252221422799491438, 6825784270383052414, 18308562203755695191, 4237445205082731447, 8485872406483449772, + 11718726714045105993, 2624508790343569765, 5794111482300008213, 12819216567095091385, 285329842793152354, 17257707863943097374, 16912487373614458842, 9501952033607497057, + 13074643344738491288, 8505193022029238118, 9932652098552590323, 267408114280737600, 14802861246220332716, 17506028737327736269, 15929083591675282371, 10937680132245212187, + 16688733766460131050, 12777635326299184071, 7769405825716531061, 12435979606514844725, 2767987141420672349, 6723940414217341603, 16114182069580717377, 4541113259200434040, + 8506371389960537559, 18031198550689409305, 11510251852995503442, 1923472385053944821, 6189904387119195613, 345664413118550356, 6439003191582953600, 18344385760549575361, + 5320548958745018096, 8341561189829530680, 3327828110998403156, 17981346269177513223, 14254804273025688074, 11111147827704077234, 9093333670517437191, 7272552282364063165, + 7587268797387514088, 4402481408866840263, 11260815389095334885, 14391444701764948710, 4224880318604689771, 2472148458660279030, 961218007313548745, 13826356220879831691, + 4477325369345373420, 299141931133875776, 6787652129916359301, 2498016036564260464, 13342319943892943548, 11124287719737492205, 2456333599771808442, 5084719026388755304, + 11208298545009109072, 9361672558653085726, 11597473974277116433, 9123409098329262113, 2315750487079392743, 14788891796020803799, 16477373474431052867, 6394267218565388055, + 15099803091969065643, 7815556206466442264, 10304177785190927723, 6493522556494567776, 14386173575053274652, 4399768637448990408, 2996083572119906777, 9762267038999270167, + 204205141115459509, 15145142808374731170, 1678672167166598389, 12032976094920574395, 7472791648310888425, 3687068899306742850, 2661021646792225638, 13705804163602287184, + 9320611303424530507, 7295004960403065170, 15749376924513664173, 11543669941217924178, 3710258597217352196, 11371260298937340150, 3902566672028686120, 17983841473999282668, + 11814188798674654097, 13017429106091059634, 11079902218909650978, 9064898043690914606, 12023954026861289442, 3592879256613061321, 9997625973577562433, 16073808232708438680, + 15365030910001289574, 8789654976305207659, 3460532362538090307, 12992239135084766157, 11449242863169591803, 5418502644558230048, 7981056000757137731, 13021725301900406539, + 7782773734814780443, 9390379677704432300, 7130223982341575476, 6496906770393189740, 5095392170846288421, 11058865093605824851, 11021902438459302094, 6088242418938968652, + 5966014717657529537, 5136588784988696205, 6360472729290909457, 4447169061266082500, 12506934948427595318, 16433395045878253504, 5116318868244944213, 6640832565780621049, + 4132920736998081103, 11827975663170283136, 379030309731223785, 3149051804072184938, 12035317616979166548, 9642536337674500310, 15531497803043399747, 14399049832547796531, + 5493097462539196248, 1629980144571354138, 13641173578972112594, 11096917099468924214, 10934169048860132281, 11269991112518485434, 11206050457519414207, 7939067479736521906, + 3806755078949823895, 15988975666336042818, 8246267395645554105, 9703363749164024623, 7795606269507901456, 451102251659512683, 5865831186929065346, 81064915983990550, + 5810137226573964106, 8424253088401255706, 4543883508937971494, 7386148745257823512, 1348150366217548727, 2103092839740150931, 8353010273955146981, 16831854467863536537, + 5095778754322493440, 16577416628492146129, 12288076721910512064, 10563487622054214075, 14620553808255752273, 8159958565993701874, 6712100880095874267, 13203797993773281759, + 9640010815039549413, 17460773950401928956, 18229977265837445092, 9252634318278265623, 16798979334068219458, 11731856767337519419, 1551975378671663669, 14320102155496153821, + 10528988339881191052, 3808685834232068820, 1064376960475785008, 6466670187430364599, 16860839938395945578, 8876458447995837267, 7897541112736965607, 10283235741250763328, + 12246932755942887931, 10842213418139067847, 1827392608284960926, 6961756951208563550, 14626966634382828071, 12653808277900379805, 3359368990539585596, 1190255644328095727, + }, + { + 10836955050615624183, 6228108794259714192, 3769609579318360527, 1481673673659326756, 301329772189110029, 3574710782304999603, 3037244905687722509, 14442941761397229485, + 7739110373965523311, 11019153332996240080, 7346010155518751797, 14853737521111213548, 2542883237207113209, 11015136828834421504, 1998601666328316353, 1540417751495800469, + 599034134015360884, 11263317530774995092, 6667501365379084069, 9844276013103312691, 7566306886180438990, 13702768345615509363, 12525031963170717968, 8463786212988210464, + 16430555432520738762, 11225321696360643709, 11777973654353154098, 13133115227828884393, 17678738157022850345, 1586660156856830642, 840647763693221003, 8645742354464326466, + 8067725618510810414, 6229041032854057836, 8025364837156161898, 1290443646630661359, 10991323655842003728, 9346782840170054789, 8939059450584871902, 4772347025802041241, + 8187379062828795656, 14744366698824202673, 17014663804743197103, 7704635785366672415, 17162645929628468457, 12942442527592695216, 13291710923558633295, 5800071247768119960, + 3552067877931717181, 590108493628737243, 497390871097272557, 12785795808441396281, 5561451613221796230, 14263823913216836845, 10481729699001112354, 7818094022046194698, + 3598736754916501501, 4827022662021197854, 8203180748141933720, 10283251600632599041, 16186680658340956808, 15183393398087319142, 8714402370450665212, 13217902016653171217, + 13766344083396522552, 3843491774288631026, 1174164282483810421, 6398024882371290634, 5459580537585379131, 5871096222069618377, 9611875286525007701, 1940221124144536452, + 11598781954647517543, 15695098933552070478, 14976427118847622464, 7147358677856872160, 17135524627354123951, 8338407198954935663, 18099467407613897492, 9025371359994313919, + 11451018285787631498, 11710749546511767589, 12969419493657624536, 2338911230088800542, 17492614411321910750, 15274296072504110502, 1258801445108685875, 15178229640559232741, + 11743016372336018414, 6125536020759642301, 16563280170798047733, 14529052521060111789, 15253502329174644388, 1556763737841306861, 3041940064290508531, 18020881359462953336, + 3035547704692483898, 462291414338050452, 4209186193642705826, 929930084709639338, 5246348806539841852, 16407585218848843770, 6076996892610687611, 16547395936238439809, + 7781914900266335582, 17967080065814694611, 14677062197599091614, 6667353926398988267, 5658765839564756939, 15807817354312473921, 7476371642206655552, 1194561222317134506, + 10645607622061780068, 11583886495890779582, 6879987349345299140, 5119348262235800038, 6546217876212430196, 5534845503308945424, 2003680599532879233, 2824480091030475274, + 2297585344913389180, 13965959247788377604, 11341378863608387800, 9890953382689640379, 10443523266835246852, 9631856696811288063, 6944503116553031744, 10030824122780966395, + 2699238910420203023, 13176131497943324759, 2961070701879546988, 1511208990650977146, 13153451530298458944, 254163587562261430, 6668642257003911712, 9040693998431169077, + 5596789796292416136, 10505785820531892681, 3803057245175025164, 13601446877323203658, 7939638174866660891, 14141848241206986005, 13782885912650943563, 6287188921995938212, + 12999700407775352603, 2664314004284450753, 7085329252118415126, 17472483363754271126, 15550759073378819069, 7572177503239633527, 15705617684783232308, 8586972133880335199, + 6636244234467769744, 18284390012667441869, 722929822219329257, 3274166388651987221, 13177791837760949480, 2568122970128111127, 3477167651270374316, 11371867850093288299, + 4065583279544717744, 15575999213135020408, 1319417044854511604, 14713082471342741360, 9399053450949627084, 8900637792268080986, 13511414538589410393, 601556817111475086, + 9243142430859561073, 14638657859832212223, 15324499241122936340, 14477761753578941934, 14699832840191454785, 5114873517253108658, 7427057898915535537, 12536800031182849473, + 11775949216482616439, 9736654184925478086, 2941126957776086651, 11331303510371804917, 3535865528819665754, 2488682969529955908, 922100556888217739, 17904958255578472855, + 12876460969864886954, 4692925517843901006, 17390372170975588763, 14692578774429957295, 1759864963511373267, 12016553435172103063, 13015881292003590351, 16187569590073958370, + 15154092100094191059, 8103665941237580228, 3265383210728928809, 8341136973870067643, 17281635732314163959, 16433737305161442677, 9130496888060417111, 7070932927684908859, + 2129695226164849659, 15163429615374108928, 2225893409909150746, 7870945454511315288, 11525457118388411301, 10519485231888976311, 17601979933176863246, 5257431126828903605, + 8898009465920717074, 9418463821940622934, 3166596280515383312, 14529914354665032916, 17743784337460844568, 15964972678726654742, 17116339264937332927, 17098426671353029801, + 5868176722765418764, 8429364877332796959, 7785756492654137899, 14975349488807886278, 3272010964035218775, 8946396491617515063, 3774503492701710541, 2113917870331282160, + 8185651664029868180, 7343199417670698200, 16586532029502206227, 1531724981369431299, 5596507566645246686, 1033673521199123313, 6075312368002387319, 6988496924054716781, + 4604669688530289732, 1867259042549585024, 16180237500272383882, 3296394050993129267, 4326520583229998770, 6557569103657179065, 4126356691591689646, 8674328613473447843, + 18057076842177382833, 13020419432300857029, 13646402493577420410, 16962268104464192344, 5358581430340252761, 16443104373870300795, 10099216829282619724, 14890543634568831960, + 13276631120161396750, 16968574704982977753, 2376454925072971568, 9477134218094425043, 13784622991820528988, 2074505569780291922, 14294803056569335889, 8759684036994631222, + }, + { + 16549155412115374305, 75977962737081600, 8870825488941031605, 7403557657089993256, 5825394234709429518, 11978746413791918409, 1876293130790608838, 9416631623519692610, + 12346821858361333862, 6352722970730511156, 9920942104315084988, 10492373916708072181, 11163323626947992791, 17035282992056675772, 835685192553490421, 12792459312570503983, + 10447922451077327640, 1515090998837129975, 13498807582085718212, 1212623301098019779, 11573518650162536086, 4823461685803772444, 7289704908733783271, 13167881392748327839, + 16959954449957105311, 11051594981465026138, 16062472412226411858, 1976004115345602080, 3630495248560019222, 12698191555196404138, 10107923614229901155, 1597725222698864118, + 3416019089997140849, 3011417601086561495, 6275242351124667286, 14197557183081060761, 5633711018871057458, 9723496411345030748, 13910057756335530832, 7285051335492395815, + 16774605620279328247, 10223834398868957807, 15781733027568799739, 2607095622729296315, 16499590296954181006, 7576646116121533069, 16638313875339315529, 14296194207652471696, + 12874411821611501068, 1998417862388106640, 13882642435422318946, 5791129521978463837, 7512934139125398199, 6966283273373526248, 5475728301311080129, 13542211842758381589, + 7798993150530415596, 3288770257171840452, 13373286069558329631, 9784279046496345014, 15725032660238528813, 16038931923358478835, 6921788930154218900, 6093507035435214187, + 12194839527972802101, 8376199250979271449, 9055995864116790217, 8125030124567662718, 1070812422878398727, 3950906148308170707, 10121516919638719072, 813471384549762068, + 7610605259962047827, 14617655900985224117, 16089669078196617440, 10594009761533811214, 3425971360520359121, 1245021768718221594, 16690372892586114152, 9933179766195044175, + 15142732720676276463, 17435583143726694663, 6030257647680338377, 243683009289621849, 3064238900429394982, 7655019927497549159, 4484400084400458429, 11650860345018651068, + 16203650576183697977, 17614744533772112337, 1119292890050870301, 4574885263986729787, 8108207498737924504, 9708434439316056191, 10676823369888368482, 1078311554675991883, + 6876202174636220158, 18057502510666060150, 7821730895845187783, 8882321799602877790, 16220624224336230256, 15562800387021280583, 3043825293109091520, 697130162105054983, + 5394549491776704087, 14795348078061113966, 14206080764200897220, 4623073019242398493, 5850602047109930316, 13783531993760979209, 14764346975698048641, 8951680172224205890, + 7302725075484262769, 12572584665857403749, 6499691362933905099, 14476353114356185371, 7381716148644532401, 1573798302334388880, 8128390307766282880, 14547454176248589604, + 12109367644744157376, 18037756988516427980, 814572839386760074, 913616818805172815, 12974490864633240943, 5228203788953366069, 11458421156905635350, 14534725545904442520, + 7717994192616957513, 12204841747568567286, 3911093871228418198, 11236736110419819217, 3283907124458179474, 11742518530965881218, 15033771683298452989, 5201173013910789542, + 13950307561490203211, 2109530041534182225, 16966608361725322273, 17050013487213560977, 6582524050666171954, 8348662591649610062, 18257068567217206885, 12084557407109908164, + 18134052713971906645, 13522834551049471624, 11796035797088472898, 4408384297249203940, 13184035659663315829, 10318594606381671372, 43784547091343099, 5864759723778872652, + 273751009786971880, 17433500308695913052, 14095169299451888252, 9384697581863180516, 3670310635026975567, 7512955195757960238, 1061441390592395566, 8687976820410979119, + 5847434943730572861, 6139588162124989313, 16640425042872222986, 2868461478718351559, 4582082172412426839, 15999623457772192080, 3911979819012561187, 2157661418664981538, + 1679437503202036379, 3357369754420384657, 14227038694942012893, 10849243658636382261, 14698996273665673323, 15473144682787301630, 12886363027445513063, 4218522843946321369, + 4305571301049736163, 7569433164869749160, 9286896219015408706, 3061813620853218759, 13836461093317197944, 12893856993043908140, 17368798334120212403, 3507360881370918016, + 17887381848254057882, 5080557806347717197, 10977337278063191668, 13725230338861893934, 12618602415751234016, 7913767807930932665, 7119689779124353718, 14253582440914432409, + 16180079775228731323, 7952167928403988663, 17529082815577219791, 14568667835887326401, 80331144542697157, 16190739578357987369, 8688615216852085496, 16668129019590270615, + 7430615013050690552, 16490141830322172211, 9793941851666815428, 12678643730925993658, 248986629347794843, 14250412400606998841, 7671639316274744213, 198890803142183275, + 14099347485199617889, 10490379547566026579, 2979540189595374423, 1947868558918413664, 14807112327541983728, 2275659819146309375, 14464189275380358394, 11448352451702208893, + 6508543885912264241, 11768683250765503158, 10952591955476802447, 13816638967602836229, 15422608700909569544, 2270147616630940233, 11179267547770249728, 10448962907285827304, + 16734703714440778657, 5221611440144584595, 14517195248502569256, 17256223341936104100, 13260411672715241049, 15406026631864099983, 13737383554048659263, 15455560302156741675, + 1751310744149771156, 13066379976997527874, 3353407191478085130, 1488844206746128853, 5630044290904406795, 14205180196532348798, 10021323252656730909, 4177092513333669169, + 16120743770319899284, 12307096057555293266, 15459231763664176764, 889710173957193674, 4419259815443372538, 17256024223837463177, 6105822529166486288, 14459703836399905847, + 13918155529832261002, 12953608416498491778, 4285102780598248527, 15853935066983430239, 2610351403194505517, 14905969693015035277, 12043976761492019990, 3883507340167876094, + }, + { + 10994470105201067642, 16033352651464686189, 15774427704233149170, 4596106024708523955, 8854068685612048031, 13529126595187822090, 11509928293490788309, 11620850709434334690, + 2068337952936280662, 6856444059219131741, 17213926210819196459, 513413453513211652, 5520465604253824995, 12970886588014924605, 12296275668437451137, 16808287251356954962, + 3413637388791433603, 16937929882486384885, 11215805046681294327, 11559398419268924015, 11697258172757450737, 6137795229387768085, 3190984692021653574, 15347236891154706739, + 17955247196574331290, 285928599571507431, 11902987704297070981, 2841167725097799100, 9281167410796848363, 16444340476026142274, 3423202423051178709, 9101021305726472246, + 7129792976024548817, 11116052691850916690, 13765136177550464799, 15815419857669199536, 3490265904262366633, 3075105190264147815, 13090337405102529529, 3772589223509323910, + 1865569627339845981, 14405510401062639678, 16548248891153314376, 18134729633170718083, 7342289204282809135, 13678804825671892797, 11309594694670555920, 6482941613725556691, + 15861081392207208208, 8373665453512079014, 1489270058265748447, 3594001972161344915, 1115942979837741628, 11080512787291988167, 8129036993725083225, 3358115086982889477, + 8869273893561412239, 10349812081309865197, 8913824872487209090, 3148808685596180274, 530908416884501807, 10284103744075805979, 13606889938905754722, 2418062398586758364, + 12413212040240282991, 7478703750955930147, 1623142090654002287, 3800351594986125089, 483782039790230646, 7823394007049468275, 7643246613581822171, 15001087565682987468, + 4027740097060141621, 11299467443664320327, 11151439614540606708, 866223440636939151, 3440384894029167420, 3873155505711856537, 5954029035616033594, 15381861683078360474, + 536906646315848696, 4762701494256722953, 3244970900590282998, 13809219136128336072, 6259009038800226590, 15448401588227595780, 5228638796256712654, 52817644221507266, + 2298603653884322501, 601221199968240092, 1285112712738261659, 13882709760355308533, 13563254433762438170, 13447718334658435053, 13493687958886238103, 11032778298151679283, + 17130548285854289846, 13389656739579236890, 11825243553071488462, 3295650559395515332, 5681593832990094932, 1986112566735995333, 6900923912677810734, 12885634718618182763, + 5991348986251844787, 10652959958005297329, 4727138097613835700, 11665606181484659859, 17818486388489237050, 17381457056943650121, 11483713831771420728, 14346336385265122549, + 6806904066777263417, 13464056321884738018, 6982639430167685380, 7669355554060154277, 5859444273628884163, 13073052226541367148, 9082949662405155834, 12390918296713433257, + 8626760324117733843, 16403951745962159364, 5837394731212322914, 6847167719031297053, 2888142337636247281, 3409818743436360750, 1677113113408664401, 1222157560539217476, + 2099068961815044779, 12562181036171628906, 16101890713848274666, 6017764396716978009, 13064414845499489050, 8419967306079989759, 18212218073753486044, 1008986649080828268, + 14883940931343463293, 12319376897638542821, 12367185247284838739, 5861252096374912155, 10018798299303262817, 6422772579819453330, 2070123940915480886, 12141302052520620302, + 7347211048650261526, 4324486111460763452, 1238262417801832007, 7620393213816116173, 13629115925647807355, 17975185632155863015, 6751253893269214002, 3530207280414557051, + 2294668553308381923, 17165287249067859297, 9897724011823072967, 17409851874231284314, 13888575318617508639, 12092766090379658603, 8412268183255186961, 8046572777745318483, + 4493498909328627892, 14652253245762410953, 5345262207345951514, 3970988687199074488, 2208768899312608620, 1510839623981662369, 642580537527653605, 14940785106713466054, + 12480576687390709541, 11249304546887636239, 6075047530003410694, 6121669232248820705, 10309256543424460776, 101796817907499847, 2110451750984093184, 10778335615512351243, + 2885395260584376454, 612553588199732392, 17978615338185945515, 10414937982597482385, 6078565000469652304, 11381998957121196965, 1536418226678270090, 15114446343888525079, + 13178439025428734594, 16388038968589028071, 16165750006742628176, 17903639397633243161, 9560319088110737392, 7888974492854359310, 16116323630343158496, 10177829649622711030, + 12866004572891901059, 10190228418101288877, 4717913135317392922, 13460871068228811018, 4756401774767581561, 7711771325649205249, 13695132008344052711, 13361851345229950778, + 938191787235564236, 14328703178349042628, 10217257468952800498, 10415924210674864240, 7171739159943819214, 6502538915112206091, 3300616451202954689, 9576887970605726107, + 17259872866446195810, 3694244894150718459, 3214322135693408389, 15571503654130046642, 2332159362399220208, 14087696453363417437, 14318693886833071484, 6131092646618026480, + 2378363646789710539, 494954399989334038, 6915496914984330558, 757197055392642378, 9097171378505823650, 12104288338329241488, 1905673690814481722, 13011078677095066032, + 8123217305309052526, 2527408826476194625, 10072980201182378784, 15489255866670747761, 12978131276673936002, 8312787524887306087, 13561211528259491689, 6311660759462081662, + 16247831307849916845, 8654394682758927217, 1180998443932568506, 3847327552938166714, 17658215545137701161, 11975413369861829206, 10679985684889599173, 14928266362876119222, + 7605162785889302718, 5718899840342120733, 6057249397801266401, 9486440247354542717, 10618370743126190918, 16153494357430969850, 16785070420314699787, 11277000340020413902, + 12712274459771886808, 15748114764509451764, 1994630377849062253, 564390855806287868, 135493276425567450, 4305883520257541088, 4842008929542073044, 7035106970720249617, + }, + { + 5757832545805155636, 17609080533053427627, 13855662030602089892, 9622498683452213297, 12281586442064581946, 610529441714948581, 14740357477019436626, 16983190111725558863, + 8470173855499872166, 15915210069852758660, 12368087246231545517, 3867174158581293223, 9082358201271846042, 16663463402757176964, 13740908859955866819, 7748969412274962298, + 13375424826931892789, 8508645806391261552, 18359272328758476903, 16433208398005282080, 13071423254987294580, 7999383023651164492, 14514701556577587750, 4848295889377673720, + 1020519568493754982, 10467781020270669620, 17607771250627508499, 6620300538436640218, 3858527175523168333, 13798129597334232823, 12495322651937391008, 3926713306087152023, + 5116038770086590715, 9943789276328255827, 13715439407309914230, 4887040860130243503, 18288477612078228131, 7640050573721350378, 14537362862524718973, 1658575506924200900, + 18400486168653423966, 18026904540891591040, 2037921821724043966, 18010956304511658647, 3751340308708032971, 16275459031633957091, 17177866831427164840, 1635431811339422016, + 3897330996014812355, 14347736534650088376, 16862404119462964612, 12216005411754788835, 11561909516001453735, 6261639657930189859, 9101978764314050064, 12280333151331067982, + 910276569977357717, 2872810615152156462, 1942106118995935911, 8734004121981822024, 13862118436432879698, 1912639548162720505, 13060137938875924732, 10642216911059510120, + 5132232031613377471, 3053931945527415993, 2695169719602504430, 11855046366025891084, 16462491222215366712, 16664416596202206835, 3077124688577987843, 7109495326459366311, + 3858762384693274897, 7520194928987242278, 4496744297661574884, 16159343214247089321, 6441167128044578145, 3604951495694157848, 3072075325567814428, 1964798869371174506, + 13689578474000942304, 8998724267038772595, 3350174507425430811, 15015413657749135511, 4848907595494161497, 7935644131326131098, 385849363817229511, 10087353746314516691, + 6067717601858189468, 10438404859927821308, 9991403870358837471, 17728358586134467771, 13476949968946830198, 7311235997042381570, 4429835371823736972, 17463216455983091974, + 3446799583712077997, 6763499387263152328, 9231082163128267527, 7733182914440272884, 17225092062157610409, 8163842076250628108, 14230171836718858439, 8195740716303697476, + 57759226194841354, 14962480748390190557, 2047254208877381876, 2830450574091058648, 14905486147404440754, 15792397930637469157, 16383409053580142957, 8686506861607761226, + 11120178572139812895, 11534611317577597022, 10437856602660752754, 13925966850017814278, 16776862023867799947, 17362554889424346260, 3408825299914455645, 2606150045870067742, + 1119490156854665483, 16772836556735128526, 8607715508817325509, 9931017263385440911, 8799481055779587022, 11740562709785257943, 1956849872282864970, 595288629437737005, + 2281206023740505682, 9926719762453358166, 4061056930877891291, 15576657447058286418, 2614863633636977404, 2206334532799385250, 3474210873232711865, 8477734925846980028, + 3340305349427486363, 5188523629566097463, 6160790887356413747, 9863988255192204305, 14066826366866912046, 11932779567129411871, 12863116515340321220, 15222969978942513045, + 12758642615291604404, 3209096496454847183, 11182564090025111575, 1931382908005123647, 15151007707308352245, 5954868822601995640, 15742433078711209582, 3347972315985628205, + 16490337555999239547, 8990885971520264447, 10360258506616249745, 6630482203535351500, 16999397485942558889, 6788531264412870316, 7229988042452941955, 9856917486277085502, + 10734804718395003162, 14385908274213668346, 6022876926209575383, 371182857232839872, 7412466195447558077, 7961511694540082231, 8030758761844457080, 8046696009323575767, + 6399666206029163609, 17663811097734928631, 11470778017516778751, 17702646621253134508, 14876192013866833082, 12935280981291312476, 1467399042175927183, 8848908916563618579, + 14359906986235888744, 4587839368531771442, 10497105860390751463, 14244616431904836676, 14906421794748569105, 7955760173743833219, 17152550002849021490, 138081467951201370, + 2349932829525749283, 14749355610935637731, 14751838563606808702, 18058355029195133983, 8461199524627795693, 4219910612621001507, 12776964042319070094, 15905069451612157329, + 1355498131832429384, 15975585519420207244, 15757549940022310945, 11357394570768845273, 8197697208897202922, 1901621009956576265, 4290101364365692172, 11947148614241269523, + 5840762872471677309, 7514977007446174348, 1527060545570586419, 16609099121469101859, 9320342325870097548, 13965331598495025936, 9683433385601741715, 8845290689278472178, + 14119395813630029665, 8634138112335652518, 4658233985292819043, 9622846971166516113, 996353694479629398, 7404001202059682426, 18145845493517798921, 6449664057746980028, + 16521775738375440178, 14142357232938693849, 10990147202113110230, 9959066954415780230, 13034621383041722634, 5025797339352139456, 10322111864643366459, 2614961497496501105, + 12557910439954509999, 12230084394391362713, 8427020226737465235, 12518021396913122088, 7134271418642259845, 3905501389650646356, 15707807001177039585, 2909191175572717037, + 769225015796913609, 8753059944613840368, 1611869096690868003, 11449828005116201197, 11517191665323762104, 2697717476879599241, 11188965056705006770, 6249359019890699508, + 15594613737645580981, 3037156291483237329, 5604071908229825169, 1604475019228431078, 7766918222574600204, 9339455406279970318, 16266564745812517195, 4799424886612563329, + 11601570184515356415, 11247678357869162156, 8415095559389686315, 9625816053586466047, 11807876143163335372, 15690209134241397733, 8684637224468015605, 15974968144193406020, + }, + { + 11275984449259340674, 14922638629881602958, 17186426309348732477, 2094500549052461127, 1245672419927595636, 7529921141299797945, 3181089597449057707, 7749529014968942143, + 12842581296013847382, 7845624487558348664, 8747439372999364825, 849305823897878133, 2217292264321907974, 8173534404179332054, 3588643190593022889, 12047811416592660080, + 6959527445237219799, 17170778245769606301, 807762173031474321, 9151445233487017286, 15103411489939446333, 7976669669591851659, 14824323986579638641, 1535817133122800221, + 2365455792963674834, 2249234228455309648, 5237136544555745182, 8814246419234451463, 13017813702607013347, 2241193992640629733, 17982226236989862510, 9800528153239873634, + 14106286229675768856, 13210380707737857536, 8049798856134302097, 9734560649539497957, 1623205786926824588, 14287958304696241706, 1800854015662052826, 1212925137572581937, + 3026947385483276729, 13169758424754896088, 6834174387382969128, 7206544572805916922, 6934064062491731757, 10620406409375153308, 5194048681860016706, 1469688754160716493, + 12993558037376222988, 4669474265806332952, 4832324179281001408, 4413085485243863075, 5405837906169635761, 10091776239975644239, 5290719555562061144, 4213669820858776415, + 17271890190678399664, 284117971978206043, 14999643475704678808, 6264699496666119083, 8859934981351804429, 8300880062060532031, 3667839168820458685, 17133003164910522197, + 2997449698566957466, 7884833253198684528, 12498695470674374226, 3115564300965505022, 13376506794876055601, 17895331353362057251, 16990581103090492269, 4674862843410794096, + 5006430925084708381, 16053115139414023422, 7049813739763202517, 6676629839394309180, 2410666182773729148, 8945309185393628712, 17674821778351929167, 2683163960153153804, + 14505459891908974624, 1849503921080779239, 13990490450160111440, 5181610498614712941, 8653117877167770474, 8814499350344722617, 5343755460620184433, 243401361005198353, + 17791633957402883820, 5938849497629314459, 8356801465373786047, 3163889445599730677, 9723709910898285412, 2841967670768995554, 10896757438566636700, 7434996874241771203, + 7372440365321345784, 2862880403174214663, 8420116322934238724, 2818552325655576635, 111342786192022359, 74705672003306783, 6591511741514218962, 13124391319573921957, + 9931074113040228488, 15362193958291437280, 6613002366394890474, 5258448208225327677, 5126245224005997831, 8755434042915330962, 4405830479557957055, 13343591337768921462, + 9242810916685205316, 2838356272544913798, 10099476622515682546, 15551100165305852662, 737838832976059770, 11188026425234857295, 10166119013055947704, 8628233674684143419, + 14086272070125896854, 12009239107306499026, 6592816798466831203, 11371087141421707743, 16277593907837607793, 16449564916599232060, 17471042072158213549, 11953382410698485455, + 823047236880870350, 7830286704456953572, 6464058012664717582, 15521380082330968365, 10182202815901986450, 18143527955004661429, 3207725716803325445, 3193887560605396493, + 15569872930692175382, 5346306686087630019, 6632365629111827330, 15865883909120927399, 7200040798106687333, 5723169387900917854, 15027071603483375844, 11018037359110138454, + 741009114382240162, 13879961246490269823, 4790141947869766711, 4479737908710468090, 4979904969974036721, 634413885118778288, 101727670723732801, 3160663692354720401, + 14613304240735929191, 7658770973133328064, 3028731168325633068, 1486737152001467114, 16715835021406106944, 15214200823642287507, 18441898204110447697, 5669963154424393607, + 4313074171267006471, 16217697149498819074, 2027993870023154350, 18018610229517524263, 117205923522590215, 1784380715025232199, 307956084870608716, 4140912860495129528, + 3938313265660748839, 13018885466029447230, 12461354215832959401, 14495299413345669177, 16234805331742830462, 1578184208291171741, 17168468892394781152, 12575003872292801090, + 10424668870965277693, 8952352824982702795, 18017430252932614600, 14101949308713937413, 16342352613992153502, 6862842966642668923, 7238655696295295374, 11216037980129705353, + 8381651800836461905, 275661552864412688, 5548629401959193001, 7174991431295718071, 7441251258233899268, 14052832476485122412, 301250917807487282, 17797202428295526090, + 5173263645506172639, 7621852612520351243, 4670271322283433581, 8663786927624336026, 14433502423455668413, 6926265712671351075, 9776903322968672826, 542207238644018218, + 9588056942118198784, 14024040464098859998, 17712446698584877455, 17945455593410056285, 18104078100936060946, 9565731894604896153, 13213845893767817606, 16043575675737450101, + 3436179376183792489, 8124476612946977721, 2169106928994773725, 8589833084708985039, 15137137534993478994, 12789920909097626916, 6767184505234754407, 8369097443031908183, + 16448089571044203401, 1396460397790470601, 9796571033221459545, 8162511506983092708, 13893406727199803081, 16188892369453405032, 16023105002157964343, 7061289566170423383, + 10448117565485426152, 8145533940921335838, 1579413779055052019, 14761309857236492983, 9815666466018583851, 15131106965446764630, 16986514923298225288, 3751380281663155649, + 2224143503200162255, 9410177163066991107, 7157489123570995878, 13420515130397093319, 2675717750075873421, 6702938999067232257, 394050047437199204, 11922372120263518221, + 9930837889018815244, 11397955329795684905, 6931891256005909739, 516538601500853702, 923444815286512108, 16665363217941733257, 1377231042965759902, 8439923996651310778, + 8743817608749172620, 7804846024944300667, 507107926259802795, 5258061329638283805, 15071070675288472598, 1848743106176521296, 16295570828486620412, 7409462376590083349, + }, + { + 10223936123327786454, 2321887803300626936, 13607747528117965743, 10456421630388400123, 3266519591187534953, 1053691207967834494, 7151443045753788549, 18124688636664828399, + 6946488664257064464, 9775328903143754150, 58700362449753229, 7901817271072273406, 5074738678159003249, 18397239731906005785, 15911102965988125888, 9277654580204145348, + 1874700306906525099, 7337351570334852732, 7954195906114335343, 17230226427261850070, 5181329498860909261, 107167242193237170, 4364856176182710332, 14611171841443342914, + 10990327814895720476, 16588412771027628390, 2850177278998422188, 11569813740328484871, 3922148781422941186, 3581659216490446242, 3646872304052351376, 10887870617200051198, + 8175121141368087217, 15079393830876652065, 16766987879267543828, 10582796406546815217, 16832256009371376870, 10042650470778064892, 17867163453935683780, 7123418345572641116, + 1782651072016504775, 11033882508408412333, 11105300284232190625, 3276372405089292929, 6399472468041061588, 15319690780388315076, 4928530863063375966, 11596222198340277418, + 5452424185619067445, 12050433097586021281, 15018766900844679217, 273234254926088220, 15426383635547379531, 5213762666043737626, 2829185842069118470, 3230799283770935127, + 280030342772428106, 17354882606189694746, 17455445295460080284, 18076709382926018941, 9895982528034548913, 13681172423928175330, 1656433131309057012, 11935757350437721114, + 14437472586336929440, 17387041914242263390, 14861577074379746687, 5146556788377906297, 13036814755814090195, 15108836859245573802, 1667563994642521213, 14722845469958372258, + 7781061995240980266, 2066078418484154391, 4089376589847114892, 2434843609506038666, 18376509832460312721, 7187709121160627756, 2455436656049651823, 14419116837518875372, + 1270185079976403265, 9214436628411717184, 15450450827683432913, 2880014804806096082, 15448799931519826757, 10080240282127928735, 10673974088219619287, 12998944469117087518, + 18028691745165748687, 8931519595829275195, 18379893031942930865, 12120980098075498008, 9596371470855895261, 4133427878071274570, 13159312399982591699, 1639865074052258019, + 1661696187746428348, 2656198437014978712, 13769477291975851694, 12512848714492869444, 5980926616932344693, 15821983893144953005, 5816015630031200526, 15887565799959254415, + 16463929919291729278, 14920112063826664828, 10056471508435050704, 10696267144984026763, 12049530292963090991, 11926086636123189182, 9464890378472966538, 9719194510330239601, + 18110249193861022779, 5612784685592189906, 11360454032996393150, 6795401682138043705, 1961398978248902107, 8999847457729547905, 8941741619641401180, 6086938661427918241, + 10153847769616409178, 16591913677701651064, 11369151065084080884, 9493662847124813178, 14299126668179023903, 2451525064998641745, 16055696673728703463, 7600736037142850105, + 3331094657189179723, 8579232659787725167, 11007434086335446933, 7488529659250917009, 17217317841029490639, 7202184784979805220, 10955913831459448069, 9000508720500651545, + 12966352809478736412, 9643078159289928329, 1577471789984999485, 3065864601417367655, 13683627106599504109, 12782093364215596525, 12883456287502344466, 384144415368165580, + 2010495664660209855, 15520744321638216967, 5385447087428594566, 12897496516555487055, 7343279016502952747, 11323820480524965410, 3414484402519450292, 2497721392671865580, + 16065061175628739123, 13981641072236579791, 6942197664821630380, 1667302033233547783, 11254994815452647404, 5265777633437443003, 1242523090981771320, 11333562630675377559, + 13967113064180443992, 10679621597408504672, 16223869620849920309, 8813286726524283182, 2000697484240530777, 5417120625530117302, 12109041278382745291, 13257693171778388584, + 11737174095432286870, 13459661128718998448, 4655386724404378836, 3119616752887818891, 13324285182058113375, 1078137740985006431, 1610820303976884986, 10433300853468291587, + 13552049979590080822, 4379357932546858489, 7594644709024650108, 7268811721525297059, 6728671136192921869, 8183021491392757516, 6569378188404015319, 6481294988812800823, + 6071501855022377789, 3805172128285889052, 6802689634429908933, 11713310861536728752, 18291420299754708339, 7582277238191809023, 6183429490206797252, 10452668103640934631, + 16083971675285095468, 2965035896159234764, 9379493912871845724, 13109394112987303523, 231416620515766991, 630445729708227114, 10015412267172773636, 18104521419340860951, + 13169770634232644390, 12462964563528956096, 2689434882719314440, 5936289129999384022, 17773436345927091892, 2631892834965929605, 8167719122803587721, 2458223071457452931, + 10744932251818515465, 13367480890778627284, 15909410072235544918, 9252559547875570290, 16355895225285344183, 5115003811789024567, 7369371640924666845, 4586532908333332092, + 15999516281080615520, 10972478396135936147, 9002100275598932738, 9043399249857967875, 4975188939801806064, 14240375126510021504, 4497218436093285729, 899858725260616391, + 4788026362409273347, 8940774760122210910, 66616358927988247, 13054723206705508289, 6256911511259454580, 589353691478007084, 17831732841616807303, 10847300659030294141, + 3016120727980669767, 340560476433708073, 10516500208515875331, 14933811541787518485, 9941997565508314935, 9752941942651093949, 1928238223054143159, 16147782066840428568, + 8953947187833770878, 6627103431982157573, 1279114735725952920, 5378128106441279737, 15447712974588571571, 10552843735673449739, 14956126644414569830, 1994513099978508850, + 3339871688614476269, 2937156932445032796, 2071344655111136329, 509603454456841298, 10929109734329673813, 4531629375826317764, 1802431569220697099, 7971315018970882891, + }, + { + 4307546666223047416, 13914498777427309061, 6812156124789414732, 1680174913762530491, 6756325174405757110, 2535144759174364990, 11263393915003278429, 14767595249676286403, + 6981289090623415465, 8930069945493884157, 8223216504978132408, 796477795300774057, 3120155459209743472, 14825603392456550470, 3711879425019804830, 11041054473536223927, + 14135544350792474553, 6171419888118563156, 12495035851387242130, 2843310747449412555, 5668766087526340552, 10117858698838396246, 5181027414039980750, 13247490124270426, + 10847249691051757241, 13332329214721571156, 12457628412284474075, 17044657510482764070, 5218221397478351943, 6922630493693541156, 6207927102810766143, 5644846665334649748, + 3169200533952511826, 13123046990387029463, 10303462306703730135, 3315008874027436174, 12427067008037332041, 13190195608614554888, 11930408619792340463, 12881268563913740396, + 6700154625941523096, 796110091507466427, 5388163944686450548, 3113104467109529928, 12930558649635882086, 7536049463980825715, 11851825635055645132, 2654888532632283214, + 17530163750522835336, 9722612350417778827, 13244522480616169491, 13740964907388846002, 793235549667461791, 1998252773625399730, 9697911491069876538, 3365596945186794622, + 6506371904134856034, 9541373683805144018, 3149037850125132851, 7111810601994573897, 16732445693192247884, 4994069681898274622, 7223719243730104348, 5649174084086150712, + 4640203560336739679, 9900565149463137003, 1093715346388527458, 17169722430093991108, 14911871124664548213, 8091096017016862097, 2911569128494944136, 10192934055727569503, + 13251895658744991883, 18083873142202267221, 8241707078409323349, 5240943892375002838, 7329419846032881810, 17784005510850539551, 14034072243705748841, 10459194866755836024, + 16396304393792022741, 510358226971662693, 2002127643935690257, 14681425695950046262, 481902649451190280, 1717807040845239061, 3358903321435525144, 12361252150277163759, + 16562962997045986629, 1977585352264948582, 15588655103333244279, 253344970359156714, 12939363813291366775, 12548224526376199974, 14450582788883748364, 5869541533939881460, + 15346378007864735078, 9904337403373774864, 17933855382993937953, 9391248304932723816, 2250334275383247202, 5978804056136420670, 1528238852592364099, 6491566547950141733, + 8439860020828526478, 8674532462170555517, 13889716766953024111, 1166696901054897271, 3599113965286446905, 3276801695553601157, 6631284861504552600, 757022358659145685, + 1117291222568805017, 7148845117809308441, 4044258438241699262, 16593433123496068718, 13992202310165134218, 2998204381658279116, 11137382784909083266, 11972581616612094469, + 13970586842647892965, 3680317572634289692, 3416494470839852757, 8341497967750607131, 5522860734580749818, 6847292760525096386, 9317394708872196559, 8522252330730808934, + 7951036477225560362, 3718789111033607646, 11667291286820266731, 6927579620295878614, 6796746225018555970, 2070061401518338268, 2452626412419851405, 6130352643925327785, + 128317967134069640, 18241952544586374251, 10689311587315723515, 16537482248073764435, 15914436258832414511, 15518344078557945167, 15883120902045970449, 16251109112716994957, + 11957637677355945602, 8965882791601648704, 9390723380463051523, 15025038333096274711, 14983844148312808973, 14488574793452236487, 15795526425513195718, 11651978879566144360, + 6838341670149165895, 12326189699069923388, 9258908232339348843, 17297038041466207989, 5242182985453021593, 9648294165629935142, 9715128265517308395, 2662662536493743894, + 11289660454922592938, 470300170724369955, 4571871646010841181, 8724229358245178735, 10173959190953118810, 3611286966550223594, 10810806064515103403, 13571898391208639897, + 6782514579206442308, 893150666351200058, 2099535232722538223, 300696716419619813, 4778737709473194628, 16786610674618434170, 1751624209281870237, 1677055321500839173, + 8950755642341912951, 1974922263791844623, 5333377426024439800, 13909803085973342843, 7639604505882407937, 16195074617613125552, 8954461446680048430, 6823359994465290754, + 6790869670806738567, 4499989093713728199, 17496748050437205626, 7194829324969293638, 18432532588985091708, 12041300075343806904, 7788543067151959941, 13703334460383638224, + 15088053026772564466, 18172984562199594382, 3119317310593433742, 13835498717175822656, 10015747176747842576, 11008571041665092033, 9377877781626879674, 10465443099481589185, + 8933481722931715231, 10811948483433850165, 16314247813274714890, 503147444786527544, 2533443680646505069, 7617720894972668760, 12477410920355308950, 422423516920457876, + 1501843276089632258, 18180777013307233967, 2535426997299341256, 5318958493284100856, 16758265544916918856, 8118598628492446123, 2511013049335776232, 11181447982017705826, + 5996381448168274884, 8108757135223610234, 8067369725584584297, 7184925262427750366, 8199341143188441284, 13031376443169557016, 16036606349050125404, 11958720833222295864, + 15336831835795822898, 6806921200736832713, 5959923980569572002, 16835674225684329982, 9985579070716031367, 6517360043741716503, 16609518082836868591, 15878184747124924573, + 4786224758360153905, 10283234398763800487, 13695837902615591472, 7260571034197533442, 9225062953237806971, 5969706575516748564, 6537573986766117532, 15754484267739133126, + 5004791824134844360, 4971286291135250424, 1811371968353107289, 15772458387007519716, 17381493577383518445, 14326903440006940586, 14237922492359728234, 6234116464684325431, + 9293668142017263584, 17134656749295164870, 5879480323258506465, 4788695233340705697, 17809277710857366810, 15157733645094688870, 14143869691462709080, 3162286338158090229, + }, + { + 4471613312912718060, 13601785177495103328, 8083849806888905297, 9053545412554844461, 1876605639999952155, 6124537911475118673, 16877891074567085688, 16541720065079132344, + 18138305348849897995, 11498878557125400853, 14125346336359365201, 11991638807788804369, 13935355764550912568, 16209147067155729660, 11086190285777019292, 16727288863943596410, + 8873152377611229668, 6260821826956744083, 11489383533808918262, 6585112195310961861, 7365821041919648819, 1936165695028211587, 16164747634991415711, 17957320776652490392, + 13065030057172289846, 7278765836407486850, 383827150208081081, 7832055893191054601, 5249323286889945617, 1631661912887095912, 4431088469837785451, 2866263172993336891, + 6140213328062333551, 16704025329777067037, 5839832043209342792, 9196354634862869885, 2735762290983671190, 5323501742548818139, 3199127466610501482, 6719610946615763192, + 4032564124345275293, 240208626666701335, 10264845378648897042, 15608289126091352415, 17866864241918154829, 6207477318890336372, 491708931325462670, 7002400618323099260, + 11507747783030541234, 13683043390668171754, 9924966309328785763, 5549516466627385909, 3724001483041449858, 2408778220985427590, 10510707601023430105, 12862520912519186496, + 5012372868660694231, 12033652755433827667, 5960732801180177919, 6089487525155575261, 18400192045204062277, 12754175136438960528, 6170965736016609163, 10141374482047067946, + 11781193922347227447, 16937876011211881637, 2982972111293427964, 1728244726890919596, 3327997232304084768, 4754833121145407334, 5871027825507908591, 15772493911709624273, + 5862944033912881884, 11132730978666088350, 12167180155548291888, 16449838286695349787, 14399676610730016345, 17071083123672650337, 13727728787831175379, 7507765123422748291, + 4883057314704644529, 6606742732149784343, 16070555141087563722, 8408294891669305261, 4298316003054547788, 1573237855902568238, 5357176885445018289, 5855732582172939202, + 11721126538980357625, 7216004194033429913, 12765889884935948315, 6003399149613653734, 4571046290325663920, 15023470461830485075, 11463513436288928362, 16135217522406374542, + 14300855104129153291, 11491527690078786162, 5674183453812271017, 5044682546652747711, 9153978680942338831, 400454762074409409, 12351470849648616331, 10559229320903248832, + 11839166519633311143, 16489041153719856002, 4820713204385149226, 13768001962143023630, 13107713406478328396, 15471245828032402460, 6733652296473831544, 7665657127090105428, + 6114372925011600760, 13061069979571997963, 12156991017966837826, 12403009591138383583, 5761958709898299258, 1907771304051897263, 3007439379929412593, 18410854883912163962, + 14408045416865494124, 2442199381796557002, 10475326303775862953, 13637445125954159957, 3778313603630758744, 9247460369874272772, 17572237597883145087, 11338350096360776602, + 16486104352829691584, 11856560607954368882, 7574789609701925021, 12240083183242127118, 9872957337376856275, 11508929285199799229, 12084460294902152451, 5537978390111837838, + 17987471707896681874, 13038244305326284081, 6130570860032709721, 13697749322780057427, 15250226813583295859, 11214437899623632196, 11227424166765094355, 16073863048822462466, + 12399110995748365941, 8259021120978314016, 13249466772279340115, 11201772702582865107, 6680428295197296613, 14825065014187212998, 11638499193934854444, 13944483483619391536, + 12792956896156056673, 17521293339475028823, 5738513258925006248, 7070317930523546296, 11175557000762820214, 15356683721815441509, 3038847573301969409, 3712495274059632476, + 9703339902904468931, 6903532388259237787, 6598718994389707957, 3524767540333384210, 17230409287786477986, 398508689507908728, 12956323124513250470, 3050411724956364887, + 9936181795041159997, 16502578966693139346, 12331385558134766329, 16368402633574222539, 17549179704234998175, 16732353056786161257, 7018642409136068141, 13907639522324102590, + 3202436334590923936, 10521323531132496064, 17087322194145514933, 2557934785422493682, 1054672647095378624, 13197226692868722325, 1089249862965154915, 6479925079582112772, + 3880905381896902231, 16702686708922296685, 9815623322445801304, 3275100382267252573, 6882533095211022198, 11000715667767797665, 17615808190378608947, 7418883369171949489, + 15109802007060416273, 6172716471862133951, 10675428021956965140, 5719399515177959211, 13414568332401128475, 15437234656470291881, 15174397947571718085, 15093134682110367825, + 12767354263003560893, 9423701226679222965, 15980976879563466685, 16370172902785037004, 8843543841582241065, 16817827501960591898, 1524531339915785994, 11624580276885598157, + 17147068462804570503, 413038056092618151, 5178874804057490245, 6267545065511948977, 17573054445714024932, 7120476833739422223, 5707115123830922617, 10971108972695387841, + 12546478152711337402, 3213958910433616233, 1066524299473173792, 6276669942370566610, 14816818963020520773, 7372806616674468946, 12220278123497641030, 4953625488417522128, + 9443607421568920607, 2583030461169574647, 9900905053299561307, 15892418329702922907, 1184158607153919924, 17842123060489837980, 2681791639846598155, 14394984710894548047, + 17363678829105605076, 3907856148144141388, 7535915338133892356, 4354053943074081189, 9644954727645503986, 6816908226661921388, 15867806610099035654, 13874346146744695721, + 2654416582410062512, 9232324386948815478, 13864516581612906345, 17132638924861000235, 16875312639179645137, 11536057026563830119, 1090137303802556590, 15667188983774010898, + 4336697789732072031, 16054848662858822197, 17934449813415035557, 14518380622432694666, 14100582434152190048, 6262866632984449325, 18069160441815400774, 9798342103009260692, + }, + { + 687104890149081183, 1938816743979859301, 11342071981175913904, 4270322127259097184, 4964776270155503160, 17849333582861534767, 15814479527332819692, 8083943565773123408, + 3986890035154628803, 15316660330065019741, 11560940574529263780, 12576851520091035878, 10883944418224886092, 9908329441525486205, 11238684990962507809, 12900626758810151662, + 4077800412543228484, 7173833470188867493, 4604439809988262876, 8090706047559948234, 6117166546062912279, 15748537214854486946, 16719594636199001564, 563850925691991999, + 7109145612337154341, 10502845970727626855, 6527587047878193251, 7049690136888681718, 16750703006415156202, 2559311261501721445, 1222802194566919230, 18019462938525560766, + 322982839910423931, 2590270731903609206, 14012397059804449007, 4254569016772908483, 8508420263334539908, 9175848619353159735, 9777676085150569067, 51565612432741329, + 10233009747926770582, 4858065366607044068, 17837971428933010861, 10016544790726166742, 15260359301638740999, 5101999662344938158, 8809855615759524306, 15369468763003019252, + 4549989329927399868, 4866130696079291940, 2784467031729859937, 12617898982021887868, 2721301974598150044, 1014232218549205942, 5446756626431953863, 7315134179045561903, + 2592184418896595488, 1723751460114310463, 11198512454461769811, 6203707848404803677, 2601731234271436477, 18186700975610533226, 4757569424831899615, 13359873383138312209, + 7339520839328992093, 3349084091338116256, 16532710170417471614, 4425958052714174548, 16833748535746803845, 12665172019028452441, 11274971974705134171, 6504206221872290467, + 17921256304121537300, 16573867650874642543, 18439217559900658467, 2917797231317530012, 2415475159165597656, 2027542924210178369, 13542535558170959524, 9428931592662127870, + 17821420552135083528, 332847653840014838, 11832506312426064436, 8314663852639826188, 5744960486691350299, 8069724388577179929, 7949740770152910898, 7431049632429535950, + 13904640252203718708, 10747313134117021792, 14667070697514384141, 2600977347774743546, 15498986940124021079, 14740645313274577011, 17403811028932224808, 8060102076475954685, + 3517334016249952489, 10826317205305313746, 9664766330892822745, 4145357045596983962, 123566849370572650, 6452080295201963409, 15558941970553263818, 1191650177320171029, + 13303794914626036653, 12135860919529132656, 3620217653879289461, 5443663950311568399, 9020744500355505374, 11953955628401776228, 2101814526784564259, 18218598416910848525, + 306945432061418036, 3150552227215797902, 12928374347433953916, 13299101042862573370, 13702883318367407795, 4879985767563062391, 17591048490944890593, 5088664549487213106, + 12990649636107730851, 13002224935892458030, 4380799638612122791, 7935443787987894924, 10438069978940053126, 302419699431148366, 551508078777729872, 366155636877501719, + 1657628676376133571, 11398060401420699070, 15376723048512638551, 9875623386041366116, 9978954704196888739, 13768323245406799962, 3568095027938899541, 11120740210192996096, + 15561317952331530901, 10479759083279078649, 16536004935523752634, 2928518661531554130, 736056663469575928, 6131440330717529370, 11275149343392851570, 9601030074480228347, + 2397968519718544666, 7793046606567840651, 8971792946996316712, 16581860514259510747, 9067804351225143661, 12322425857061932421, 10680196669251962457, 7226521395530060461, + 14734735764746786753, 1378251478826083755, 13509550209468602124, 14458158239096821346, 5681313138148713219, 9054039627425609375, 4235536482830620712, 1502753755874778370, + 10053374816829223121, 5956370573575798562, 6842782625116195714, 6646143553705917790, 10487617951080656190, 3930886288654953669, 13141858447548326172, 6966039733711006320, + 3565931266726110263, 10142260659118036168, 18315406451571961983, 16857333990691080595, 6889519058362658033, 11812045051361479600, 12503117299646153207, 7223531498406875484, + 15243128568488310595, 13798032762330794140, 4456440673105474920, 17896260893739107970, 5519537045179649847, 11908888770632658821, 5444504459295913107, 5588728973482930155, + 8914021876030553161, 9071747156187788379, 14974736924255494885, 17070198435868341999, 3643991391224035758, 260637732328275649, 17609644917816078225, 2302996326941944665, + 1293835161492069734, 5795029109259991590, 6978986253519330084, 10360755458408067486, 9467742127861782141, 9197981630801498774, 6297600026339958279, 1375635441408481019, + 16875086338187280639, 18188722331528885957, 2047282716697647836, 17808297209051779725, 4756860180475663362, 16103863616340614471, 4416311024167936572, 6340715229216403079, + 14261984008515151673, 8778722476581699445, 1624620854396291363, 8490568310899028272, 6147263592092458803, 3717414274397202281, 3449154725620836174, 13526832985450537957, + 5888744936142942064, 17277140802638358763, 10290028650289820825, 1940657436863195045, 10796401239257150661, 7788083050548605852, 13474393003015663489, 8961936186303685357, + 81364364291228199, 11636155122637141142, 927710893705810893, 1403208391464987879, 4332234662194589819, 7913319387647351094, 2589089673930123808, 5387282875974124558, + 10611669207938469024, 4491327257859270050, 14129391883837344111, 13924810848449766461, 8792187899775727862, 15048142623570073200, 3933861866144269656, 1162055633060412126, + 6883724061714130987, 10416279294253729103, 12247033224345499651, 10291073256885105234, 4480789666471481188, 6022169887991948086, 3778647272347441051, 9527380466585130391, + 16407225233842256953, 13423683834633513951, 17454464203550700633, 6033758555290610449, 5063673994339442907, 12250392784929419939, 5954485814444410119, 10099095370725442279, + }, + { + 7669790431656261769, 2776517632462593286, 11694025667665633506, 9533794089008895277, 2895611631120558023, 11551410655448788956, 10026541900772270925, 6243136875017000843, + 9434484992529186384, 16435748047660609525, 16190660694150989986, 7083965852434071085, 4216306437741910756, 2698742177539497614, 5199793642504009017, 17298424769819019160, + 4041169394784902550, 5699517344009382913, 5306272267462320559, 15846674482556330025, 2606351264228884283, 4162585980422107281, 3715151019132039005, 6607223447043258693, + 8168579295855409503, 16727569921530031841, 6182114460261837773, 8940603165471931374, 6081572078077526926, 5890840443923124563, 11215305828294759727, 2875117534361804712, + 9045974983664041829, 905036705033699463, 6962033946652121779, 3027264198782618401, 13786415307358010100, 3643342525745067473, 13641958783381681886, 15675065537779359584, + 7507377696839752642, 1061259379811757443, 10276590160392917813, 6889137095037822679, 16373913505782725550, 12287733095803524526, 5695917172259210496, 6360958736925918808, + 7459854586357006968, 702429387211615855, 8231296036461604410, 628323703857882004, 1059802628602873385, 12517208225099517507, 2368172548334856593, 4792344750094708709, + 18352334786472886037, 7096021570596476676, 17045407505128867173, 2467670847537319400, 2225663888244226889, 1876713214939672742, 5329943993157142620, 12168650975912182188, + 6639850268372381409, 2284514769224558945, 15390110317831975716, 13933785559694229008, 12787641603764341997, 793886210532292741, 3222136169196008839, 11104892506868626444, + 12660547967989039787, 2109392063597767300, 9889743271997754037, 11803327596624324036, 6940409327849314286, 1466399127363116843, 2572333022681966275, 4216097356402537802, + 16858757460581672909, 5838407119753001493, 4453405435911954669, 2828665451507432751, 13657966632733241760, 6875986784381874300, 2390233934255482553, 17386653779125555159, + 2976756344404126744, 17032556609402836559, 16348907464011574182, 2196781021202618892, 8270822867494340805, 4738372358350764889, 6088256422707334932, 17121369334507507505, + 2081729301541563384, 5577186154173396778, 1865152567701500436, 1422284589642218069, 2489023909725140903, 276494395149046869, 17420927169263487236, 8292343688801608074, + 7819174654675104600, 12778055482430336726, 14615848543490171611, 17498415175263742825, 4785899184222234034, 5227136636239697699, 1570704808469050246, 2858953380860123257, + 4323577007857413306, 10524228743339400397, 5418808897687027557, 5939367271366264075, 3569359126353670574, 12961495213964770607, 8906990808988099905, 261084295374207271, + 13937553904380032591, 9165760362893872288, 14159606902675650669, 7794101517494576908, 11994596892880464164, 16211278212275417034, 1568324133241165712, 6579463633356173526, + 3784436423124943604, 14504130598322564217, 13343318845201913758, 2617267381187565844, 10063945174501910869, 8584806992850354016, 17494557973113338328, 16987450461117846543, + 3191556545349441897, 4780077336463115599, 102121356289129288, 18353108394754479957, 10099934050411322327, 10323433488737585897, 1480832277301232858, 8304664509429164326, + 16494820005379860880, 1719281141269927630, 2983529566257876158, 15928721259545722550, 3714203000118655889, 15922105900709017310, 17662263539397115758, 1577461381995722723, + 3426958921435818822, 395886748655323570, 280632942609884625, 4361473570148050146, 6600885194277340683, 16668323952296831943, 10057749804882861513, 5701592287343868424, + 6951585494335471689, 15680855848517030170, 9776921814538436791, 17640230976984644473, 5777838393869379647, 2176689364164694052, 10884627395386092313, 17656310368333301757, + 215205608065278414, 15361057989137229644, 6756215047166430628, 12215084297877052825, 7185815532109454500, 3394755837885079236, 1778980761557523977, 1861969072415300655, + 1535235777601157298, 8875662482214652105, 15404846185148709157, 6538418983879634448, 8341745508628160868, 7582603669233291629, 13003716464169800826, 13309194956036155778, + 4791947847339351337, 15204996809755844932, 11672964318683763318, 13067259871945801803, 2139419248113049376, 18195694858089271989, 7208559250123396675, 4671149208567820584, + 7276586425415793787, 14549539461274532692, 7381249250982432115, 3215735370879771405, 9197833835152018601, 17236122023193655371, 5029275100388702506, 10829687080866991082, + 15533362570521057331, 6942829144635570952, 9572990445468151820, 6294042535380467396, 9052929167426522790, 18293430694900525497, 9076155092724374912, 6410242671697688127, + 16930844972313552415, 9009509357611549679, 10722442939705348974, 4686888495512108749, 6326319203058274828, 2590592779822711917, 12876493112068819735, 12372064322375408146, + 11938822647496400962, 15333527667419199710, 2385985954862343680, 14776415112244140169, 12817753724474105460, 5129368568396757194, 607898027127847045, 3917240453172744497, + 47211231428738650, 9333275559955619158, 7534434473427098199, 8557232404317963052, 11597011861056629671, 15926835677212702441, 17943276685960195536, 2513989430679125485, + 2903417389682946131, 15905578940823611094, 4910425097773753648, 10817415382143821768, 16356392378927186116, 1174713154793914656, 9176413825070952738, 17779105524945038711, + 18302140065591767046, 6334261306636966429, 4203057092695998640, 2740754645452686340, 10020911575632378009, 5906713384548665207, 13902791548718280892, 2505591245136304093, + 369660229032730089, 11851915833529805698, 13485269529443969890, 1270120511649175022, 9128783725626301238, 6173048611666804214, 14151404531169195672, 18241008099921643437, + }, + { + 16226789363155700046, 13734705589524056856, 9629995513492843231, 2636144377026081617, 1233405076007260313, 2119672919365858964, 4932766292290315579, 4185117177904214366, + 16996170392430604056, 2476294162951949891, 6677439492116109133, 1649550562276235959, 7307278264575968221, 17128676264244010843, 9768062299436691373, 3825325732056225433, + 5861627228365499618, 5011684805137210454, 1579621475012951778, 11535371650014354624, 12847902922833318241, 4997014846790385136, 9875988184618650628, 13094082946822736823, + 17224650011872599657, 11430188086182976152, 12892063618843720029, 5912993124689510433, 7069617917494051681, 1298012103142698333, 7943359430865057535, 9329776843721719539, + 9091412025380293893, 8622355764644651307, 8718353412518918238, 12338548766610785709, 5241721208413391572, 6315749100915178625, 17919741546105181107, 13677847475856526539, + 17388254638056933809, 5422523708003180288, 16851423629233109043, 5504298365310420423, 15145549220326540137, 5184279399795985462, 2201159255780420815, 12506121988996036804, + 4460258780042860751, 1816027820333214126, 7778555198679811350, 8155451943744426012, 18392325810806023014, 3955295139981696248, 17141295608995204052, 14206938573418983337, + 9464085603669036454, 7848014338005901108, 2368914226155404065, 11578416111848517850, 6323647866244499941, 14399589996703947996, 2824522520842155768, 391310842153371124, + 17489550078249576530, 13418700716683405568, 8265132837103985034, 8386855948619700037, 4642739669076635265, 1941217860224507563, 7402267177254210690, 9863923110146355168, + 6176679707488254741, 4307819088229734202, 7082712522654871200, 14603822721598353371, 4115674343542702663, 4132348830250348245, 5992042367418590636, 15937819366199058986, + 11008669567537833607, 14841150752801539889, 5253470025479549456, 5665837575328478629, 4601810548582757669, 6173003636576141170, 6899193615399367692, 968231402917393055, + 9948650801233133770, 5836115460383443197, 11404170696974449207, 4791020823967734476, 423024247809958592, 11251668387880260801, 5562546584223492723, 578572156618131794, + 13456676488167240303, 17121749146829956377, 17370555398500311209, 5041791432274350681, 4009412063225388868, 2407629981571159579, 13052555280728877038, 11483117063845312302, + 13421089948800544371, 5001604265596626568, 15312985179876036482, 16032805766802337150, 12508684642650694186, 10422897636519090240, 3970071218688010847, 17419166239676042564, + 400453640980208069, 15220637399286523210, 17321057148174216619, 14860227640908306879, 8047994708253288483, 10174040071518845057, 3280567772472213687, 5651529697807929627, + 13988854693674964723, 10817154032069031941, 3171651998645961547, 5518712225783687705, 14706905091132091970, 13960758460934966876, 12141035142079693145, 3149939820435101269, + 17047631647660916802, 11327141967045825261, 6773994317182166280, 5064726840218426586, 11921340002806613391, 9067034595359929709, 16499225867422892436, 9333282251383805811, + 16851791401266483516, 3629537449474963381, 9616439067014312078, 17691280261538133313, 13915291913519800282, 4229243823856128517, 5998682815524220834, 18293451622818510596, + 13740317056016164038, 15410121987858832401, 12080671504470100936, 11635316325777860129, 2584464163154495637, 9849046399519426256, 7991103215010751716, 2109987257001640948, + 2505301881938098126, 9962323478923652140, 9312199523950444342, 12957822502673689705, 8060810607849163143, 737408553843844193, 8143568733429881786, 18003168270780769476, + 18361695650419575705, 15964191128341330249, 14834821085064012697, 12512940671502931238, 11592194993753547188, 14358438239394059598, 2876909840522954216, 13154864917311376528, + 1919485747906370662, 5250174270363591951, 6270889482486194520, 726576673961648732, 5067680336545953003, 3152041783219682891, 15674051618916413369, 12438966377512424334, + 7755405178378312585, 2001220826274540277, 13276328134279740680, 5464764824709243977, 5374818714652367118, 7988129049563289676, 13996688354532099099, 14091540329663446637, + 4460927228453411137, 16058422703785787527, 8016770980039986075, 11450941100964860520, 2742597710491507274, 16940752978671801273, 5897441526901650840, 5926672707007682446, + 11513132526446047688, 2371334524276946445, 2461552185903242316, 2195417192784351355, 8821293936856062699, 17392142102281287994, 4066797133115509650, 10704373174879556404, + 15778536817306082589, 5755579035239870289, 2105368957367433938, 16043807797277162048, 14990960263520315004, 15618512283659189876, 1020703273079622517, 9735594589053383212, + 11529096471626785524, 13217557548494128192, 6973227637542883184, 17901194406865837244, 2414269359614891938, 9165268075797348071, 1013041849562373861, 17525420894350269712, + 5772778048593061508, 15424756817708323928, 11842041259277183807, 17669952685051160523, 5405007811515938363, 4415223809135251038, 2223192286456742546, 15742105795795272774, + 2844957165101842208, 5188198001787563362, 17071130520794983821, 6691797472842348899, 4294126956896299534, 5788827614077663481, 16267876196920424765, 10795461545625002360, + 4405006158507706423, 8343317561528812223, 7851955346465616798, 14568481075913348758, 4391527082463073614, 13997921112025001396, 15259963045788570485, 6787776208020191083, + 4002627348223514978, 16231148554725644698, 9578235186329928114, 14741034641204805809, 14651073646349829984, 1797163177099497214, 982043220105120238, 9027434646723092211, + 11809342655313500273, 16822704101813284237, 13097372075606737923, 5463281428453250615, 11967866991673525562, 6828790575157689223, 12568831962097805646, 8385980093725157349, + }, + { + 9246769514475702626, 5788284997389507365, 15857897362850327403, 13864676801095094218, 12881526722328523267, 2620841421323221200, 12599981775316397124, 12820989846844560040, + 13066648645100247757, 16727492115601921665, 15749471761440498106, 937594351871983779, 8381111811209734349, 10884357918725639691, 781591570669492079, 12778743765298428266, + 1797915488494232282, 17274756142259274463, 14207994319179101777, 9405903752538915237, 9001743317941152797, 15048752608061590843, 4925745663463425863, 17143694017177138485, + 11613437975225156304, 8619196433402562266, 11907033287998837424, 5056904365610561965, 7637552956459333558, 2827449950719061527, 9998507085256853501, 9238562885525900325, + 13246436769495027717, 5445015753017977819, 16266739009580878036, 15566606095998238977, 12196078605380432771, 4854324313875295137, 10974170498288217052, 6425550765546527417, + 14574824159194628650, 16992289415800830701, 3499062703303067574, 11220872042664151226, 18135860701984580530, 13630928571014923388, 2913126838766947469, 15869180955632349704, + 10621010745328025245, 14637275395423748577, 12928463178963493980, 3270672471462681194, 11765440832075775157, 8138439106739837848, 10004644076263261924, 12582897670868871780, + 9605391611675301152, 14014632424042523224, 4638465078692570733, 3013469722048440965, 10972600060210514686, 4497572559400894366, 2652629676209366276, 15827846806499715082, + 216774559418075105, 7056732230404238374, 4342481467357759950, 16143194646968227790, 12304857685680249595, 5021239809847286634, 745754913624924064, 1603290801266214539, + 2784418922013631805, 3554650219010546629, 8896448905401216908, 13445015286698819482, 6508982623352460996, 3322529327934132311, 18417788670080975365, 17554108945303789353, + 17620122226715347133, 9738429733440215024, 15577771434516492888, 12422193389576942718, 18383756008252443605, 12736926759685644351, 16981429110294392086, 11999528928951986433, + 14489177617081844909, 15995916840320959685, 6361381313838994395, 11146176143708648759, 17190512001934479207, 8406914945663974955, 18073221191428103088, 14075266763636071788, + 11493260321718935244, 7134447477334726345, 10489281872281557152, 6145540581503915475, 4002857892747271740, 5167943945955725680, 2892864850826359384, 16887114279977647596, + 16493058314197913501, 14642843949567816202, 8421201635021034279, 3645913604138483317, 6127272877310948153, 3660286308390076870, 14343325047340052700, 5355450922054278073, + 8426383571761073988, 17627146217941553397, 7396223609641674418, 2402241526082789613, 4067059813672963823, 10306840429023537942, 18342506396531908477, 7249869764848707701, + 17055119974261943875, 6266720893662254540, 13102139953381148874, 5249314164321788611, 7157525732140787612, 15381277459195914226, 17265025258266710353, 17573500432599548120, + 11703325491493519624, 6756922948215553472, 10849241105791329449, 4442124988071574400, 13193138084274485850, 11408181130174894537, 16602978650637017500, 4282478513876287613, + 15849352004835856215, 7022332658299393045, 2753527422472509447, 2508636546397160815, 18156018186852519542, 13445036260276495365, 6279372959444826452, 4487789154840943220, + 6912674041294744283, 18177825269025993506, 2129493844567951509, 6833453501368177831, 1878514166200306112, 12873954541639117785, 7984716702294892278, 1590286870058148425, + 13310953099825480439, 942949035351116482, 7073926138905956784, 7700580694019269362, 3135382872993338421, 14860196563555722941, 10662854588851556233, 5736680857908686906, + 3285730769783013255, 5648284582450022694, 16712547815126338303, 16508335566005209527, 12272617736405465053, 6690178916455692547, 3481505327914964440, 9148348679521508925, + 5445751308732564169, 15671537507319596886, 17721221564106627243, 379590599139121791, 11923849517192812255, 11794879354344258105, 4802202540817083733, 9502952511912834734, + 10387170863530151921, 5325952605083195756, 9255511257002170523, 413412942592261158, 2693041233704004652, 14135620291598275670, 11595337134421837671, 1965085859594934829, + 10567751951694288416, 10466024270444644770, 17138727632883910786, 12652567654757797118, 13864111438265559205, 2552332838857882141, 3739570066357761968, 1439381288436968019, + 14926469836092482784, 1974273958550553776, 10770915481273902280, 4033929759715842024, 15461883773070197251, 5631323369668498153, 13319268013678629907, 16483196656661792008, + 5825598074470439590, 15514383036808278765, 836600073173284669, 17006029483641514808, 2253041172677940136, 10109282146738215012, 2050330973627959134, 13783991480192211446, + 7361422649689322835, 16012782899552425604, 10324124765039044621, 12319908523309013390, 17065808121376215422, 14844145564675640794, 2754581529304803758, 1149534055082731343, + 5371192675994106473, 15892724499541682278, 3862864290653799361, 15759456296270265029, 12018492462347307225, 11503979417352537931, 1894695486127847219, 15184833349947874986, + 14711143160318482298, 15515618319260581947, 10015362293284733112, 1169298538214120845, 14481541537099551545, 10304547737174682912, 9351439436434829996, 15807708290724844107, + 16946643895530263911, 6110142153011856496, 6857516759047242219, 2026267735072107620, 10338469980804248611, 8224240981205716101, 12739986350836865860, 6828408496869642385, + 18199296108774357398, 10154672256889745380, 1190269705881674139, 2317654455984851716, 6948704988682993246, 7864433505284017226, 12371653445644439372, 16432795124971446509, + 940679263188661008, 14653357165718140350, 15439920797347843673, 9415587255510557494, 18115037054677722678, 8165849408798239027, 17369387099667572407, 17619066457126678815, + }, + { + 11047138821675365077, 8918121441180891972, 26692501222219426, 15248413052700323978, 7305399157133896461, 7065644238942265367, 3949166834387057064, 14178248206708015607, + 69860179712677448, 15464996655458230480, 15095351218136595554, 3792171085643513009, 3187131848664503636, 12713332789590787064, 6278731049699775392, 1597379696359884724, + 3952205381894147962, 11371446109407143937, 7231851263356642380, 11612512368538303138, 5227214975837085115, 10737565048439707166, 6333629542995218640, 12386725921557807638, + 3631886121917081375, 14286411187847401959, 1546298555066841633, 4790996540037176549, 9541492152219486842, 12304868498960755609, 11426775785781090329, 10793898029125361155, + 16970032026045908366, 4739834790205788500, 11604777595337607879, 7222013010088766249, 5472916641327283117, 4172262758310864960, 5724466588558015820, 1116300519629843659, + 15795014995613238211, 14290583239597353888, 2490895887909073495, 11130992987297321872, 17554999787604367088, 3420129662095546057, 11472786435923282727, 16869713476687852227, + 15035061229930585935, 453017670704522761, 13269498238801130975, 9381945743239523058, 2560842189862328725, 6461599464735341542, 12067824007347016987, 254830492191366350, + 10932352970046201499, 5875690226460998551, 3699681560657289718, 8665743594825198441, 10232089728487302472, 15664572298733091969, 7267222702489958195, 10552093353886118696, + 15492342672675114391, 415437554733257587, 12890781990283079094, 13204935186176658494, 16394061615709463286, 5115734945762570776, 10421418042968619739, 5523853293632283162, + 11813086056645720947, 8830149648607040713, 12579056778157665738, 8379445845509747387, 11968812374998926933, 7579079245215672446, 18392522237039663466, 14209436550919930092, + 10567400467353853420, 12039111362360014956, 9752698954159464580, 974455144078370581, 16749750902684349652, 7431880327875076520, 16572811640260132367, 197121614392940749, + 4008236965647744142, 8547116629188387980, 13874587567755370880, 12696453513706541959, 10752386832421030566, 365775083075323708, 14295272684753058141, 11024897725724291722, + 9389823976782902582, 12987864137510618346, 14351996708263571593, 9397276818616280108, 8943695845699072910, 16761881794918812428, 14395546039428720745, 9608138420173912436, + 1876375509629583057, 3290820252719995988, 488255726920613097, 12524692306565281959, 1588481057230489293, 2737168321842385117, 3787136521155591587, 2297952115270241626, + 14002797112021507101, 15941913959379016886, 13373428680779564378, 905956693320605119, 14911807685762669378, 13046351903511292109, 5010776430112230246, 13569296078340893444, + 2399232949134869057, 16408469118941953277, 17229778225562184411, 15990256768949242309, 10694906341686584836, 2816242351659628719, 10794163145486835660, 15601904974333104002, + 11025280186920123511, 2638544612389113264, 14138782464677956897, 8182901095979048555, 11304014986311338849, 5418181013691186545, 4702887342992202530, 10901371551431733592, + 7470028071605003558, 15552389775050890646, 8285175978626575302, 11755261053723122966, 10951094485216236078, 5507384267235142469, 13239757172982680465, 16153920989213321821, + 18058993449364903238, 13898361855323379776, 4830208064835445821, 2108287244297002782, 403367259355957679, 5208097191763320114, 5105753392567780820, 6874403921011777407, + 1158521281204350113, 6232098057848694897, 12517518152351190341, 17852831094628421272, 11653774695260269881, 4420518556213490728, 13835371272800239099, 12119809446886544909, + 13202632776652821767, 12444449950521044637, 11128589812117041029, 13640351754206364654, 12210309609173025143, 2998033188714623978, 2790558847086549679, 1412882974937756344, + 8872627396983903111, 13010748252899511409, 9503554222158928531, 17266043773425260257, 14299273669130129568, 8206060595465248374, 2391269797717981426, 11490348680137544215, + 5625434013536513462, 11006046905736534335, 12974260386406529669, 9092861657954444193, 9064784322822166467, 388172762639483312, 7975459140038679785, 16519143691087724914, + 5143546864201185527, 6400878864024957342, 15513803558106064076, 6712861984922181478, 15623960351786428150, 3094277713920675576, 6184647748693682810, 7857605928718754519, + 17306606255667524897, 5112741148301782470, 12807238528895999857, 15137864759480529337, 14604908573844046691, 17945466774813936069, 8840495514948749443, 11197321446299638637, + 17220811598578674405, 4438480777123093236, 3563461541688367236, 3111403934731489046, 16319666149508644048, 11775149819643332554, 6467838040542164752, 1567553021477840718, + 5384669083154912160, 17619132083131362037, 8938889855576647487, 9107335704092137106, 10077424566800668390, 15550874273916351174, 15171215175982142697, 15277375103802490853, + 2219152199405421709, 5367881810186787185, 9606063680551349934, 18233690822105957780, 9941441403610160291, 14996958158691873775, 4936282940888570414, 16608409936766385729, + 3344228690528365773, 14741103791830625697, 12105806333035047780, 4814603778329751458, 15692542571489717296, 4074467482166609769, 11583878004635312071, 15057041878895842153, + 12046059187840675577, 1106267261822046486, 4800396230944794513, 6983782857932290361, 12630891077786998995, 18331269049237387531, 8843236455524152484, 8233277245902259517, + 4072376012468301087, 15956856707868364136, 6651399164294705117, 9169559249495366525, 8774931051408681195, 7328702764302633441, 3821510551720221090, 13559321821383641691, + 13270099407878039596, 11569032926557804346, 7759575992876193458, 8239088820951102451, 9633607727685959064, 9775909232917811341, 12297921731498614906, 14756100221590046549, + }, + { + 5228416958727036186, 12534300056259911378, 6859045937063682340, 16561718753727911412, 9427589074776024847, 4167904055656501509, 10156691045253563236, 17557096561606923049, + 12847261474293104380, 15935635664155479706, 11956861064550631146, 11743590506948225647, 15973092866215748716, 8269726904881958353, 15639962392523441528, 15171417818360069012, + 2605212343977737441, 18393471024186189813, 2302707671753008158, 8606549841034095192, 3842822953634987820, 3094721493917442423, 6408313759447502937, 13486364200254727287, + 2191808101092881088, 128992526124656216, 738676021426139131, 10157323147642681558, 11221959943853120586, 18255489816550713347, 10885231659068427649, 12104397395119665023, + 7707807226411417919, 16609863548699265350, 17639371636697428128, 8755472387723764172, 164779854477783265, 9714199241756765614, 3491355372893948450, 17683742455036967163, + 13595758632462338296, 14515163666150177917, 6720823780841221770, 15071435664343609336, 9016075014492765983, 16881277609836316886, 6969993988115170067, 15419704786434737070, + 14933348768149415725, 8499210770493553168, 6778840616148281272, 13282837866452012488, 12007326272174861053, 11172739862019218274, 15202495365302649711, 8797477675597086120, + 17862558746132168231, 4941846130090682869, 17131557654945008226, 5312800819142473968, 5818269467205924209, 13458582047859447022, 2683428091382447153, 12956887954464730664, + 11820752998821943867, 5623379642132478491, 11666807493120740820, 7241997274572162616, 17165010508995490690, 1769225877906480182, 3814296306467163522, 1913823003062817434, + 11936813336110488997, 3878433838529606580, 6540053284493149566, 10610279324743393563, 14079852809920102066, 9176732841330794388, 14287311909822853963, 7146204303626670196, + 1222343790928490335, 2199405396044383670, 14080919887213592148, 7341303626667347624, 11784881532696657518, 17307742911086150556, 6036132721599132043, 12167106497065306941, + 13817073203406999359, 7220729284169210756, 14908407498603601482, 13536224989620701632, 1615171540711527931, 2063856048260214664, 10622581435417474559, 16378505765730768032, + 6855676470217754770, 9517149712286624325, 11080380031068971680, 667425509348698033, 6136243307299269825, 5326577850303193160, 16120190278345757447, 1982981965726975383, + 15399454106099176868, 3988744407816581672, 3596277710300384050, 15129113714633923498, 1554582462382333698, 3164553872715651710, 12729140363982748426, 16366728035709811784, + 11647936211409428873, 14704462653811533865, 10005129575282387925, 1526194796943187368, 10906326807488904308, 18256878690674435807, 13093574545395154003, 12352810226542367406, + 15290817014272444879, 8012864091692295774, 7591940515496590516, 9299619125326026848, 7297256232167521068, 17861204372399797627, 3100022958796565106, 15313770879200204613, + 10190931844127971311, 4449277895844944513, 18060903840299422620, 5786504870079014862, 13877878835839147302, 17536010013969819055, 12266576574650233794, 3344384108564085445, + 10406231172694378191, 12785551100938284935, 12210880209800471137, 16615829503150405150, 11718424737227538631, 2245674303359461903, 9283401225508960391, 7699506693893764319, + 2278745583218618906, 10638058115573097116, 5685140621618740987, 7758115175926730915, 9043786871908073988, 11442680114439652875, 15805407285446479015, 17615595308217319903, + 17127838629068819444, 14692086977823146619, 2491742894643214379, 3238012827598604955, 4066194902402629617, 3613111175737094005, 3296022969960608152, 4860674720288543209, + 3753308721541654311, 13160824061458819791, 11298768140351857216, 14042645015841972579, 10518697187157549363, 9641851844202952198, 9254393371864075771, 11429987449073904258, + 2566815986599406395, 7824829323439900657, 14465315986665451243, 2957504741164666523, 2280672126115151165, 14999624386740200468, 6090063205272921919, 3478652904863279960, + 18131467168461028363, 16471039226156513736, 14133684792391617163, 7137732710914086892, 17299189471163637576, 17270681183882183871, 9046519354210103502, 16091721986926209161, + 6572875037492082093, 18318192911446580882, 18107990043035854610, 13573958681720538720, 2821064027974708708, 13000417359062035623, 18286430707379660800, 13070676610179458046, + 8521670721910745896, 7440450230382417926, 13794050882540606099, 3657777690979179248, 15466400576048586018, 7802926536345945651, 11932698778931413693, 4291944108972289013, + 16729016738422946915, 4082443597391481873, 2238453914102498318, 1806710580451019071, 18305396377745213463, 2262209146853870557, 17240603302299977012, 1540474707615687112, + 16013022710115947086, 8748688582020024424, 10921431579160628425, 2228053349060750948, 7024441100951863599, 15816203310189470753, 9078141084316010447, 9841344410499582933, + 13377311905703150010, 6352753896568161822, 11086576920416079356, 7629848369702522073, 5472036379742160857, 6535781794177956975, 7671272114437903042, 5056286897725243410, + 14579350500102276494, 5882738271691348624, 7188200631561491668, 3605286077046581049, 8957701412704914688, 10347270272487533128, 5995825272041784807, 18321189862831103872, + 2376178340116743056, 2263593380938083722, 1990228394694589285, 13477447633165073333, 9023956677421314778, 7820910817739139038, 5288765314200405868, 13070699273589738968, + 6765952613794178887, 347733275422001747, 7640026333627494061, 12925707101320796635, 5670472934143686904, 15041817307271371058, 18176041895529109656, 6838891343875575060, + 9902363248877274636, 15776195244792726061, 1935342462634574355, 16572507349421626602, 7503944294807242065, 7454248748618678609, 2837392985175901475, 16494567631149775512, + }, + { + 12299242278498309265, 117303082144788574, 18382936515565701803, 7941141688858846015, 14923823358299367958, 15681089039073030752, 16878721085421212785, 3933697483394042011, + 2878536922988449879, 8819365314325664735, 2696760638950720974, 11357179421800829605, 14730809809256560583, 16277258726425730599, 13189689275745970592, 13769784951430309444, + 10292669945637125918, 13595563061674492799, 18301330068714272653, 16981073598172019270, 4022713583718555211, 847970754090163894, 12867993617169467387, 10021141621864633865, + 15254713655124736464, 6283719686609422435, 5417864180357938798, 14010638809605797246, 10873690600705871523, 15014239467130590294, 15765460219545280655, 6048061577845125750, + 13465802402879986040, 12777495579796377113, 11251142258511736751, 8312965145580158560, 223338793373356823, 813747086573652373, 534790745256052224, 3658554932030960904, + 223170064814687698, 12938716002978051117, 3848816111228150666, 17463649319617382466, 12886402189488467296, 9605942357133455486, 12272689261734151433, 9916808458308982839, + 2879267873712146919, 1770061136847768757, 3497337219301780129, 17065005588401306579, 7675751531915094916, 4337540836976665798, 12505868586426061855, 16929961945120117126, + 12012729503226546642, 4811951115754240681, 2652621264600062520, 1108958391967017223, 2508980100759035797, 9023233544151778447, 11183557587641545146, 10726727280840759519, + 7189877122763725514, 14656082750550993666, 13508306914749420120, 4564443784575285318, 15450566991657647015, 14019683331552104148, 7751003035652012225, 960642801291306739, + 4621870789074053275, 2699296606556701282, 17510056683561737074, 14554735156054608866, 9556940770704438829, 10801168482998872433, 2280142648958056556, 4982572404720159279, + 14621729774738200671, 16850208728798178903, 2650832773786164628, 8325244333065591089, 17692120343646193143, 2242845836784335580, 9386711085286369304, 517979059098779699, + 396296174223428093, 16763788748988621834, 10606803701784640909, 2399987183687936561, 3641562114746393614, 8536687357022564742, 14532545286961725758, 14658331097531946901, + 13237433907493396869, 4990918623816750268, 17673032790739307275, 15907935024302716062, 8613470231259845273, 9346326052910147032, 17747177708802561938, 4490130127498754807, + 13867405496809412712, 7002613759387491643, 13033935552806967378, 67437088702121131, 1528641041740753990, 7001198041125832592, 6102137699349551632, 11527483925092226802, + 5535652777947676324, 1216916140919282417, 343617165825197489, 10806931059627863289, 3212291315152120591, 3351900116486367965, 8595828725191802110, 15621077401736893558, + 2386026063595321071, 9144724461940169335, 13121187420621518554, 17351696676224980491, 143495028693925520, 4590642171152119027, 8655406817079059692, 10005507077955932112, + 6982427644490593208, 5211219672384700779, 14348546115682624722, 5876199850746516331, 18396840586595761484, 1465795856184232635, 9374516147960853174, 11803025633575966436, + 16374709377982692229, 2545295070586009694, 17366393861359867323, 18067336234259281315, 9181658491221440805, 16188192004088261717, 13669686513572099673, 2044092029751770484, + 7308293641399229883, 9813539775451467496, 4837144575100457648, 14073521030008335794, 12371724228966966456, 9185074727660313894, 7387427551441329556, 1866580457929037678, + 2047964090310465728, 14133690277069748515, 8287749071957055844, 16821270580974431218, 10324684883587585565, 9652498187344172497, 2461802306013063247, 15048850312040680643, + 9659170831875656345, 4251587871822599596, 12391279033133774782, 7346556824831912968, 2133114137534468833, 8694105814921565301, 1000087733076615381, 3478818915231998954, + 15832320183998834886, 898251865651859288, 16874504161383651033, 18425166917936355349, 13387271833996394553, 808054572728974308, 2281828182196149100, 14620221246129351423, + 2755242181069093228, 16155597320469161129, 17375128328249992589, 13376690667170223367, 12825454052191060221, 13625129606409283552, 5627148592782580041, 3092789333954796605, + 105705035058376953, 7541598459498134635, 6627685529861836787, 5724525771392188178, 13865897118300842617, 627652561624109853, 167084371112939132, 14192831153344015422, + 15618434900514973465, 14267977447705810206, 8823759714826430108, 7918740515193061263, 1664424041430494212, 9076733744947861202, 12010737794701759719, 13920688631446302868, + 14823160144680924028, 15690572793903331709, 1101762466949115887, 19462496059060771, 6099422315003219574, 4300077459158116870, 1282001407902323746, 5792772971400374848, + 11488321122368726901, 14632273370344181937, 12984850848826263218, 1857014998357880446, 13897135914532207935, 15925630222053677390, 11992050787349110965, 10072349923584966035, + 12837696619944805389, 13470316523008526719, 3074966674353053986, 2630814767089382743, 13353767941686870870, 11405513520090968568, 3071969598389884693, 8212421686942839224, + 7866179127856055582, 11874624506147226333, 5793384221044709375, 4411967221310302622, 3004913667339358722, 12230878672003882045, 7395980261120250376, 5188846147165419817, + 16160221386626609076, 2876994290210606255, 6065036384672004173, 14696333348949573335, 2667009584785381424, 12100192661844794919, 12401945669155059163, 12847772853650923808, + 2286437117905535902, 3130250324287833414, 3662253455746154641, 13229041365675585947, 3663813013822489770, 3093300797589723687, 11507645566517710232, 3715061633580408995, + 3464453985305889088, 7486900500389940957, 8944303108517222303, 18319933556403836918, 6782476025105836770, 12822840946923377510, 2799592944286097404, 8737598030273298051, + }, + { + 2754563581284692865, 11257360722362829387, 8254261291934606879, 10023569920325096229, 7980898855627864603, 17162063449612285703, 9275759455936104363, 15936804738099638644, + 303387668469489035, 7978391052264888020, 15413722057350324494, 508608987485166058, 5585753287556892522, 1344134516582665443, 15144279405777509214, 17014353449841567149, + 12518577022215294774, 11347384788122950558, 17122718824958020364, 5431993665805279177, 1445831254446028321, 9845654210244803480, 18315778529692612284, 930563922336183289, + 4894710987714215219, 15704993603878996107, 1606204036324478223, 14308635149530198932, 5026736228773269251, 2911689442372084137, 9004077539360196849, 7770049130277452000, + 2745120518194234905, 17255944807561408883, 7371907591838942770, 11781525288383871227, 7814952754785494862, 15022715213812536212, 4112388658963418656, 13703771908397991335, + 17455440140812341569, 16738670164475421762, 13259904130186215994, 2168106064304872507, 1969289843772256992, 9025317999701057831, 5835661391798891929, 3826587698101558069, + 9149648374608464235, 7248346993716635643, 17283919168525322365, 10107681064815728795, 12176813938029507719, 15110337574289033068, 2436453685316043712, 5876967059744625564, + 6197919059881189313, 3300993078638782623, 9357667752372201437, 17688129755135009447, 5477090746558113696, 12602024521188880300, 15889961935507293355, 7135039746373941272, + 12561063426893244305, 3079971284510744316, 15695857190375815873, 16730673956207425338, 12065477821845465116, 13846158368121919228, 2126156187526559500, 3005167441915916768, + 3858987859895327040, 17043903959888117395, 5861237635520080595, 3292646198413575902, 14286644557048422360, 14346409530388980974, 12583555046601155161, 4665981927428063991, + 7657686120974201842, 2388299767028319466, 17934808017791217639, 16708640707026372313, 14122341266134976486, 9547124998857374491, 11194069918436025923, 14657538980930727877, + 18115789712912297420, 6543740714573413570, 1955886376702349613, 14736853369719086334, 3914330395250768396, 7607848156418885173, 18220633528980056514, 11930952850158858930, + 17010681753474701341, 6961088634819162945, 18395881317121515295, 11611411242007267179, 7996717433149311639, 2687736005475404867, 15340214362731923149, 7116441414289074727, + 14302198697220662403, 11915041511943922518, 12363437164440173650, 4047410026894059083, 11439743031696133447, 8776097395071907030, 6851061783357383945, 16484733576581941012, + 2861660066704264713, 16453202148771053225, 10039035813504063627, 6275446616881871868, 7150609984920482782, 11100941755544354363, 6219760433202580646, 2875377482232912143, + 16477698187919702699, 2757160833848759781, 5976267476122243443, 7375951277779829055, 6525111513935493528, 9969722922172879681, 12582700753056539952, 3861958159147836631, + 4207324524057007052, 13478421263392765917, 13318275642734768006, 8504333045658265535, 3960720256367501697, 1601661680373853468, 7704205542213854353, 1552780884856863914, + 11788483659211580527, 8739274750400900816, 17562450707643849072, 2113004873311762141, 8542099133996522813, 5273956141012313478, 15661081976505113338, 2290009483289921559, + 7730337285529332076, 910421998453976119, 1242962796308775978, 15931313183507922513, 296811920445331257, 5821874870466240960, 3843405649348506130, 9007082448812181532, + 7200777231000974420, 15816416455380831370, 12932038056359512011, 16422801186386616731, 489979647738684819, 8269568123908387407, 11617965045895762979, 10069799398667455631, + 8245819835927284113, 5237630684564909794, 16572245571184457585, 13396211619915630497, 9177789877937729597, 7598297211302983411, 3133511073496333246, 16553020037702090576, + 13441991323065749602, 15441570013111011986, 291172418860690999, 765089869758770890, 15943751395897588683, 1887511823199710563, 15452188663399676440, 15028027691170546376, + 11009923302693800320, 5465227554242327455, 6511134004216481185, 2187999546010819375, 8387421071023131689, 174295266381833460, 6010935117399493668, 3340537243300033200, + 270646782953286316, 6635640130829923909, 12717598479778596267, 3198506535831522029, 2605714695474737827, 14548588937126505914, 10448279824323025574, 16008560590494788290, + 11460241048816176102, 6557818897531989327, 6948658872009630691, 12506263743501199667, 1813031030961999507, 18320107449706503757, 16783076453582799039, 10113937529079967843, + 3096618551325580575, 16427990761832670936, 11792441105446619028, 682188988823121368, 15606025696371121549, 15395362449248397023, 10158149307437310549, 4442375503593769727, + 5486499432056098253, 3811951715772590831, 3856863699598204250, 559724736042732093, 13251752681229681959, 3173330346541355882, 3597530263899943500, 11567248716558420280, + 12822024566847931229, 14487146762942136806, 1361688279016339671, 2776885758026394514, 13616222293131162973, 4629388276054227930, 8304132204812769256, 15188275451670510949, + 3676452641243730693, 10839008248003066479, 7676518604603740317, 18384275325050378660, 7827069556104560937, 14335741841451672783, 1145975213382205474, 13691620069378415495, + 2513451633312793643, 17331457978938147928, 11588204658848186728, 8824497684232939293, 5956154520546906549, 14434958079241686709, 11798870987920360447, 5875117843056165993, + 11313908033360767461, 14678575871510948417, 8479250768537158849, 13854183783158898926, 9413525381201650053, 10077438283140087199, 11413783222317729281, 4418417663988371635, + 6001837395299394988, 7545846298204709215, 6662102781970969966, 12696054550672669874, 7436995610194789060, 9042605089262227561, 11621508125069628605, 7289479057360149973, + }, + { + 15555649500689005370, 7857014165815014600, 4664069234996337119, 8058230521837307501, 18090421626009183450, 9278179697462444898, 17138879353097908770, 18285223269807746171, + 12741225973381753432, 5461579923265799106, 4348015554411389960, 14970536173310927872, 11568371199139699619, 11748662751675667230, 15495664823061891700, 670495577617908409, + 9865772269601493999, 7325690007062740244, 18437964667185475354, 9546360111100619473, 6266116854923135821, 295905071295541234, 16037468634731642095, 16602609756229843150, + 13266892287530449189, 2232961926857263527, 5934654989155432442, 5415975493246016158, 17117784386882463158, 3875398271691758986, 15755743581177209843, 11380746535012415659, + 2047267291755864302, 5637045342080349843, 15779859211873634959, 2415175423642772217, 8664113127182901077, 3032959071705433205, 4250761979529656864, 8729259992491925346, + 16559648310139278090, 4796731467175572814, 9267555165184254828, 1400425639375650333, 5199035239208036114, 7994153995816640929, 15677746297407711038, 16338895562326287438, + 1740700879164022194, 8442598604870387302, 14969965175291161450, 3086786406508018865, 12097766404705693713, 3199218739761578935, 1744290654371906763, 3672816528005113908, + 10162459499000477259, 7534168794800651527, 6320985751131807192, 9263840233901040421, 12178625283764017250, 13143797113231152006, 13089053551699608219, 13480464010111258056, + 6572275813002629593, 15328678880838895837, 4281489161088939969, 17996597009627631572, 10405019085582914256, 4773602940383417103, 1455403777441353089, 14766164051850429812, + 3886207141264898075, 4215113531127552656, 14283840761174092490, 11161507022796293343, 11235510295695006534, 2260082644337974884, 3781681413610409735, 5577127823856153222, + 15609337727165147542, 5725010295752332028, 10091444858515990726, 16162855978360002823, 2478705273652882251, 11394669968372227148, 512641267828429208, 581410050368207889, + 11426681347395118622, 17135867298562042628, 10870734720453621112, 13803364322975322217, 9740527283062276630, 13765238480893165263, 4792349632705804116, 18359029140065847048, + 15215482935039834459, 3553551735757600990, 2471323651039083728, 11355669733892999598, 15830640053604899661, 1625382463038435804, 11969247519895019474, 14372668755409420943, + 11113773299077372683, 16618589175113863833, 12580653821785550146, 8264195478884998326, 13569468260761711850, 16539804400793525042, 14464540796871846551, 7710175783216723569, + 17565888320840294282, 12018783137972195797, 12159604578082686310, 3210316551614996638, 7700243787046971168, 8307491254792612954, 18022719331150542511, 15890872243361196004, + 1420251412241033168, 6449255753238336368, 7468624722117319576, 5716072259994197219, 8165015263320602150, 4757529151848960259, 2040364517493350115, 11069642333484542749, + 6861520668253090597, 14998859189233167760, 4851545815068976365, 594940747993801912, 8473464707442482665, 2316305389548210767, 3995416902578245152, 15770229481630179441, + 7316766449463697051, 1410976281384361962, 2878678490331118371, 17638505404208445694, 1130528985192221086, 7544558337870473835, 12071909234624857373, 436426448500115731, + 17436263074416557505, 4339627812592344328, 1076653379358004720, 4996950998108333398, 8528954985898069924, 8259369611572362613, 7869239207308554342, 3592003501289265534, + 9434687670958330812, 4808705744496679962, 13910334628239183613, 2628594509406050235, 10055911465166862298, 8069256921143792190, 11886968715847498191, 6351594160398684406, + 9865961381837093259, 9590584894285774485, 10674927452501376239, 13861388033657872936, 808108663597281834, 16581187679405825998, 490312642991375167, 11352102610468872412, + 12888468148530619065, 542846015600866106, 2086677842713697080, 2758534484095407635, 15767123419143795297, 7077908316515201321, 10297306681753168866, 4641656730233236179, + 104445550853777927, 3829969899624802332, 4713997522991885393, 677661257782477991, 12383280183673921457, 4373178143111769979, 6375181113677777933, 18335077047046332699, + 5472832021993175857, 6120966193470238758, 13156950075464061259, 14833372202848630444, 5760885723102571027, 18022572190906170343, 9870918995920897221, 9546055667466056471, + 9516299398994303577, 11139435630263588724, 7364473923787049608, 15378275072059759415, 7378721410182635028, 2461490895435109307, 2579531356642691202, 11061693189962996686, + 17380308085259417126, 12584808641030185141, 15485460243194852460, 16172215807782473427, 690761937231979275, 17570908286361380250, 3347059970688467328, 10404397759606846636, + 1302709369035452282, 7149637102192386111, 11659118804203241786, 13909758997057192683, 4361167997834561257, 2300569874961985919, 1609719848856066643, 9866395233709297503, + 17124591880405051324, 3379747334483646957, 2084957978131092947, 2413497199486596627, 2867893699156486423, 1357836849049583382, 13607307985344221035, 18039194570940763745, + 831259058391834318, 12782538711785697535, 12640197944141330321, 11004378265133697847, 13622812183191119169, 5878590957416415562, 4810392157669422629, 11128662835376944411, + 2248775486830407244, 1550340755758127506, 8399436463450785695, 11063895076440303538, 2168511054719571959, 12238498894267955838, 10824266376477587807, 1073243669335517712, + 13568560319245254019, 17615770913976878569, 13214159705850440913, 7542574047209989510, 7392331519546111377, 2685908847786414772, 14835825677444128105, 11347648758435372538, + 13230815692170010235, 10662664037814374845, 10120384214921531334, 8892863196093018212, 4443096401408136417, 1896901619181196514, 739574867683694091, 11233952771600927581, + }, + { + 10708602749843635238, 8046488591192123621, 11391158257016334553, 2512908912806916201, 14760224624269838038, 2631910198880826809, 2387247811669872033, 2048193899742148806, + 17392983665205025720, 12603331233691760840, 3752711326309791976, 8281544857330094164, 17004651346561270106, 10399322540256775923, 9721299450284863176, 3725182263994944884, + 13643198694788276032, 8127425924819487897, 14165945065582850538, 16520977003164405917, 1941948502806705647, 12390949208067741787, 17112117376594486408, 10232906951259490042, + 74190110112564319, 11227229657066745164, 10151080599595091944, 16591051376074591375, 8256332495682655293, 7127985739945537626, 5708687346183367016, 18310921046455023281, + 10040565835468209502, 3986586816478505371, 7957179672896506016, 13347112914739722590, 14099734293320932556, 13921950344400895005, 17478414833301838037, 961445463330402797, + 10553899634420153414, 4215979268474142438, 3643081140297634139, 11620906704125380460, 17733628678553828301, 137473878710304143, 6211837577294956591, 13926110616399428016, + 15203257341351417031, 11597829209697937782, 17317571979811895272, 15929491640570317745, 5731227916276913121, 17093153916149088230, 3908757069480556294, 18211818355208735794, + 6887629766078662088, 15330755394432598442, 14144608177273202986, 13258654996547018856, 8975611270007504091, 16869834856279102361, 12707970875852047823, 8520055680055874514, + 1643407997152867899, 5400650551136488814, 14663391437159245064, 4743209938058826866, 1728998201888511561, 11238331920657195520, 11617984741897247805, 13858029141809651878, + 14003691155137683825, 14641672309228817657, 4031783205073356111, 7414359968614421153, 8166814052414482491, 5209260157266028169, 17555696996149558694, 9780166780476833956, + 16029688335186691281, 4244772808651443261, 6450459413414527821, 695875191412722741, 11104054226249884864, 146461617619843327, 17480214580411209436, 11285418463967817315, + 4922928863857449168, 7226901725606965824, 7568276305032368752, 6253457805758596797, 14345040877576203078, 1718759302498746946, 3544444746772280646, 17880302727399449566, + 10693864548794383214, 736148233485985101, 5241869061152863453, 7166954323782542739, 16861482585847848251, 11483636939866570861, 5950529069765100144, 700887039653157350, + 3906969739692830848, 5546431121705298614, 10491799900914853406, 5871175286230239238, 2851574662174517162, 5511397532379144624, 17409985391224790540, 319012646822749823, + 15269778527761027251, 16471737837294177924, 8830398856035267114, 8206807757132984992, 1421214226977370752, 14233751335943482739, 9668238787333455452, 8700964319357541954, + 17561670470565298976, 9524122142014309347, 12619871254022879995, 4098610542031538614, 8338691110372464881, 4378598564044777665, 16435680634249352743, 12067828180476756532, + 17102475410743425567, 16244272017711449252, 17598420420289880464, 17858587557620312875, 7275673248698358659, 13952444068457447282, 14004356855576602555, 15776401868125266614, + 9848210305813205280, 13777844361911806961, 874096498600831552, 6286216140019341540, 1229781121487503670, 1221366673976886811, 4534525466071627057, 12966848050780717673, + 14890015174575641658, 7082696407720868596, 14546372439063914434, 18306301153433516531, 14360952638570231274, 5387283652784509262, 7246876761413034655, 4917620254108676720, + 16572428185201836512, 15535161956998457706, 3118508753345802652, 1036719175817464914, 9929541174185476740, 17658764424885337186, 3038747611544544975, 9299826573437432057, + 4068144934809412921, 10422353259330469599, 10820596685747357573, 18174251490011716747, 14838047097904304200, 6494279871501263445, 10908514990777375627, 2395220126873880030, + 8963350163641627638, 7331858013030906816, 15047142507680204097, 6113080618647404016, 7520779807516814683, 10255234845683676901, 12010823325949652354, 4005195924244758895, + 14455661618497189876, 980858168361168621, 5057114595071838088, 9447128440518577562, 17115933446433165191, 2063106073840638313, 5944852338857186064, 14601740796836275216, + 12750698494453238590, 822220438401342753, 12735466470750534773, 15168985403101776640, 17837672477921333079, 5413174218886573483, 8340507718774735027, 3796235681866322764, + 3366536195244539993, 13901131415620358879, 9146606194544531067, 7568835872371146677, 7101767951356426039, 1958938171972212156, 3871412404872561111, 6437054924013233533, + 12849284342518738377, 6061751293342567452, 15168528907847693260, 2071752334274992986, 338461453751559028, 17270401493472349305, 14152214298057413781, 14074152302209367061, + 3814267663972523036, 16047424572869508620, 328411057776532579, 2321721854548154476, 14950895796162035951, 2381867458906113095, 3121132178592915484, 11019696935452271225, + 17929201703034060485, 15478512769360046037, 11652099424221007544, 8436785170867890275, 16340404489137765730, 13705192502407972039, 9464924753010269658, 17372624212933856135, + 11237648987477338397, 850109691127167972, 6566350160877169296, 8028073340740368222, 4445151747345891893, 7753144690511205475, 7551118086710031441, 16785474804106433438, + 3919851124685189663, 16028223238454025712, 9008783533564802058, 15647028843636411071, 2029953422298604024, 361326896057539567, 7653333452646403127, 9211397293968688243, + 1817762546790624760, 15025271080704836746, 5761603182050280401, 10355268146728370750, 12900583599325924868, 1488036927944469046, 3405173852255315327, 5600132277974719103, + 12574920924242276218, 18146097977073890534, 18281543194137545725, 4432773597060264867, 797962164984225968, 13432184750641235201, 12394976215803938078, 3054137600383896411, + }, + { + 18270562314314829224, 17574550722906577917, 15522987576586641271, 4200899284963891561, 15719788437321868967, 18390235318178988753, 17371818886753265385, 4583380351670429228, + 10102001197913431240, 6211688443233768420, 1986665099237206297, 9248907879269017005, 3081890249882755206, 7828527646248386813, 12676034092230326487, 14655968027461080131, + 11464797300361906821, 1444449385286554508, 12433005157477847389, 964895564896662942, 8457290958728547067, 7044433897330872257, 12292673928275053405, 13679355097865192207, + 5841260956815214452, 9461234662498869948, 4761949640006529525, 18229823346336752572, 16055957459773168413, 4272222475092786627, 18249888117586812770, 4531982814021269346, + 6528332072572425694, 15678657170585498065, 14462305190193144746, 10159286562616704237, 8919172138248087686, 13247073064443362933, 3056992278576665488, 8216417459286092432, + 15095644792163717355, 9931529712396800935, 8608932369590222253, 17019087735655287783, 17120516184457264144, 16412592485673181957, 11221555966650765276, 6815162077372858604, + 2239262553722461896, 16518231021003046485, 12875479040073845800, 5243141733462514317, 12216971859495819530, 8917663622006068692, 2606734295032613674, 11237688605489138628, + 7270238601276019194, 7318279377964882079, 5226788506940171017, 16838449902078450273, 3375184937745100689, 16320655850583231520, 2173229791272659780, 9816381971766204380, + 11061652864259684005, 3625039563689831268, 4435107405432574197, 17570841169180914890, 13981724030179216670, 4992487505540472327, 12893808204753555435, 12899171569920731024, + 12002788024483301555, 629439982201171214, 13749214763651595011, 7164215996082938159, 63895081825959000, 7006379700570403491, 11929054672290963822, 14290981753366049931, + 13554823979828564217, 15627748053816803157, 12924111102804720301, 3165135223777020148, 16345805559363705538, 17656153856991335888, 5211305829410935273, 17846236012427517420, + 17113448198982970082, 8879656883528014268, 15215762680430094206, 15232212751792759071, 13699137317730183483, 11815206710130297569, 12298409691055054593, 2192455093917691024, + 6973243752017383665, 15334919534387330350, 12203459507012560294, 1880762698376948842, 13008085926447766632, 11695961991328184563, 1311309249708428072, 11981691262998313807, + 9209757463013140118, 6782250604095077195, 7896297860376631775, 11500117438976638113, 9099678680126826621, 11908588510950302487, 16863479726536938776, 6368086884375751995, + 6220904427249143299, 4501361418756965744, 13907877383736656540, 4499586229279778873, 7233050316216252450, 2775027076708404645, 5669561106187108564, 13951461080947060780, + 9742819322069712752, 8779224519997661749, 2591205872359340025, 9144644967919881415, 10495832103710459914, 4557264342687723360, 935865282128150338, 7120324256648044882, + 10780007491891304021, 14382731247791652187, 3296810302419712004, 12567831906993651128, 13933396378746555124, 9754754796778422405, 2905077741505886450, 1522919492210831578, + 7282056954663740402, 4915867300034445627, 234865561845141598, 8874426225092097899, 196269165389812019, 8951904020835594063, 6908903359164319029, 14062039535595890356, + 17922518107542393156, 17388335427727081004, 9077910363057082196, 15157438705071651749, 5615196861086779767, 17404239261681991687, 9772161835068093639, 8380484042808490346, + 4683169301229531061, 14940390399739549639, 13128742567354398401, 15222231511210090535, 7352694898928671332, 1221555526903686446, 8697118143614336514, 14515400523185205597, + 1119145169329993209, 3453487026721044641, 13723232966162256192, 15282444658208236515, 17806849942057939434, 158876409507122147, 11954364486113732203, 17566268785944006600, + 1443798830844295330, 5744920153630226551, 15739845606128975055, 10458513157123726949, 14711103578835123416, 13886988522344422595, 4454455988362290346, 3507977514728491242, + 15328194945269186082, 16398971046683442289, 16293780909421539295, 14488637138080135219, 1108438550767062231, 16291467684905586857, 11891067917592351245, 10459212739896579624, + 10239864229747754958, 12477284975467600510, 14054830413782031834, 17752968481181892755, 16082713391521411762, 17191329716867535304, 11245514405315337909, 15159733745232554536, + 4102022129275956496, 9361580273813141387, 13824110615577377618, 17115977884930866990, 15058705994968389537, 8039281695081359531, 7179945727911625126, 17628825480910826356, + 2477336341361304271, 18030759410783456479, 1164757311756325043, 14195508307731677040, 9794350654156795137, 1135232100348022155, 16693007636113380448, 17770308235375345497, + 7064407865619227176, 13284912648471743270, 9099541805618279168, 7383718461788433067, 3311987567268438113, 10943963018398042859, 8038765968977300792, 11039205462473399718, + 15444441705629456398, 12030687282161152512, 16500102437404896225, 11467410246278043769, 14031300093087427598, 14458597378298191386, 9434445586505481169, 18221119130471329822, + 2269899977501467759, 9674818903084386596, 11781166634280447465, 11752600152694102168, 14011747753002945247, 1084585411243442928, 15614695372212325691, 17196679090968022414, + 5062812993852092949, 13193601915773858975, 12910718608861476282, 447390754333146274, 18393090736120037653, 13231946117349235609, 13365030203093499221, 9724404925244523782, + 18064151108813428175, 3928735035534454387, 186686833744587171, 18406101378699384605, 16477405641027895528, 697258480673566897, 8958117283476321666, 6970167016227017231, + 12694666558858009121, 10992313774737315187, 6046508760845509477, 16818819584649823054, 10464090160691032219, 1221502600750419478, 8658907655588546849, 16110628890984509877, + }, + { + 6266830413981331818, 10890859480409122410, 738708598357264321, 9241173142142102299, 9152169484987657321, 12122430118903337055, 14270062735458703743, 13877635605034675649, + 4572419849863661964, 16330741525817240677, 5456771007607263420, 8798510164381810403, 16547183593064549865, 11355135595370359779, 17581910791451710925, 11684604415749005488, + 2766130068233451740, 15909689412657372214, 3272828023364980896, 12907534005596438003, 7065629942275705493, 10609982651084321649, 17330343421617897811, 1746246157222856918, + 13168953859078137190, 9072500190247791267, 11090199374278127099, 3503847851309060744, 14395788825673846582, 15073993563711333791, 12879874391706003251, 15417028700542288171, + 2686132933630431595, 334448852204016400, 5636563341880055087, 3897420469445246068, 10569177829735084588, 8244586887721364305, 17973493209847502315, 18083956436923498083, + 15514509130323617046, 9833490355170899102, 12028021566105512521, 6349458533674010018, 13470024118569549588, 7867188201997717819, 6110792121234766402, 9917858515766574695, + 8273062939911446888, 1936638151089648185, 44602505720759914, 7839132833110815763, 13045756168264521992, 5375972549477973022, 16964151563535745964, 2871770426902555432, + 14164643693563803212, 6386904235704679249, 931435629437735510, 4496152555914735639, 820099532545743339, 13419988718062417698, 8948965620484833159, 7238410427920554862, + 4387941928212462673, 8023190031094282215, 12322462122895470016, 17311901330042910195, 16445894183838823370, 690424095855074674, 12820742226551488738, 227935274674223825, + 17437729542205914525, 8439533239207225162, 2862942422640746698, 7340866642549630610, 6770451500989398335, 17262212260581413381, 2156505157624055602, 12195119268846383898, + 13685370053507732180, 8304030489296890211, 7042719123662732989, 12115154796394040286, 10496877583013829980, 8909625177349683785, 5268451666475070682, 8910488385056259560, + 8874918984373509240, 6652428549855789281, 14866714872885601270, 12093494664302554643, 10149999253136441007, 1611873554177023520, 10271627298853910516, 15171882630355491729, + 17085353800722834618, 3271271583189511718, 9338466116389304614, 4685545953421459012, 5059702655119414343, 201476627889215522, 6388612869673101372, 8357217932305360896, + 1836621694151238424, 11438765101326043062, 5537182303007083642, 2657011195641217678, 15370176245454161308, 1478361893117141052, 8729368992402422055, 4807782542738120272, + 5084555197036037383, 500829604818691390, 8128181767026348964, 17895639808733462562, 4138748420878083709, 267892430674902987, 8954358455330696651, 1946224964877667668, + 9440495138081785154, 17328162383695942099, 1870751290505230781, 17987066187778049275, 9952223038481207705, 10126409487298126876, 1181369784146909444, 8158422380540037915, + 13005094963168549814, 7254364757817833162, 3708127625424981603, 13214729399033107803, 14306349749849146051, 6983270854272831328, 14340019638575491596, 704963281855585401, + 14561080905697443279, 7640393429462623622, 15685656608213407004, 6317405842945074950, 4586197269496115618, 4352991463721324184, 18421865732314202847, 13679296167045126011, + 5024751682397066348, 16464187416447039066, 17561916915150311869, 1553872229528720506, 3971081625989469183, 16363381852589102144, 270446294712200212, 4668332646727035585, + 4623922898967168175, 14927682190770218553, 18082407698612059245, 8156136453512346914, 17256761355350416250, 16185397881787027880, 15277309552707416345, 5991448876439153037, + 1334994484802978518, 6876293985013000163, 4439518198423905531, 18287119869714109760, 10942138263490204506, 13981840082343935999, 186527448590996253, 11759869552919496944, + 12652601656062843187, 3947181446273381189, 6235196886760030384, 10531746495897900463, 13249616872107073217, 7937663398525899211, 8701780810784627798, 5901496026068341468, + 1059285256835989485, 18284969105568513488, 8222225088165109003, 1178299600673068913, 16068875143685216551, 17849596766342630525, 1648308197824141718, 6344465813776674352, + 13850247359965870279, 17391106451201459411, 9882112511974412840, 9027485913083134379, 2654737707750698953, 2829872619210764000, 10765067664204983675, 6008367494734883394, + 3596754664049660092, 4049565277418079196, 14294713401434678004, 682517403208603499, 13234861305501540306, 2878761138137340816, 7563571058666806838, 10752984583868770507, + 16399575624290910947, 4698193514990054887, 16222170007882213172, 6300376482027477465, 11587700570984519002, 4408509191665524069, 8909599698892352923, 15110169407475815879, + 13814725956725513903, 11675366986709837701, 8008867936756292473, 9627238521208818281, 500674066787171963, 7307892989752288627, 16701476208533897826, 13745712031279374379, + 14988991093658383268, 6586109441484875615, 1456715231981080716, 10587865765103526958, 7439504550868615754, 430398141621608230, 17710495017725824018, 1267747579289674850, + 7939033276966801601, 2952159422351169438, 10439776924885737877, 13630489377585028212, 1779349587540144503, 17209739673050012100, 4174716919431642272, 4986592555205663040, + 7110204405213656469, 5225260473696365908, 13544564684169074596, 10807318789744351361, 16301252682064971136, 5046748520130689465, 7049174921499294642, 433785658536711265, + 14622798677938552282, 10254953149954221954, 2609148400899865119, 8197897294400569748, 11784700166516996756, 18107483989994737564, 5332550435198791193, 13389061302706010047, + 10892870009313407934, 5709686117526627488, 16343828906887149047, 16063790174205876315, 9076070192754075075, 4639156357669822592, 4904064385440242264, 5942264027390072320, + }, + { + 17271984572727555145, 2097715321690717305, 5328035183708920909, 13206781766168781008, 5915693606819932446, 3870849056297265622, 18070792155150730518, 7786839743829304936, + 7939886940063870939, 3597929036186322512, 12732772396498766041, 13300425267730247515, 2345112231224079293, 12327614629296314761, 17106102937162407683, 1702694317559034053, + 8821632341545057929, 16708916351043551467, 9171560460858577216, 5711973041149612575, 15808302665077457285, 8412173943543358851, 12602476370021215716, 4778674887660148537, + 2707032230021934480, 14943945588296447659, 13333962501998857701, 10603744732015256400, 3386903941135274495, 8507451908469049716, 9231176235773710950, 995464562185179329, + 1251633503842168929, 8646405730060859011, 7525758827556699239, 12781503299321323139, 3762059070509735358, 12904588764985510882, 518456268741331092, 2752400776174997580, + 2965193395248314453, 17005383961540689211, 2510904953800463288, 14582093408745785683, 14930278391247460535, 15319775861672772086, 7915822626743762260, 10481055458185028303, + 750419144665626202, 4009275022270511551, 4810013488865977907, 13090697535304919393, 17408171061427940566, 13469810562978287715, 3952372983235223818, 12596642250700034956, + 1497127512412966214, 11292269970549257426, 13920714718237672232, 1363993524078475237, 3687544717271789391, 14097532154250414203, 8367320351336033564, 11089672460564007700, + 3927746316404254574, 9973240942982210953, 14122301504960485144, 13249357693517290445, 4259646940372475995, 13156585130751616020, 424701295260668232, 13006066175253059189, + 10308406270137410351, 18444509448482991837, 12509509048086126555, 8343613342319774737, 7902938427788958534, 9924925722974851885, 3762983399809982874, 3397026083592781307, + 2116063253535766674, 12792173758770945620, 11357854367169339661, 4502375174987631263, 11374536277081101446, 718846097450449491, 6555869089578359747, 8571702699293548804, + 16993953276024768829, 12025590727803527383, 2672535181364381995, 2183111709986676538, 14822521615475063339, 10618745739454592027, 9957515072444869664, 4797521918890127374, + 4582720743315312164, 18280419827142252016, 13380629421749133990, 16786942173448683921, 5929601960379909803, 6715621236552343797, 11192523517069751956, 228125323996215945, + 11861176681909235996, 830114321507110720, 13132205092670772295, 15318287322892364044, 9027539547229346224, 17629383881225964174, 17167841317952050345, 2169650970520181403, + 11366374573920831312, 81590945660392134, 3339836125719372590, 6176339191258224503, 13498384602634172923, 17380518646558253069, 6505222573402454298, 3404196177841425416, + 18097777493026370528, 398882723487597643, 10462164796529820357, 7704526739683689547, 12438059168025171393, 8163001730991802064, 3319372757738711275, 11518015261707325261, + 11235814273447729629, 17827792960634604769, 10951458440780869321, 13957342734404907932, 7344502969085321880, 15052563297577817908, 9276707332138855229, 16077312904856138176, + 10945312442787809330, 8353703025227023259, 2523779015225839136, 5997809042199398051, 5595238423081509301, 1901941038793828090, 983256298544496123, 929860142706986099, + 1859865867925261002, 7171610585558961405, 1708769301690637951, 1669524125723022855, 1126574755172968332, 2284167219201068318, 14925928881489847288, 4349400324295146347, + 7809927122217534998, 6003738786706135597, 16541272992243715653, 11352602417510156921, 6070703545889058045, 3742828100079104877, 9416263310824977145, 1406892456840131842, + 15907861713154660116, 1789008941779432664, 1086909323248385272, 5337878342158043460, 16405416607888113885, 8262005873603178297, 12775015438669465500, 18394022127507526579, + 9832954710628449545, 14612341389215489179, 8860090710725054989, 501948203387806263, 9969784653624607958, 8524029089859194791, 18028069685553315869, 7863046312587606086, + 940114737935470576, 15661699274328042324, 2496303902262203344, 17900779334646110602, 10928989106385540880, 11160326060698033088, 6591628982832414200, 12860480197090465356, + 4005088727670892586, 10215872293486093012, 7634075494800881158, 7707144163086802537, 7085702388211248163, 12168208652772836726, 16347414703478252736, 9386623607672009940, + 10720163442173876242, 185901255673735804, 189524655270248212, 17937598483325200462, 9672767027914841820, 10911520298114954717, 17238190140596785520, 12302850034563751398, + 1819872496749425461, 5856173707582412777, 8519855762092470428, 16315722646681962500, 11554620938156340375, 11822224388003836169, 8221825485736638318, 8413608007099273503, + 16265754830488408124, 13716061973016396515, 6050948709307262401, 7654402024031530787, 149712175032162058, 8319305312043679388, 6115793437696694706, 9669523344165801010, + 16530167766100505402, 14672843572926881623, 10752276706209340624, 6888427606311779724, 9060900993058482991, 10439396339124215720, 17640982730425880863, 12916411341252677116, + 13182242421100666863, 5267519287044706312, 1780278156705475292, 12839545421803851420, 9724873776343820617, 11742602593528879231, 7598735248774560112, 4512374343657017031, + 15080601286098047668, 6570749562833033851, 17494147260115946401, 4878559727303047850, 2259644365338981526, 4232993783633913284, 3035566741498855042, 4306414296080197928, + 3878740698199360708, 1631626027682263021, 10479957065093850273, 1678395573475248815, 9964111965340163993, 8992208313996775841, 8147773940555378986, 6205594793300838098, + 11776245660806714247, 18129100488268011560, 15389929343761297429, 14544292652959164154, 18063319363114104433, 13433144948667100183, 462314076175867487, 1862686058702915115, + }, + { + 17596113920958619489, 11920824479658301378, 3786905428099710821, 11112764289322906111, 8817260450068629272, 6518847791514184438, 14593687325057339783, 18018581321332807475, + 2056254186648603335, 12143016575009965669, 3290271983033386616, 4338404082685850854, 12660444972475266123, 6345409453044955404, 13278869140778657354, 10063005167581762786, + 5303950317664091150, 17409642188139937758, 12135894348302287058, 16444741243419918751, 13935885817311324323, 8496908197501732703, 12163317723288843510, 16891353436915314685, + 4168420842704770545, 338440394515115377, 2102734009665481092, 9772725684473416465, 1247616337419130000, 4222072446972129729, 4836898447189504007, 9154346000276664999, + 14649401370738987318, 10044081678892811795, 1306517740393103656, 16586067283450489622, 8211832777731897494, 12849393859171286949, 17327526552807783018, 14171704619529498238, + 12849053390245557890, 12693731077061619694, 5891211584023409476, 1008960642219209210, 15593393872187214387, 7381248773473326001, 16559656086795428559, 2106025108820858934, + 4347667984894353308, 2129883711661222690, 1076488804494872856, 15059968377755299195, 12380937310378496242, 16425480883270944108, 4769192332535557551, 10388305045430499744, + 8553482596123775980, 12627020622203381515, 10774788686070344669, 6271789114731522097, 6270586844349642345, 5584690155569770537, 9478526526319537174, 3405597782572827563, + 10255408065071335198, 2384996481315588922, 10679447117297819075, 3734157461055440416, 1635042286365643780, 11321809677772938996, 2373960964139986040, 4869129159740273704, + 16681657814739017038, 2045405432090866328, 9473434018957974472, 5549808619751464269, 3650191693776946828, 15805634549736708741, 16764187297356548667, 6849534466635874363, + 15295973549776084894, 8150873746601283651, 8017271980921908229, 4899654767305073834, 15257501950484641691, 17365331272978440066, 14582514748324426172, 14727798284858071666, + 3180828552573045472, 17698570278585440462, 8986722854533057232, 4518665117523514004, 1718699978312382231, 16973074530347269964, 5684175730451960274, 17228649521631238473, + 2897180423141326703, 13691273076814343144, 2967066815351306232, 1032540647518716635, 16365716239989474776, 9503666134295232767, 4599017511227366879, 14475021161770955579, + 4512626226592149712, 13575110216387069176, 13488662643497927183, 9673147324484250604, 143936220816719815, 2307325398241477161, 468315224038772027, 17743582630124600591, + 1476494936296433813, 3408612621327299295, 11632756669813257564, 14296719897220703576, 2241234207239321749, 12237974399755684219, 16253635131573079566, 11892871179872526079, + 8492025373682814159, 9341562763134230960, 10104358220305514878, 17545404790574939459, 15737064134098795026, 3880597485411313924, 388663918823974597, 15032915458906101183, + 965170717686924337, 17890763357610871180, 17588999527212997589, 13975763809893342952, 5109669798963414493, 7891916061794044612, 4789971769354067287, 13049661741280223048, + 13047125712251887103, 6463859133854403980, 12163714608926575519, 1018022589444930561, 1736262463418943433, 15665908585957261569, 8814123147308650486, 4798595000205497714, + 7506024921976923590, 5624217973379693717, 1727881279508834884, 6843292805721229768, 14721392495779901462, 15739256886195814859, 4955780690636679890, 7941019297099640360, + 1679075860853192334, 11512607379850785303, 8606478479964129549, 11355506676698290554, 8638706560448426692, 11314948425220125007, 192055228531777598, 1407009579456262795, + 13286048494307428802, 9003344338654830342, 14153483128501604993, 18443414499226619410, 1307798988667786279, 4422280407538765508, 1295189585361403916, 13026087054487841568, + 2784400402546744378, 15890015749743051151, 2721137876244951114, 5096506081391833837, 7797931926335359630, 11689452583898581132, 14104784079353186010, 3188967683935096888, + 11330231400343362000, 12540174755074499088, 10360616188128925049, 3458938550662172118, 9983547038346979353, 14986318734459319551, 6345635939240236679, 6320686366534231970, + 14746231842102190633, 3622710091833101572, 12626649920759262265, 7005023704205322451, 8825692535315999015, 4515463777365688013, 9604411949030284505, 440641657645532650, + 15551627195111259367, 17849357920181562395, 12870839822102241674, 13056924324197787476, 15109676201265834798, 12974964680406025093, 12841612415554457877, 2986633967268013902, + 16172780290314506283, 6024364507532794579, 11981052290745212925, 14235100278052078327, 12912505872017936022, 4228821405313065812, 2097279962856941481, 5542690235350104224, + 6815123236701278368, 6160442936745831892, 8260371745376005388, 715614132817606668, 7741929556783214361, 6266561134278568728, 13996537792746468394, 13116379830815883328, + 2212637711439965528, 14217650183061928416, 540869510933311267, 6195450915592159668, 14904187357299823445, 5215400274033728644, 6907285779833076435, 15804222685871187391, + 11124404141552478131, 15318338152189072517, 4067893425297764249, 1697503410612817642, 219476584157335935, 13106826093753036522, 13049745208482785760, 11832231199490391669, + 10493328169052594634, 10627081887813813659, 11388663495964140754, 1823051796271862577, 12476400584366298768, 13709148086980681224, 4023418280354022922, 7805776130903851852, + 11989040498741265687, 10985482710426001838, 598034896692782488, 12230542700168560619, 1496676485546951232, 6833695919100964828, 527254545105454187, 6276811762216173921, + 9452334891928331309, 15207477416486363718, 8081596400773698461, 7528187414539292243, 4773782664413845594, 9435822414884353799, 2722451711480791323, 13642248100035410269, + }, + { + 16570512961992288509, 15784840936011612960, 17797638261217375128, 10589124475671334830, 16848440972121709899, 697679021479737566, 1456738239410270672, 7214966028857473701, + 11434157439953722433, 9090860151661100670, 8407869262026581159, 17882547383849407986, 5277257988019769029, 11463853580825342183, 13607489835500075467, 16878800997498950751, + 16059297404709367406, 8426877510924536482, 15269952608796785555, 6256768900860981984, 13142655793714702073, 14566340391957173918, 17147065283704191109, 879106195264399, + 1169887957113173798, 4936710663791789838, 8029349457377894665, 3317691225106441967, 3622769674498678594, 1954144360900150482, 1432045977341997899, 934737636789214593, + 3519438486034584001, 16935008858078961013, 11197550931955434437, 14100007087636813411, 11096181469792598416, 1355325916242161182, 3003143504356161310, 5855778258533244174, + 3469569649879539425, 2734409579230557820, 11243101718460963222, 14449395552625174865, 2832531264658408884, 12736053595733579053, 8514265014627300817, 4646556172848350801, + 1035318057221356651, 16671259128991069733, 933190532640544326, 10073090919720429370, 16298191828003546946, 89465711115503243, 1726024123088964037, 6293688775358665990, + 9646181593082190523, 16068017411165381498, 13319927590045936565, 6113055520205251774, 5576373032696512038, 13880344501714804196, 12022206929479211261, 7387979357081975315, + 14353322331225872624, 14137906560696321406, 9597841809127146330, 14479164716385450316, 18390885446667453601, 13789601367024187697, 10599569472420906075, 2183893278236533867, + 17984045804937170919, 3008713646989855019, 11485907798025297413, 14380740919052976941, 3447658178143557676, 9095585806057103587, 698302327819557146, 7922185712178340950, + 12592522203651044465, 1491459000495558958, 16988036704095888812, 4620491143241098446, 3378886739158384486, 4601357523445825298, 7994566595487207192, 4507705687201434902, + 13553890993911526641, 1237937561304731611, 11053651340854998814, 8737874920379363783, 15414508226001886918, 9311523317130687807, 12080742822716708234, 4715194040021784977, + 11413808093931937231, 8917864246709968658, 13554307490245863526, 2827250138133094370, 7637229863299622584, 6947884496333162143, 4815638417787805223, 10291803792760846879, + 12634048591085853546, 14321728045924893987, 12328747445286182403, 436433860116637979, 5910966881246245784, 11478152401127002379, 15956760875311888867, 9580341487614973173, + 5405380974793160831, 17240616607222875763, 18407061562244315632, 1777973921117407170, 6264824459040652928, 18267228171835175724, 1278124974392461846, 16099414790431742315, + 17182132836049601530, 1486820395924546410, 14089047182364760490, 5375431386740917568, 2352352269256972682, 6220398075470064021, 11444733678216077372, 8173002234516562536, + 2862732059898640615, 16485439906762588046, 8431038226899400253, 8931540904642954995, 792388953489761723, 9296018986570869365, 406447163304028453, 13270392174836298982, + 7772216409762031099, 334915652033124323, 9705063888720244418, 9829080877134570370, 13800256788887079067, 6121678265481939341, 11747955988727867922, 15561904257519022219, + 11919247213871390231, 15058232650937578711, 16509435050946309716, 4585646383560577121, 7109079914182671169, 11070600764446172401, 13212464399509938674, 18057628120939602025, + 7896339057146013415, 17613745684396593735, 4238258305077796259, 15438639564771394288, 1482402451684594916, 3104492350488980260, 5195487229736262641, 1361150797580203482, + 16473144777827648385, 1226441665397311636, 11587851779002173636, 5723433682141598491, 3818559725806959172, 9177247615754603193, 9531025756553277601, 1716800965379459594, + 10276432666086031385, 14627452075834666747, 18000674623336885291, 15328386422432799237, 18139556051577750412, 2213209867616444127, 9597214736611625280, 2458176131336755868, + 17117806110792423322, 15887422186644000204, 18208397717053970445, 7361598408210891485, 13818554723430207838, 12816010025806087198, 17883064936092688211, 1716893191215908273, + 15949855327936545010, 15892613064802301412, 7776232754624386979, 2193423430757249310, 10751855334513902678, 13772090376350944100, 5644047706587449960, 370992037484721524, + 10797607675141630710, 16625594903133516890, 4419277245854893028, 2258389314023537326, 16758443963306613299, 15289730903996513589, 17124263661185245991, 15862017582286958991, + 12272869926038995590, 4569089761627301260, 6495211060884501138, 11124576322292919277, 18314798224925096163, 13232331582712038213, 4402693571738173484, 9384301049965683996, + 9611026793910805538, 11152002731283498747, 12528844591327054806, 1485961507414531975, 12820893906402770618, 16248407567081091370, 15794078730898691457, 18231302945982292403, + 16329953561108738383, 14553061366216182492, 5112198484879130320, 1893048255589705004, 11469678860036344015, 8992526488267920066, 18208245559304821518, 8980963391041920447, + 17694621707784163170, 16317870945177246022, 9173265111786762052, 761657177655159269, 4876597178189658673, 8185879737091523833, 7520213092991049248, 6827963030155074898, + 4104149897263226969, 1008830393844825523, 1692548451180187046, 10984924503299463085, 3526468436911084942, 18012043951628458646, 15181223987778535698, 18016160796635284569, + 1524865955503524054, 7479709667052337482, 1064851658558537015, 14404181438374010311, 192685278892740648, 38546070651855709, 17006752915941498851, 7120034574635007914, + 5783711159088718530, 3503029393593618754, 10736192136662142256, 15443859608128978668, 271805305647187927, 8244170003029416464, 17017071503038388446, 2536084345379259313, + }, + { + 11535283160083833975, 15102917952496589829, 12909095696891909745, 4611119212602854744, 4195756524232932570, 3754603965149529000, 11539276962358607816, 4401424391553230481, + 6842993463058627120, 2708745114617181146, 3832382691810282630, 10333834458057320812, 15028197197004077388, 7681293343255119354, 16227537691626587485, 6703363869832495607, + 17567108285065737529, 8693245930330183070, 4025672038042952121, 3491067119247522844, 2100799837993193702, 9579542950705774054, 5091525285265581997, 1806757015709820088, + 7757354840118131559, 16227348978414023262, 5800861674805516343, 16486235803248700961, 15646700163023677309, 504258765210816549, 13724147899924699697, 13588899538317277096, + 15895596198730294923, 12513494396374459899, 13552575153453342654, 11312160635199213507, 12446618129881485796, 11286186116805515445, 1584191291800429567, 10188741008566636830, + 10157626021970320469, 6580688164585715207, 17158416694471177787, 2873484006255074946, 14852216457444863041, 7463041347566136496, 2190030775722958628, 1116223035803602728, + 8598875756176012541, 2146658618778432566, 17575736667490551813, 3602654209723135985, 7223347129734689099, 7256921024940026570, 12249118963297692963, 18168532365040819099, + 7585174044375463988, 2491923406404093282, 9355733262044036112, 11484079611349577325, 13145030009254943291, 1234932884591406048, 479845670619308618, 87735010308690865, + 17307641427543377277, 5862898330718319545, 485176909118483750, 9845223919324484076, 4293549583740204024, 12765124043303931186, 17870894781132657382, 6508172378961793849, + 14234156373312856400, 16210939788814051708, 6478880037923038392, 10435512103812909561, 18142844321802359753, 3243996803126554757, 395603619159523019, 10213589535656704607, + 13256075137060741204, 991285459654295161, 7857174835799942102, 16201105040554625727, 18398612085349994216, 4512860776717176840, 3521452275695011919, 10622137733045360311, + 14993897771652736376, 3320388672992783302, 18421556740970114213, 7438967127794745135, 15048397725789819354, 12721899159423777001, 1135125102123667189, 6637485660805148630, + 205606553319362431, 15484041062449893984, 12896720585684759529, 16675624014916513672, 7579112430564108390, 4602460356900251082, 2677787525524280838, 16723483619407414479, + 17981939084373319995, 3989926231875116241, 15342509934701840045, 12999252495311233519, 15389919024942778009, 6136335679373143315, 4117381415379544275, 13342256463740646775, + 7622769999043907199, 15227992053145045634, 2719412067263856950, 17811161335980566241, 15036003689029442301, 4919601685231030712, 6756893600905532338, 18029567067112075531, + 15804957839814547154, 7924193945337173678, 1080401129055171214, 10816444561878528576, 13171610473229361771, 8099842733764406841, 9284741070210451667, 9245195215372025289, + 7352706423771400643, 11698139248518535945, 12836997796963939813, 5747451345763534394, 7572033904536738295, 17752330422795919668, 16404760947165813434, 13477251724246705199, + 13700661979310397040, 11172816633936827025, 7087232997755437759, 601317374152115944, 16028751590837491967, 2749566595186093629, 4445248645671399873, 14714182958477634997, + 9630153311383545953, 6436885924177487891, 2150319761793765423, 3799049242167098053, 13902640603080497957, 13121685068446422901, 10099985117244683905, 10692630753099650856, + 15680946025356791729, 10935239212262708062, 15255596602338430716, 15502989798538458360, 906862139952472300, 16128362872146694687, 9038121313842477036, 18304772087255114926, + 16961332967315316395, 2872796507989583018, 18145413156795763341, 6377517922859730669, 3543621377523624979, 10701607653242580646, 17747200374013876449, 15987594633077120628, + 3487728992359467218, 11271201736509774853, 5968332690756574092, 3519182420015237550, 17144214368301394415, 1805926423542721773, 13696269518209159134, 942126126861202483, + 16211326119697754410, 9043490763746629445, 13119640043033532883, 9720862297941999125, 12662669665140843415, 2188499520755532048, 2671631563874698813, 621164898587943254, + 4804461736506692241, 10698651491947798952, 3524135800884470917, 11451653751986650957, 10424912129082359813, 6912080226482239953, 10357808719970986526, 11757540241185558439, + 1841157911016607198, 17522398974331009019, 17392843956059453556, 10510758656389762948, 7666344868273530034, 10739409534839380580, 18010518965344703872, 14478457810678500914, + 1617286442811984718, 4008909641875477702, 9328654790542709745, 12015676532404599710, 1763241944305573436, 9348325841675336084, 4072126498552363080, 17245688939115723821, + 17277555838655940279, 16604852268187595492, 11674181070138727191, 9847423407697994070, 13562477602392929772, 8181792789545038731, 6999326623175714057, 1227784795779857129, + 14923095901189736698, 90760593075377861, 11732533481504731510, 6000651333412910877, 7847865090059184838, 16859539404919901595, 2709105957383645337, 10263820965340474390, + 3161036642361826348, 5744405044938832483, 8939741099437920817, 9766097724147073614, 12117283480449144394, 14632688836103128438, 9491651214417380913, 13676064073123352224, + 4673738700738845848, 2758750364605631228, 16596306154038523740, 4124917668203310922, 2170509910405778957, 4178077301639210933, 5109055439238993109, 9627760120514410208, + 7259236533647228872, 9608619771663043870, 4148523959415435806, 8831501534166306825, 7919036824652396994, 13625969543100731176, 2546426055029800579, 14852443398434563210, + 7185947197544988797, 13306809398790059447, 11440959253278285287, 15084384140482244570, 5059824327869316332, 7585354587200615362, 6801884469610571467, 6427162399794357267, + }, + { + 1453348772281274490, 13028088570940491471, 16100623112750251840, 5210244400259879874, 9443916155735416174, 16869520919318450506, 7479400208826706574, 14374970913352602458, + 10149597276931117465, 5778043705364022356, 13888443605241209218, 6889225091714429810, 16209363638493043975, 8516350006446457646, 9214830076046105138, 8894115046323798175, + 13026208197163596446, 1935567165776196957, 17296090833026336866, 8461284827078097590, 14545382879887213077, 3302103559307506085, 16026840048628844803, 4599071908983273604, + 16375505785562641226, 4903074653735993511, 10355787845763031761, 3188849033041803587, 3145147452182864049, 13878747873108378466, 2798650520315922121, 2325962694441538199, + 3587824003578414733, 14942115314012282784, 5312737955169054323, 12478174640832111702, 7866537714619856949, 1076672758151595875, 12163513815501875048, 8343003998956997868, + 1392855790923554429, 928317148609633070, 18064469091536763974, 13446092366984636072, 1975222540660444795, 15443703204026028192, 4016450768356916736, 16656367700821047808, + 11505659892372808762, 10322665279031813234, 16948868760451861492, 13706671779256832515, 1968671033447691229, 2446599110590827903, 13721045634744350023, 11053432744256776013, + 11530583608023224967, 15979155166527001287, 592931868138800645, 5361781029549479856, 11246418752830406096, 11882251984248471436, 12026389461944629423, 12289077922798223820, + 7685868633977346753, 12528120620943035447, 18394735788313062922, 8523101916703102094, 14261596878655792929, 6364753027040158382, 6433482955677830548, 11538026548937002170, + 16221339092185577802, 2285289075757313223, 1151823739515800834, 1010537560193450047, 10651328720714490261, 426599792903611671, 7181136719074122463, 15350479907287263858, + 7559201271967630136, 3561344874280275357, 16379496429080959327, 9662226613694502966, 10995850494788192620, 14875349277152338391, 730989400822814422, 14352408679782573731, + 1328339467113622233, 13374824154992864223, 12057132015324007824, 8507647484414695512, 9286016370798146986, 9083798709648036612, 4312959727577073260, 3732271624824420608, + 13007262390446754395, 5631627784562092966, 2644488352265945851, 15340614364643014664, 6692152810984634488, 3903120388658969320, 2513009101887784188, 11999681442010831364, + 8301343575202991577, 7108394080005777057, 3477086484634015274, 8772644795325835021, 14747670046873500269, 11068536909552811695, 12349879357573378133, 8898863927320049679, + 5231654281125841638, 5181061730027800171, 10657176101406080919, 2548241936122768256, 17140253194139059526, 17961047717804458883, 12407260567549658707, 1464243167234637194, + 14129872794455315922, 16354810591314135702, 3177417010197743958, 16494351130927698692, 16557765056328447818, 3139394196704738651, 16891813998271303650, 7374470997276173905, + 18244279644122204437, 10097660526910786400, 9270181538098732492, 362243376823712218, 12369863141977485111, 2550957813014523686, 7768963959853738595, 470330801228165919, + 14632133560934390222, 13844843545192224059, 12232948338847787315, 18223343336729121487, 5219716370019749202, 2729037467284418866, 4546118556621109595, 12191675540034649671, + 15868991745937371466, 12686820201922367283, 14799186526268126508, 1241626948050017911, 7080072468753824165, 10793537086099229143, 7855065677501047369, 9747396305344084667, + 1547814412223404746, 14194709348405912167, 15771028929623393801, 10945048172868684389, 11234483878611528405, 9542605377580701681, 4555391547268120796, 14916872217451960022, + 398873176015355134, 17609838001051405497, 3752252377312468061, 10441993652683449973, 5218696730429184844, 6514361533063264268, 16024112124035725701, 13453525984055386124, + 3452753233449684767, 8937677805622461008, 15346651759545553711, 17055791435062851045, 7025089132368408239, 7345356702153522862, 17760529714295220737, 10772604293313163303, + 9940223451501501487, 13671810088603813912, 1432075826781639138, 8145669182511487125, 852664959675237493, 11640273224943853609, 16220508798123490173, 12787926729706993802, + 15490131882364039637, 5140304620645573547, 9403655757498826823, 9824850954989176893, 6366139388903157264, 1981838834216345294, 14659870286877979556, 12091578124492612524, + 9672198938588933438, 1848525214318852627, 6500329435429402369, 8547555101599185897, 4282139019453982058, 13391782461875853462, 956960429753408730, 1865393350316759140, + 9155847368519787501, 17397005067762861574, 9943535970799289809, 16365250691105460494, 13595148040475375224, 8300668237654861875, 7149654787413440141, 9226755501324961219, + 9359301870380673800, 9344500253098672841, 282669288080771734, 1996492472861301505, 4777949892950526502, 1374151996531969836, 1529729047243522545, 3371309923165192567, + 6832171775190531128, 7903951882621813138, 13717573220828409267, 15400575122727850054, 6101307565293576434, 17226772767105983314, 3485283905347036760, 18439321272895583847, + 5095761409418784463, 15484673138064200869, 7743962634971666154, 9119597914470879266, 17978461537972396088, 11490423388734028778, 6537551181013090408, 11706370534703673937, + 6635008658379780815, 11428304571924124070, 392068559161657302, 16314310970878215293, 13769492864572584674, 16880907685897496637, 2877983831559338706, 10391660973242662710, + 16861266984653213659, 1968749328591656132, 13301499995824894911, 14523175695360471336, 15130688872832023531, 1794208537894703529, 10525607764904270704, 14288604199111912452, + 6289130721434350290, 16129337673129720846, 6648351866142453445, 7705983837166554199, 8120136556582544814, 7924417299222764443, 7821995671300500892, 17697662726179084739, + }, + { + 14086745261650819748, 17953107869776717888, 1777725846494438428, 2765314406831814212, 2603997194371852991, 2223517025105045134, 15579901335531749634, 6571733615332171148, + 5478465698516556930, 287443454357750768, 12201204663663129285, 782849770204658255, 11270045035009204251, 18152683972363144337, 10463300037926642739, 14363641589598863851, + 3790592075869665284, 5120320091554329756, 15361581282394028709, 14360464660911164915, 15249656958991931940, 2563751872827049233, 13745792006936646733, 14572943674933168173, + 3167679014977537749, 3417445004776702290, 1709246158507866266, 5861367897285174360, 8437429877561342262, 17231607446243478748, 16047596399306766948, 17656438585829685897, + 12977336347094692192, 13723871955002954132, 17399919575273038847, 16163973860244779675, 14997921584659740746, 6543247361992425067, 4675926398794487109, 17580512382853194054, + 10778828023580771765, 9812611440536367405, 14168149065325522570, 6692229110872358750, 11010962724400581057, 13055203605065073902, 11396463140731730116, 16969789651736772232, + 3285258013801327520, 14114268241282882888, 5367399533198476395, 17277410244918727028, 2751895479568588421, 751309667192066167, 13038472116718581917, 16013586354334596135, + 12364168614988940500, 13194367252463423118, 12223406606527741280, 5014139294736037086, 11244699482831816093, 5336498572491451990, 14268404582568856142, 14502318820969599316, + 13295673091232554814, 313981772853781347, 11829785736449464030, 13341198421333360997, 16787450350663111566, 6525407229623764159, 2012189087039636323, 2110887590404698758, + 16984895766311549717, 1057465499230843916, 13565444352859773343, 1019268943988786852, 2190009140530404855, 10045598732295352970, 4789803496780829836, 10700158388954091321, + 14840255112988420500, 10066628133368048408, 6527354835873855384, 16106607076894419125, 3989024604987083046, 10713316697020150694, 16811389107269552264, 11294596059797019619, + 622403023838932676, 11423409007234191765, 17086830255702454786, 1213655124481948199, 3976593910085142945, 6315875935390432543, 17947502153968859628, 18031540937011531543, + 342675887578148289, 18366454547938469828, 3853530442390999217, 7499455395579634652, 768597405171336502, 1636271570683567151, 16786205337983572309, 13056241332863199715, + 15991153618414855143, 803325462494472241, 5709347424437559249, 10138502962472290727, 4675124205115228106, 9599016746550345197, 2769443894695609085, 12311020551315051087, + 11470964304318784059, 17313372553735202469, 10686997186364536871, 9228453594798060121, 57933324335302024, 8931389936300346353, 17823596478938529898, 1126996688113949835, + 10457697409306668434, 7830477435299250296, 7772379952622394912, 6109610138112185532, 4382803614711332911, 286231563340803504, 14408860285425706036, 9445290615796219321, + 17536503470234411585, 10755841521760916925, 15905055604395954066, 10842889504280336728, 10780689817551616331, 12490302644719656914, 14399349211478895553, 6458867531104408547, + 18263696007238300109, 14344529985676987842, 12351733186419515951, 14648750128188787544, 3817061805140294292, 13460439592176294955, 2651602395003150964, 17613970291099197676, + 1107162420032075035, 14270134754120385897, 4090584027509443635, 16066949131129832709, 10961641187652236678, 5480069976143996625, 8549185711954755645, 3125346629140152790, + 18337941236561689695, 2899707239319273137, 10519944305927777790, 6913088845356962577, 13796383125935684169, 2756403850320695444, 10018647980137529204, 15185795467001072323, + 678732289042224133, 4682655677430115166, 4806112367076139288, 7101473987708012826, 9907594813802528406, 5572757906434657546, 17819688309930892783, 8734990255058630746, + 4831187103439262344, 8323117365987697459, 10690753367486223100, 8744079000061869982, 12737295198832254982, 8667406752954112119, 7942221205780634447, 12612313636795726189, + 16544756691464009983, 3413196415113664237, 18442955254149959801, 10193439941306925215, 15178607176290875326, 10962146035584651400, 11757614026658646304, 16241528460556234026, + 9593194029396792148, 6376573619820601945, 14694667798662125868, 473733746941891591, 662607401339043361, 12105576520816361855, 16629740468317868384, 12416206001206121129, + 6655696780366945398, 12313066500177107654, 15308290012322636383, 2159880960357061128, 12374858353753840133, 11331956329091160239, 11794840094276473821, 14170553661155653327, + 3336445037682266403, 3746885541049520962, 12688476435907418892, 7399089272376853858, 4625608774712059624, 1535040330210000507, 6878676093546636363, 14533846142831376645, + 6250279356724130049, 3901672557903829499, 4884397030724371499, 17385695093365573379, 1240675257703364805, 9703149291204612490, 10295741452056015824, 7249917314998921510, + 3336800790505577062, 319907795530586958, 15852045830964927276, 5538471989976998401, 16558766045222360422, 3135574045680866961, 7590873965560972285, 17191236425969884848, + 542161999237385999, 11197034618748267807, 9595673564043235773, 16351524685431643264, 17127456926935032059, 15448416181819692483, 2035065584045934249, 10976830957530152324, + 3230012351101746458, 1662948417350421518, 16062645290454019168, 6021730506322388306, 9903225699788133023, 8549278993611431648, 16267339446315716903, 9759051179942016620, + 14281696762614162345, 14970002486407845832, 14940104843292093805, 7021313216295048550, 18131586729996841512, 13957742754718859034, 14322894803959804982, 12861731196696133597, + 8838210194055479741, 16190279688839291456, 16520121358582757556, 16768959728701970634, 17279896910204983538, 3582816187015369256, 372137484481226748, 12972230207718993241, + }, + { + 11480031272463364121, 2525856087688686375, 5875255653057452580, 5606696614467440464, 12094715534218447962, 6173479337351577758, 18244015404482482803, 13199349349511499695, + 6097225965006328457, 2630336000831717722, 7049638698786526134, 4203465038263485233, 4677974565964393904, 16044036678123636261, 7266049959100300634, 11339674070148504929, + 1979992348876614621, 7494083465935166973, 16035723662722831744, 6820849908885211777, 16740735239901023053, 2017530162004533409, 3087262288875984227, 9072904925376793991, + 1830819081327272165, 11951292080860646547, 18002500803418629938, 13317986695217403840, 5005574200470766330, 10138179785738652504, 1610518863105278224, 13309443265578956954, + 8383241685301818332, 6629521234420338478, 8997316634951392497, 9976633096395028594, 5171570735720385772, 8129153749198218776, 10596302915145665067, 3726383961188926740, + 14494271933981109919, 9056473564311980628, 10557807473422306929, 1549747977888697589, 4534184223615087698, 12977118933167042558, 11930457930026683843, 8346041661496792064, + 7756665146227128459, 15140824521273386708, 693427108108819556, 14819189462601222526, 4507393341357475468, 8710020646873218244, 4535796033535410044, 11884504632761707946, + 14192194428653714479, 11578618567931657764, 6032668189933768881, 15981535562386193924, 8925792218631314923, 9408714146004183681, 8859017894477140398, 1675606340537058506, + 13447287279335601133, 7792625320709870803, 5347956615552953057, 335662974452886013, 892825083599137885, 1017154417323307505, 11923254597349925339, 13818364932306372202, + 15945578153358602744, 6304522416189552358, 2545503746231186920, 14563857419242252397, 9711931929315762229, 7949505077082864287, 8780199792032437102, 10109661610848827442, + 1628958128919487289, 9818701341087940523, 16480240737841185501, 12633108361335093100, 7982147509828265471, 17959437456356197928, 14370416793872407673, 3577532534573396628, + 3265119697568866078, 13753322853248061974, 15435163376825672274, 13646180516491714938, 15620545622955090250, 18241486585498394565, 459566729126467878, 9728217493753855944, + 3187267754295885454, 7928049460349917700, 737484733736740002, 16459695106656291329, 13000947522838718027, 11933371771659873912, 4720706464557996274, 7997020276574823784, + 12655797542121172150, 16574741514838026101, 13532097913031715162, 13578832971779600350, 18171552525916232035, 1516234640889581592, 13625693062693291889, 3869929504544890755, + 5134589228918179333, 5186584327613952853, 4114726195152833642, 578924708883784650, 9128473117392713984, 17390547319520768186, 15077700332150016764, 8707446714183162237, + 9883406233903270985, 17184231210468300584, 5498903678702785900, 6903833261382863389, 11489138095102981636, 9021901931786177471, 3227433089132150317, 16639455550797627042, + 2873811051246262545, 12759149028054319339, 17920917684786397179, 2576455203420292139, 3181713670456310447, 1109589489775958300, 8920119044838278090, 16056330702164227666, + 14277712977137303378, 3896132440952049994, 13252040000848248790, 7844779060499908154, 8651912177362107995, 5527615699397299219, 17688189207278018869, 14560189235973121390, + 10861951673021959044, 16820848382034483641, 6761027571816469843, 3555385088072119757, 9363319138244920099, 14172742116400795253, 9535965929584057049, 15628517769546199992, + 839045372102318861, 2032615141683118500, 1921816835840256924, 504869150737570005, 15932184001422473505, 7849475855313305697, 1189994394722618598, 9874798350548229684, + 11973862230325381876, 7670835358390713178, 2113918814334481709, 2289514490388170400, 4570586695077036349, 9449360682811675838, 16506880875578470116, 13723444740920888736, + 14210428465641691143, 15330786835024186142, 14173742373807858721, 15041216914246450688, 6027140311333696225, 17929849776014561356, 3955935517651718925, 12080548003455651805, + 1974142217308765297, 2347591555456293560, 9029256828390326937, 15561672734848339972, 4719329765359230610, 1924866103348851009, 4950258359754995181, 3245952633715281425, + 4636201671610663345, 16662311204732135584, 12398897461787695675, 1355753199357412657, 14695655628527768564, 1692838776852698754, 7346906782826540912, 14869028424564984700, + 7242751356102425321, 7770223857340282376, 14976092066160539655, 389604327668352376, 3472336298605227213, 11456496863560248128, 14597769228654187922, 17838672631901123288, + 10997764239928568735, 16648935573721932916, 13735964592293716412, 1364388817619955667, 2511134998006929958, 811167458534120344, 9371523327214092569, 9359553283016173792, + 15311627918891973770, 17170652974122329165, 12620036374776436604, 17439165699070911984, 18124482726761033947, 18390083820175794165, 5492125340791896125, 16506113603670143446, + 14240080119980315297, 4751983902385717684, 7941412103662252178, 4796803816695225123, 9327986654018000413, 15111345676387005726, 3582558555283734415, 11913156735178831102, + 2000999613038609412, 1070613390669459171, 595743672188217500, 9169968884291187666, 17960105939867090032, 13927107353795575459, 17872593051171658925, 11087013461789649235, + 2280207936513065312, 11704149285124951522, 2138093032627822381, 6816805886026674440, 12141709925796155041, 12164596600353477920, 5711177504477877148, 17211856235678509153, + 6061025098309340877, 4060747063380827182, 15186975689243681841, 18380882388949786706, 927262408801716090, 7447789770541113239, 14074172896745727729, 15372475239996145400, + 12915868875134296756, 3071143582305760275, 10848717856747030010, 10973183887638314967, 5983269487036236823, 9885184706933333413, 14509493669845681951, 9669608065801379977, + }, + { + 1190044221726873109, 732025666411072563, 7781096808432277694, 13079879637655900365, 9048680577986693793, 12528346194104542124, 10575369576322629835, 14068913038053465964, + 3297775431071502652, 7947266993949467566, 6161673381820779563, 10604626734847205996, 17669018066064502925, 2386071939136502354, 1076023928806956187, 16075459682742916440, + 12387028018538599950, 5791681577936683396, 7536922194386052138, 15377770247350254336, 6564316170002440575, 10629371267149545956, 16125760269901494382, 16051398044897962024, + 6237354803374899565, 1782400080026955610, 16115027077529639342, 17907259814836219524, 13179234383592426160, 7302978467158243198, 13607720993463749225, 6693531817169120736, + 9659467198848065929, 13765104107473534739, 820057324758632016, 16604163594878267405, 15321524555426147294, 14524167419333362957, 157291234996957911, 3689488130722730671, + 13896531645245568605, 13598412639648980920, 3875086557856143664, 9242105512956135595, 17410265178284161091, 14904754836127450463, 2354327747158525902, 3858493849578874654, + 17288438225198818690, 15275190140700748774, 14532856272428522409, 2192294551011758591, 4275966798014984695, 13252812474545742114, 8604705074440591847, 504054699541924162, + 3623027910997185067, 15957466839356832933, 3504133700071704955, 4135728439139397021, 1160600455691338871, 4431928072859292239, 1542956305318065546, 14109181184369694855, + 9135041378474229537, 15626265487594878380, 2645257479784082878, 8105679948445763432, 8579715781576202730, 13437359533149316300, 4344754720520585005, 13326372852934103673, + 11341622086474305983, 17104958945811183278, 8154944722722765678, 6696975609844549775, 10895966360082878017, 2277686037575837054, 12236842881540344526, 2086470279064067791, + 2942668817124399651, 11439025398519255779, 17477264434671471242, 9606507094132585461, 1771475584689465869, 10791261379080046759, 12901998265727968789, 16423426725595035468, + 555419805011031621, 13715683285513290290, 15526654591995532751, 7023761423093873354, 15093366433178982304, 8625749648874372840, 6412297471587129206, 12161114204724955762, + 9362623422820895267, 6491356159483508885, 8543224082493101588, 17290929683278258587, 17348088672546490894, 3323350644823701753, 398525379151271104, 17794417664139368677, + 5880914635028486784, 2898124605786107494, 7953506026198179840, 2189477357380899574, 11207122442953694293, 9288539232660208671, 13527697625010979453, 448462453367651162, + 11262205719433170585, 7539606872920196479, 492385789142086954, 16036594120332851267, 8084547797138041354, 10063336189771527714, 2484395715469739911, 4879298610504146231, + 194633990068625151, 1028128699653523895, 7436102537486268753, 1855520454959348468, 5098690958966904466, 3342676718901330604, 6942212660412942406, 16510188838209674083, + 8847926418142642416, 13342814936333556870, 7082971165114489981, 9307541560233171550, 3013250253632606412, 289291445038948658, 2146586262066552853, 17331519863134074479, + 13747350589043267381, 6342477793304440894, 10087817302474912962, 18076409030930122816, 240893790090129194, 16364025156922886538, 13518167316464590136, 8034023137744309866, + 14013962864860194917, 5900268096329749317, 578665371390927342, 1407477069341362927, 15142181569643383319, 5217173950329651840, 7999234477517614232, 14722759409199120103, + 857809728583972424, 12785911478120621636, 11351522624307635957, 6288237507210579634, 15030282678317951238, 5521516375915920991, 1243458350248005764, 3567973108073272461, + 2834660673354035229, 10728451420162645120, 13396052377701115268, 5730788601228223475, 1616452754395208882, 18236419625072278846, 1179103743668306981, 9179882267624091153, + 14087439523312437665, 7814060325531094731, 16777382811045908592, 16916500419494378884, 16312259370378381991, 15848836870251345077, 16352246673954213424, 5228629139249919486, + 16889782864065172884, 4486233301301317202, 12424854171669138635, 12490430652425390015, 17335301435940798099, 9685877269515541824, 8728054940414220990, 12781228698496150916, + 15949574575791239459, 10394047428873141717, 15915386168603191086, 11400139144838475744, 17198578050070482368, 10505386377385262682, 11269920026804647377, 6796664536515856824, + 3285292208372623455, 3132524240856145976, 9712372580979649457, 10523781046601368064, 4797168047433466290, 11748687702182632788, 4177442610271848350, 8549047039673741703, + 6897143822689085584, 12727238507037725105, 12692443686524496083, 1187606781546544862, 11016254758711515442, 15622643445771261724, 16669571628491989170, 7099030384210775042, + 3541342827520921014, 12596176563952906070, 5209816272233406534, 17158219989390045881, 9096207539532607151, 12291463442559161708, 5188945441827912424, 12721126884401346746, + 8137171114112655022, 6980210601071561830, 10156197453074241467, 4481350962546197264, 1902625885079226055, 18310954340184922140, 10624840172920793227, 121304340390125189, + 5261036238619130144, 1418912875050883205, 4741122621962383610, 17995804738511375239, 15493968366750472633, 8417505178158780382, 14685111207483504618, 9729483826733360559, + 13434828863770210135, 2940287993177646896, 18241509923298296610, 7613631401252601295, 16815829390381900683, 8566309323681786413, 11094402941539790077, 8442864581771174862, + 17650059733379916650, 4260524072883785227, 8351659371377110706, 710338300032970720, 5512358883882849029, 15533759462039713914, 14352344066268876816, 16708588250954382269, + 7963995066277321795, 14986230345162551366, 10616366460602472778, 16186943329215681149, 9522855644164647723, 9858336437877021178, 16344942402271072884, 18027353494090590022, + }, + { + 13175608910844763921, 11168387468381338510, 5555873864224342205, 17780559602571640345, 1582669533588472814, 8145133762789622706, 1625372887980692455, 4576809104068554285, + 2900978533555060931, 1749946807863203576, 11705734511931072459, 4446980691693419424, 14437524160594907241, 12795912566640000773, 10400036254697939154, 8356113088668925361, + 8900726473285671992, 890209742292473781, 16059468388719373167, 16577940938542233221, 17381766864962227733, 231915274132518769, 16477817024012878700, 15646021286310268545, + 17511864284462479051, 4391315454785363822, 16633389246499252566, 4290325975494843430, 15912670649662225191, 14172733821603328367, 12709802627494541709, 9648238681838878635, + 4196883387800999444, 11261069840079702254, 7135968036494594517, 14537849011631244070, 1930221875891546479, 3029378442249928630, 6219774718328347890, 5922417028077454069, + 12470404961188516783, 10420863874252801995, 1369334550763670666, 4781925915058005676, 13086538845357988031, 11031029468188842766, 15252022305121561855, 10497770692868889659, + 8808726441417268278, 8201526072266158452, 1136378216494101481, 15014143365043073153, 9752793532008788265, 18423606089906807282, 12708377698545978413, 13697405528655748691, + 12840624483048662115, 13614226123606379619, 15087571995173849344, 1395488309690794621, 7173958427217959878, 1198561064176820332, 16821886260165681626, 10019479169661217935, + 8089335244564816024, 4652396396372834438, 8473523796721514770, 4493469844513366216, 5448577418901909194, 13487502520341193870, 17978888920023381084, 13125222810420128122, + 11369140159803973135, 8391820975236191093, 4865145203995472561, 14899728882581231165, 11169032718524058736, 14532440521453562763, 7464998467530340358, 14981246381757614771, + 1242992129726403300, 2014928170416925311, 6341058783517690890, 11690291498253019630, 15951586247597589423, 14033993236702971559, 16963725291567059464, 15075124616754319226, + 9901328250515532535, 12796305315632203942, 10819069447660403847, 12542238242508661240, 17077777737462854238, 4364294351375777648, 8335244153165894685, 8863541604979427311, + 12648774127830238318, 5576880401343711606, 11786867566889606858, 7421038047404952574, 1037620897405863409, 16680872357246325645, 10443290127564886223, 9718182896013830581, + 15199007294286606824, 10225517367964809030, 12827778649823141649, 16046039393887815140, 284741135347255597, 4015036609703147909, 3902771329647468314, 5128707935422024078, + 16953148044626345363, 5101833106541998042, 7655361325113312133, 15948906743291877728, 11619404274756349415, 7521254459857915559, 14978040810149334918, 18392994517091959591, + 11029520456752683158, 2297291237551781454, 7934683676555855479, 1563954733146546128, 2252805128528536255, 10523375695822939112, 4598652721256818062, 17493379105069761435, + 1717382065475436420, 12444276194160330384, 3605273785657402256, 17503422605669121015, 12066457002913396306, 18109827202111882684, 11555238022219952400, 1993655497207863497, + 14852223665677610379, 4743851404709775958, 8525514757892437524, 10402777181498591725, 17096034999928466604, 4289543339828736175, 4306145672261807290, 15366124999227707930, + 9159996652502914864, 10301349423202296392, 13530090903323000632, 4082840779249202050, 8824726775176314063, 16033767772359951785, 9181204573557660412, 7582747879080399183, + 2747551692916263132, 3151123035150683281, 13938314333309683791, 11970864255483579560, 7894236725861110998, 10515613623232567716, 10445557830757066839, 11155097727742050955, + 511773909731247800, 2463012923954369656, 15859141716591041471, 4940781664379556792, 12435624343534748284, 10278084527750129328, 13178135781125832492, 5930328346313533490, + 9122100956633732655, 4007876149211873275, 8339438668849688737, 7791075492023424820, 1771434463088769532, 17441254147665904787, 9470298561063283873, 16552350513326886351, + 2842235074681099572, 6045955093828210410, 12534027406207583719, 9023829328537353058, 1661393615224515538, 3265308219651631507, 14825441620546235307, 6190486519065164472, + 9569762631377921701, 10341967309273270300, 4697570564829842013, 16684762125903667303, 5281929071085172097, 13027961546412671127, 18398764602992176314, 3872796039504642974, + 3625046733403850478, 18072436321985678348, 12926724831909767455, 17260889391923475120, 2205546675974800411, 4823605748727161314, 11756378320036258430, 12725625915588142865, + 3620769638269480452, 531680461898170, 10213227252513668871, 15446816035938502695, 15189868868814686765, 8689079054027125562, 10767300823767661010, 12185259819280811201, + 2954211398425891878, 887045055614004603, 17024961552904496644, 11183183814128062689, 2275500228939836642, 8454621353771976628, 13706050871317440521, 13152782683288296426, + 5035609627965208105, 6338722048255995169, 11594969687968475335, 5639340633771742838, 6928934109570365590, 11589609913085167707, 18353534295019770247, 6879412911232288750, + 13223374340976842384, 5803903047180226505, 10382392856292138950, 6807712794865416975, 7273350714698980002, 16071615116869102753, 11130104866208195846, 17099222713467268806, + 4288395624114587260, 10186593737807119648, 5970871638851383523, 17274628153010076591, 11083355019391773968, 15571651381840416650, 7269503864920933911, 34314525388851272, + 13518907013113787435, 13799188114963266222, 10949327997049617616, 12851874981220611149, 14245323937486085594, 18324803746062213911, 13224741762315864830, 15910543010675195930, + 10042008593756684008, 6713471518385846030, 10961845838926538977, 855334359173719954, 7598642325962297361, 18006511265377032901, 6844179774752820363, 248341098560552116, + }, + { + 9259451175701532574, 15597985540941612547, 4541553034987877619, 8927802479718285609, 14672230714928802576, 14284617950605306700, 13339970812390782046, 787078889494395850, + 18165439414433063919, 14693282888419586094, 14992616289789993230, 13232208150801553912, 16850347485914337693, 223364064845089224, 7302899015436300563, 4391216311540396088, + 12558388403188680537, 10687978569513354810, 9373570856564649772, 4079327722512691465, 5372437374337150740, 3297421622932790851, 9326853593823854687, 8305371884938201251, + 13121472331750731303, 323745485980480220, 15110308702528119977, 4696302365805118372, 9859094500834571602, 5315656270700787939, 4187063204400651801, 1695695129564818327, + 12817586844019849804, 15425488216915741929, 15293562913126043054, 11770898970765978555, 6806103820345670787, 17789094149138630459, 3807781571713999192, 5823254011289457198, + 10112524230916015604, 13571143908656270599, 6031089010487808103, 5774558171390644848, 1808959243244841573, 14071312530426692155, 9241399242704553402, 9836150050655369231, + 14083007972403535491, 16009534514129505275, 12481249112231139039, 10309390659262581143, 5782517315325366794, 16717384553294759530, 4578392002424884134, 239005024949492645, + 1836857790164349346, 11263074778654917115, 4786985732596838094, 10525445084936097674, 1484357665966453236, 3110871407036679558, 1668700683093601768, 2736269131339849752, + 9249362594190920246, 8088172462140746331, 4080107866285682736, 16205599538438551353, 18312943145606312277, 9100632964181080418, 3969991115337154345, 5340098959750368315, + 12122448407048035645, 2891250339380982359, 12794212052932523400, 7166035112141500392, 15777441312724841162, 4552528682229856831, 2210391301762911476, 16410254680957321386, + 6910044784455706429, 11951245774670922855, 207795885948948810, 3884359690300962405, 4578772752480772344, 2948797025787714138, 16774444535658202808, 1388183483009000463, + 16561979129019905420, 1881862411760441386, 15441950514711322010, 12933020223458438856, 5570341451312029630, 18172638959728259059, 9074261777549091198, 6171200053222754816, + 10126435102176037237, 1545112930055760251, 11563139991870561593, 10766754172364938834, 5116781688621052838, 14471715119500781375, 4724882615229687192, 10031687030722046325, + 15016829467434780812, 6777508689306592732, 3811682306063049290, 11475361222871876387, 6080948654298953274, 11612742274762615033, 5268311600240325047, 9147351973710519861, + 12130203770930472759, 3880998309361490881, 8807462332494735511, 9291388074337055133, 18165312304248982432, 12733144434841535979, 18090195697688236271, 5825342884125782172, + 13034385644450400616, 16498936039876211302, 13019014556329727588, 17911110193068084415, 2034190024798401134, 1526884555531436223, 8108814142164064795, 4075908755148182733, + 6404489603451030675, 16601749455344583377, 12907740667428956072, 8446383351289364752, 698035388979141580, 3593914367189873571, 6744392605914028800, 18168078953147292456, + 14484703498492722699, 6030798911934842161, 15931002029256202288, 13491601992324491240, 8585568434702372483, 9113555433818303018, 6375455514164501736, 1476639189214882947, + 5209683814158663472, 16895526973128357178, 10457488910391635027, 17530003042232440701, 4030542539553991812, 9445656287872984963, 4212489101708176016, 837886727556721620, + 2983790309644332360, 11276772732994425347, 1310621139116895737, 3131558545024164284, 3529698629777893989, 13271773334458143370, 8171825923423406479, 305718858162497191, + 12347543988562572522, 4315642616923374215, 17586477762860427847, 1037334149869395772, 18311071546005132724, 1489505092175764848, 8926409949339059078, 10260307609945070716, + 1253128470325829265, 917180526219408600, 10471425074479693158, 12658678264459355332, 8502334428811982364, 3789675096428271759, 4531393894096863308, 12176495757901795513, + 15081766794595471636, 3944913291385975654, 14507832069904091484, 3624606168811123851, 11476968507677098110, 1056328247986567681, 15246608002200052960, 6566558379177875405, + 652315099041528631, 4287214618428297946, 11730560225433863449, 7935915607867430686, 15979159466809939008, 9209839549459543141, 9501045239358734673, 15490773728258884277, + 14281001444503113096, 9253803478538227873, 3842669056581745692, 18399990656305827164, 11841387504710944221, 16052361836589007383, 831115622826254867, 8219898649601530197, + 2339128600785774471, 1426373723429876004, 3299581455481810683, 16966544600853047157, 8419320331267538738, 8376963013864643226, 1996128805959565963, 2376766970819731241, + 10963611841695254911, 2914831079289063424, 15884256460390936367, 8724520571578171796, 329402220949313078, 8905943304651682982, 1280899166177109409, 6980213851983339340, + 5524321102331478758, 2149164875175284006, 10897639484514200325, 14605181792035620644, 316829907946955098, 13776780818927038502, 18167912441745301047, 16845612593885106452, + 15817940025107036888, 14405005201957074368, 11647077937228007305, 13795438792777593442, 9813339145840642083, 13196196205982926907, 5981408724994946624, 12303812818084690125, + 11821409230485627325, 1934768678832528678, 15798397330147151183, 2089418311766868031, 16206123311846842647, 10276976147555604745, 14858750786699873336, 2500482310681473276, + 9502861285700748804, 12163827978530279544, 9383068907817479934, 5717811606328725851, 12416198015020836733, 15689586164720677894, 14337921697724349521, 9392403465642971279, + 6696074876763293236, 10302972695440286968, 16647054763285662245, 7841147641486000427, 10612636854719975349, 3592516733641215266, 14172459823963607855, 1290213042793222575, + }, +} diff --git a/libgo/go/crypto/elliptic/p256_asm_table_test.go b/libgo/go/crypto/elliptic/p256_asm_table_test.go new file mode 100644 index 0000000..f91108b --- /dev/null +++ b/libgo/go/crypto/elliptic/p256_asm_table_test.go @@ -0,0 +1,59 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore +// +build ignore + +package elliptic + +import ( + "reflect" + "testing" +) + +func TestP256PrecomputedTable(t *testing.T) { + + basePoint := []uint64{ + 0x79e730d418a9143c, 0x75ba95fc5fedb601, 0x79fb732b77622510, 0x18905f76a53755c6, + 0xddf25357ce95560a, 0x8b4ab8e4ba19e45c, 0xd2e88688dd21f325, 0x8571ff1825885d85, + 0x0000000000000001, 0xffffffff00000000, 0xffffffffffffffff, 0x00000000fffffffe, + } + t1 := make([]uint64, 12) + t2 := make([]uint64, 12) + copy(t2, basePoint) + + zInv := make([]uint64, 4) + zInvSq := make([]uint64, 4) + for j := 0; j < 32; j++ { + copy(t1, t2) + for i := 0; i < 43; i++ { + // The window size is 6 so we need to double 6 times. + if i != 0 { + for k := 0; k < 6; k++ { + p256PointDoubleAsm(t1, t1) + } + } + // Convert the point to affine form. (Its values are + // still in Montgomery form however.) + p256Inverse(zInv, t1[8:12]) + p256Sqr(zInvSq, zInv, 1) + p256Mul(zInv, zInv, zInvSq) + + p256Mul(t1[:4], t1[:4], zInvSq) + p256Mul(t1[4:8], t1[4:8], zInv) + + copy(t1[8:12], basePoint[8:12]) + + if got, want := p256Precomputed[i][j*8:(j*8)+8], t1[:8]; !reflect.DeepEqual(got, want) { + t.Fatalf("Unexpected table entry at [%d][%d:%d]: got %v, want %v", i, j*8, (j*8)+8, got, want) + } + } + if j == 0 { + p256PointDoubleAsm(t2, basePoint) + } else { + p256PointAddAsm(t2, t2, basePoint) + } + } + +} diff --git a/libgo/go/crypto/elliptic/p256_generic.go b/libgo/go/crypto/elliptic/p256_generic.go index 8e1a412..48793f0 100644 --- a/libgo/go/crypto/elliptic/p256_generic.go +++ b/libgo/go/crypto/elliptic/p256_generic.go @@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//-go:build !amd64 && !s390x && !arm64 && !ppc64le // -build !amd64,!s390x,!arm64,!ppc64le package elliptic -var ( - p256 p256Curve -) +var p256 p256Curve func initP256Arch() { // Use pure Go implementation. diff --git a/libgo/go/crypto/elliptic/p256_ppc64le.go b/libgo/go/crypto/elliptic/p256_ppc64le.go index 6f721b8..2af9d75 100644 --- a/libgo/go/crypto/elliptic/p256_ppc64le.go +++ b/libgo/go/crypto/elliptic/p256_ppc64le.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore -// +build ppc64le package elliptic diff --git a/libgo/go/crypto/elliptic/p256_s390x.go b/libgo/go/crypto/elliptic/p256_s390x.go index fb38e0a..3b9a767 100644 --- a/libgo/go/crypto/elliptic/p256_s390x.go +++ b/libgo/go/crypto/elliptic/p256_s390x.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore -// -build s390x package elliptic diff --git a/libgo/go/crypto/elliptic/p256_test.go b/libgo/go/crypto/elliptic/p256_test.go new file mode 100644 index 0000000..1435f5e --- /dev/null +++ b/libgo/go/crypto/elliptic/p256_test.go @@ -0,0 +1,155 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package elliptic + +import ( + "math/big" + "testing" +) + +type scalarMultTest struct { + k string + xIn, yIn string + xOut, yOut string +} + +var p256MultTests = []scalarMultTest{ + { + "2a265f8bcbdcaf94d58519141e578124cb40d64a501fba9c11847b28965bc737", + "023819813ac969847059028ea88a1f30dfbcde03fc791d3a252c6b41211882ea", + "f93e4ae433cc12cf2a43fc0ef26400c0e125508224cdb649380f25479148a4ad", + "4d4de80f1534850d261075997e3049321a0864082d24a917863366c0724f5ae3", + "a22d2b7f7818a3563e0f7a76c9bf0921ac55e06e2e4d11795b233824b1db8cc0", + }, + { + "313f72ff9fe811bf573176231b286a3bdb6f1b14e05c40146590727a71c3bccd", + "cc11887b2d66cbae8f4d306627192522932146b42f01d3c6f92bd5c8ba739b06", + "a2f08a029cd06b46183085bae9248b0ed15b70280c7ef13a457f5af382426031", + "831c3f6b5f762d2f461901577af41354ac5f228c2591f84f8a6e51e2e3f17991", + "93f90934cd0ef2c698cc471c60a93524e87ab31ca2412252337f364513e43684", + }, +} + +func TestP256BaseMult(t *testing.T) { + p256 := P256() + p256Generic := p256.Params() + + scalars := make([]*big.Int, 0, len(p224BaseMultTests)+1) + for _, e := range p224BaseMultTests { + k, _ := new(big.Int).SetString(e.k, 10) + scalars = append(scalars, k) + } + k := new(big.Int).SetInt64(1) + k.Lsh(k, 500) + scalars = append(scalars, k) + + for i, k := range scalars { + x, y := p256.ScalarBaseMult(k.Bytes()) + x2, y2 := p256Generic.ScalarBaseMult(k.Bytes()) + if x.Cmp(x2) != 0 || y.Cmp(y2) != 0 { + t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, x, y, x2, y2) + } + + if testing.Short() && i > 5 { + break + } + } +} + +func TestP256Mult(t *testing.T) { + p256 := P256() + p256Generic := p256.Params() + + for i, e := range p224BaseMultTests { + x, _ := new(big.Int).SetString(e.x, 16) + y, _ := new(big.Int).SetString(e.y, 16) + k, _ := new(big.Int).SetString(e.k, 10) + + xx, yy := p256.ScalarMult(x, y, k.Bytes()) + xx2, yy2 := p256Generic.ScalarMult(x, y, k.Bytes()) + if xx.Cmp(xx2) != 0 || yy.Cmp(yy2) != 0 { + t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, xx2, yy2) + } + if testing.Short() && i > 5 { + break + } + } + + for i, e := range p256MultTests { + x, _ := new(big.Int).SetString(e.xIn, 16) + y, _ := new(big.Int).SetString(e.yIn, 16) + k, _ := new(big.Int).SetString(e.k, 16) + expectedX, _ := new(big.Int).SetString(e.xOut, 16) + expectedY, _ := new(big.Int).SetString(e.yOut, 16) + + xx, yy := p256.ScalarMult(x, y, k.Bytes()) + if xx.Cmp(expectedX) != 0 || yy.Cmp(expectedY) != 0 { + t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, expectedX, expectedY) + } + } +} + +type synthCombinedMult struct { + Curve +} + +func (s synthCombinedMult) CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) { + x1, y1 := s.ScalarBaseMult(baseScalar) + x2, y2 := s.ScalarMult(bigX, bigY, scalar) + return s.Add(x1, y1, x2, y2) +} + +func TestP256CombinedMult(t *testing.T) { + type combinedMult interface { + Curve + CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) + } + + p256, ok := P256().(combinedMult) + if !ok { + p256 = &synthCombinedMult{P256()} + } + + gx := p256.Params().Gx + gy := p256.Params().Gy + + zero := make([]byte, 32) + one := make([]byte, 32) + one[31] = 1 + two := make([]byte, 32) + two[31] = 2 + + // 0×G + 0×G = ∞ + x, y := p256.CombinedMult(gx, gy, zero, zero) + if x.Sign() != 0 || y.Sign() != 0 { + t.Errorf("0×G + 0×G = (%d, %d), should be ∞", x, y) + } + + // 1×G + 0×G = G + x, y = p256.CombinedMult(gx, gy, one, zero) + if x.Cmp(gx) != 0 || y.Cmp(gy) != 0 { + t.Errorf("1×G + 0×G = (%d, %d), should be (%d, %d)", x, y, gx, gy) + } + + // 0×G + 1×G = G + x, y = p256.CombinedMult(gx, gy, zero, one) + if x.Cmp(gx) != 0 || y.Cmp(gy) != 0 { + t.Errorf("0×G + 1×G = (%d, %d), should be (%d, %d)", x, y, gx, gy) + } + + // 1×G + 1×G = 2×G + x, y = p256.CombinedMult(gx, gy, one, one) + ggx, ggy := p256.ScalarBaseMult(two) + if x.Cmp(ggx) != 0 || y.Cmp(ggy) != 0 { + t.Errorf("1×G + 1×G = (%d, %d), should be (%d, %d)", x, y, ggx, ggy) + } + + minusOne := new(big.Int).Sub(p256.Params().N, big.NewInt(1)) + // 1×G + (-1)×G = ∞ + x, y = p256.CombinedMult(gx, gy, one, minusOne.Bytes()) + if x.Sign() != 0 || y.Sign() != 0 { + t.Errorf("1×G + (-1)×G = (%d, %d), should be ∞", x, y) + } +} diff --git a/libgo/go/crypto/elliptic/p521.go b/libgo/go/crypto/elliptic/p521.go new file mode 100644 index 0000000..3d35594 --- /dev/null +++ b/libgo/go/crypto/elliptic/p521.go @@ -0,0 +1,259 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package elliptic + +import ( + "crypto/elliptic/internal/fiat" + "math/big" +) + +type p521Curve struct { + *CurveParams +} + +var p521 p521Curve +var p521Params *CurveParams + +func initP521() { + // See FIPS 186-3, section D.2.5 + p521.CurveParams = &CurveParams{Name: "P-521"} + p521.P, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", 10) + p521.N, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449", 10) + p521.B, _ = new(big.Int).SetString("051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", 16) + p521.Gx, _ = new(big.Int).SetString("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 16) + p521.Gy, _ = new(big.Int).SetString("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 16) + p521.BitSize = 521 +} + +func (curve p521Curve) Params() *CurveParams { + return curve.CurveParams +} + +func (curve p521Curve) IsOnCurve(x, y *big.Int) bool { + x1 := bigIntToFiatP521(x) + y1 := bigIntToFiatP521(y) + b := bigIntToFiatP521(curve.B) // TODO: precompute this value. + + // x³ - 3x + b. + x3 := new(fiat.P521Element).Square(x1) + x3.Mul(x3, x1) + + threeX := new(fiat.P521Element).Add(x1, x1) + threeX.Add(threeX, x1) + + x3.Sub(x3, threeX) + x3.Add(x3, b) + + // y² = x³ - 3x + b + y2 := new(fiat.P521Element).Square(y1) + + return x3.Equal(y2) == 1 +} + +type p521Point struct { + x, y, z *fiat.P521Element +} + +func fiatP521ToBigInt(x *fiat.P521Element) *big.Int { + xBytes := x.Bytes() + for i := range xBytes[:len(xBytes)/2] { + xBytes[i], xBytes[len(xBytes)-i-1] = xBytes[len(xBytes)-i-1], xBytes[i] + } + return new(big.Int).SetBytes(xBytes) +} + +// affineFromJacobian brings a point in Jacobian coordinates back to affine +// coordinates, with (0, 0) representing infinity by convention. It also goes +// back to big.Int values to match the exposed API. +func (curve p521Curve) affineFromJacobian(p *p521Point) (x, y *big.Int) { + if p.z.IsZero() == 1 { + return new(big.Int), new(big.Int) + } + + zinv := new(fiat.P521Element).Invert(p.z) + zinvsq := new(fiat.P521Element).Mul(zinv, zinv) + + xx := new(fiat.P521Element).Mul(p.x, zinvsq) + zinvsq.Mul(zinvsq, zinv) + yy := new(fiat.P521Element).Mul(p.y, zinvsq) + + return fiatP521ToBigInt(xx), fiatP521ToBigInt(yy) +} + +func bigIntToFiatP521(x *big.Int) *fiat.P521Element { + xBytes := new(big.Int).Mod(x, p521.P).FillBytes(make([]byte, 66)) + for i := range xBytes[:len(xBytes)/2] { + xBytes[i], xBytes[len(xBytes)-i-1] = xBytes[len(xBytes)-i-1], xBytes[i] + } + x1, err := new(fiat.P521Element).SetBytes(xBytes) + if err != nil { + // The input is reduced modulo P and encoded in a fixed size bytes + // slice, this should be impossible. + panic("internal error: bigIntToFiatP521") + } + return x1 +} + +// jacobianFromAffine converts (x, y) affine coordinates into (x, y, z) Jacobian +// coordinates. It also converts from big.Int to fiat, which is necessarily a +// messy and variable-time operation, which we can't avoid due to the exposed API. +func (curve p521Curve) jacobianFromAffine(x, y *big.Int) *p521Point { + // (0, 0) is by convention the point at infinity, which can't be represented + // in affine coordinates, but is (0, 0, 0) in Jacobian. + if x.Sign() == 0 && y.Sign() == 0 { + return &p521Point{ + x: new(fiat.P521Element), + y: new(fiat.P521Element), + z: new(fiat.P521Element), + } + } + return &p521Point{ + x: bigIntToFiatP521(x), + y: bigIntToFiatP521(y), + z: new(fiat.P521Element).One(), + } +} + +func (curve p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { + p1 := curve.jacobianFromAffine(x1, y1) + p2 := curve.jacobianFromAffine(x2, y2) + return curve.affineFromJacobian(p1.addJacobian(p1, p2)) +} + +// addJacobian sets q = p1 + p2, and returns q. The points may overlap. +func (q *p521Point) addJacobian(p1, p2 *p521Point) *p521Point { + // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl + z1IsZero := p1.z.IsZero() + z2IsZero := p2.z.IsZero() + + z1z1 := new(fiat.P521Element).Square(p1.z) + z2z2 := new(fiat.P521Element).Square(p2.z) + + u1 := new(fiat.P521Element).Mul(p1.x, z2z2) + u2 := new(fiat.P521Element).Mul(p2.x, z1z1) + h := new(fiat.P521Element).Sub(u2, u1) + xEqual := h.IsZero() == 1 + i := new(fiat.P521Element).Add(h, h) + i.Square(i) + j := new(fiat.P521Element).Mul(h, i) + + s1 := new(fiat.P521Element).Mul(p1.y, p2.z) + s1.Mul(s1, z2z2) + s2 := new(fiat.P521Element).Mul(p2.y, p1.z) + s2.Mul(s2, z1z1) + r := new(fiat.P521Element).Sub(s2, s1) + yEqual := r.IsZero() == 1 + if xEqual && yEqual && z1IsZero == 0 && z2IsZero == 0 { + return q.doubleJacobian(p1) + } + r.Add(r, r) + v := new(fiat.P521Element).Mul(u1, i) + + x := new(fiat.P521Element).Set(r) + x.Square(x) + x.Sub(x, j) + x.Sub(x, v) + x.Sub(x, v) + + y := new(fiat.P521Element).Set(r) + v.Sub(v, x) + y.Mul(y, v) + s1.Mul(s1, j) + s1.Add(s1, s1) + y.Sub(y, s1) + + z := new(fiat.P521Element).Add(p1.z, p2.z) + z.Square(z) + z.Sub(z, z1z1) + z.Sub(z, z2z2) + z.Mul(z, h) + + x.Select(p2.x, x, z1IsZero) + x.Select(p1.x, x, z2IsZero) + y.Select(p2.y, y, z1IsZero) + y.Select(p1.y, y, z2IsZero) + z.Select(p2.z, z, z1IsZero) + z.Select(p1.z, z, z2IsZero) + + q.x.Set(x) + q.y.Set(y) + q.z.Set(z) + return q +} + +func (curve p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { + p := curve.jacobianFromAffine(x1, y1) + return curve.affineFromJacobian(p.doubleJacobian(p)) +} + +// doubleJacobian sets q = p + p, and returns q. The points may overlap. +func (q *p521Point) doubleJacobian(p *p521Point) *p521Point { + // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b + delta := new(fiat.P521Element).Square(p.z) + gamma := new(fiat.P521Element).Square(p.y) + alpha := new(fiat.P521Element).Sub(p.x, delta) + alpha2 := new(fiat.P521Element).Add(p.x, delta) + alpha.Mul(alpha, alpha2) + alpha2.Set(alpha) + alpha.Add(alpha, alpha) + alpha.Add(alpha, alpha2) + + beta := alpha2.Mul(p.x, gamma) + + q.x.Square(alpha) + beta8 := new(fiat.P521Element).Add(beta, beta) + beta8.Add(beta8, beta8) + beta8.Add(beta8, beta8) + q.x.Sub(q.x, beta8) + + q.z.Add(p.y, p.z) + q.z.Square(q.z) + q.z.Sub(q.z, gamma) + q.z.Sub(q.z, delta) + + beta.Add(beta, beta) + beta.Add(beta, beta) + beta.Sub(beta, q.x) + q.y.Mul(alpha, beta) + + gamma.Square(gamma) + gamma.Add(gamma, gamma) + gamma.Add(gamma, gamma) + gamma.Add(gamma, gamma) + + q.y.Sub(q.y, gamma) + + return q +} + +func (curve p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { + B := curve.jacobianFromAffine(Bx, By) + p, t := &p521Point{ + x: new(fiat.P521Element), + y: new(fiat.P521Element), + z: new(fiat.P521Element), + }, &p521Point{ + x: new(fiat.P521Element), + y: new(fiat.P521Element), + z: new(fiat.P521Element), + } + + for _, byte := range scalar { + for bitNum := 0; bitNum < 8; bitNum++ { + p.doubleJacobian(p) + bit := (byte >> (7 - bitNum)) & 1 + t.addJacobian(p, B) + p.x.Select(t.x, p.x, int(bit)) + p.y.Select(t.y, p.y, int(bit)) + p.z.Select(t.z, p.z, int(bit)) + } + } + + return curve.affineFromJacobian(p) +} + +func (curve p521Curve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { + return curve.ScalarMult(curve.Gx, curve.Gy, k) +} diff --git a/libgo/go/crypto/internal/subtle/aliasing.go b/libgo/go/crypto/internal/subtle/aliasing.go index 812ce3c..86e0f3c 100644 --- a/libgo/go/crypto/internal/subtle/aliasing.go +++ b/libgo/go/crypto/internal/subtle/aliasing.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !appengine // +build !appengine // Package subtle implements functions that are often useful in cryptographic diff --git a/libgo/go/crypto/internal/subtle/aliasing_appengine.go b/libgo/go/crypto/internal/subtle/aliasing_appengine.go index 844f901..35b442f 100644 --- a/libgo/go/crypto/internal/subtle/aliasing_appengine.go +++ b/libgo/go/crypto/internal/subtle/aliasing_appengine.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build appengine // +build appengine // Package subtle implements functions that are often useful in cryptographic diff --git a/libgo/go/crypto/md5/gen.go b/libgo/go/crypto/md5/gen.go index 1468924c..29729fa 100644 --- a/libgo/go/crypto/md5/gen.go +++ b/libgo/go/crypto/md5/gen.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // This program generates md5block.go diff --git a/libgo/go/crypto/md5/md5_test.go b/libgo/go/crypto/md5/md5_test.go index 282ba1b..acd456a 100644 --- a/libgo/go/crypto/md5/md5_test.go +++ b/libgo/go/crypto/md5/md5_test.go @@ -157,7 +157,7 @@ func TestBlockGeneric(t *testing.T) { // Tests for unmarshaling hashes that have hashed a large amount of data // The initial hash generation is omitted from the test, because it takes a long time. // The test contains some already-generated states, and their expected sums -// Tests a problem that is outlined in Github issue #29541 +// Tests a problem that is outlined in GitHub issue #29541 // The problem is triggered when an amount of data has been hashed for which // the data length has a 1 in the 32nd bit. When casted to int, this changes // the sign of the value, and causes the modulus operation to return a @@ -212,7 +212,7 @@ func TestLargeHashes(t *testing.T) { } var bench = New() -var buf = make([]byte, 8192+1) +var buf = make([]byte, 1024*1024*8+1) var sum = make([]byte, bench.Size()) func benchmarkSize(b *testing.B, size int, unaligned bool) { @@ -235,6 +235,22 @@ func BenchmarkHash8Bytes(b *testing.B) { benchmarkSize(b, 8, false) } +func BenchmarkHash64(b *testing.B) { + benchmarkSize(b, 64, false) +} + +func BenchmarkHash128(b *testing.B) { + benchmarkSize(b, 128, false) +} + +func BenchmarkHash256(b *testing.B) { + benchmarkSize(b, 256, false) +} + +func BenchmarkHash512(b *testing.B) { + benchmarkSize(b, 512, false) +} + func BenchmarkHash1K(b *testing.B) { benchmarkSize(b, 1024, false) } @@ -243,6 +259,14 @@ func BenchmarkHash8K(b *testing.B) { benchmarkSize(b, 8192, false) } +func BenchmarkHash1M(b *testing.B) { + benchmarkSize(b, 1024*1024, false) +} + +func BenchmarkHash8M(b *testing.B) { + benchmarkSize(b, 8*1024*1024, false) +} + func BenchmarkHash8BytesUnaligned(b *testing.B) { benchmarkSize(b, 8, true) } diff --git a/libgo/go/crypto/md5/md5block_decl.go b/libgo/go/crypto/md5/md5block_decl.go index ccdae40..5f31731 100644 --- a/libgo/go/crypto/md5/md5block_decl.go +++ b/libgo/go/crypto/md5/md5block_decl.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore -// +build amd64 386 arm ppc64le ppc64 s390x arm64 package md5 diff --git a/libgo/go/crypto/md5/md5block_generic.go b/libgo/go/crypto/md5/md5block_generic.go index 56520f1..3d44df2 100644 --- a/libgo/go/crypto/md5/md5block_generic.go +++ b/libgo/go/crypto/md5/md5block_generic.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//-go:build !amd64 && !386 && !arm && !ppc64le && !ppc64 && !s390x && !arm64 // -build !amd64,!386,!arm,!ppc64le,!ppc64,!s390x,!arm64 package md5 diff --git a/libgo/go/crypto/rand/eagain.go b/libgo/go/crypto/rand/eagain.go index 360b215..22be7f0 100644 --- a/libgo/go/crypto/rand/eagain.go +++ b/libgo/go/crypto/rand/eagain.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package rand diff --git a/libgo/go/crypto/rand/rand_batched.go b/libgo/go/crypto/rand/rand_batched.go index 60267fd..d7c5bf3 100644 --- a/libgo/go/crypto/rand/rand_batched.go +++ b/libgo/go/crypto/rand/rand_batched.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux freebsd +//go:build linux || freebsd || dragonfly || solaris +// +build linux freebsd dragonfly solaris package rand diff --git a/libgo/go/crypto/rand/rand_batched_test.go b/libgo/go/crypto/rand/rand_batched_test.go index 837db83..2d20922 100644 --- a/libgo/go/crypto/rand/rand_batched_test.go +++ b/libgo/go/crypto/rand/rand_batched_test.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux freebsd +//go:build linux || freebsd || dragonfly || solaris +// +build linux freebsd dragonfly solaris package rand diff --git a/libgo/go/crypto/rand/rand_dragonfly.go b/libgo/go/crypto/rand/rand_dragonfly.go new file mode 100644 index 0000000..8a36fea --- /dev/null +++ b/libgo/go/crypto/rand/rand_dragonfly.go @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +// maxGetRandomRead is the maximum number of bytes to ask for in one call to the +// getrandom() syscall. In DragonFlyBSD at most 256 bytes will be returned per call. +const maxGetRandomRead = 1 << 8 diff --git a/libgo/go/crypto/rand/rand_openbsd.go b/libgo/go/crypto/rand/rand_getentropy.go index 9cc39f7..f82018a 100644 --- a/libgo/go/crypto/rand/rand_openbsd.go +++ b/libgo/go/crypto/rand/rand_getentropy.go @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || openbsd +// +build darwin openbsd + package rand import ( @@ -9,10 +12,10 @@ import ( ) func init() { - altGetRandom = getRandomOpenBSD + altGetRandom = getEntropy } -func getRandomOpenBSD(p []byte) (ok bool) { +func getEntropy(p []byte) (ok bool) { // getentropy(2) returns a maximum of 256 bytes per call for i := 0; i < len(p); i += 256 { end := i + 256 diff --git a/libgo/go/crypto/rand/rand_js.go b/libgo/go/crypto/rand/rand_js.go index 7e93974..7ddc2b6 100644 --- a/libgo/go/crypto/rand/rand_js.go +++ b/libgo/go/crypto/rand/rand_js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package rand diff --git a/libgo/go/crypto/rand/rand_solaris.go b/libgo/go/crypto/rand/rand_solaris.go new file mode 100644 index 0000000..bbad0fe --- /dev/null +++ b/libgo/go/crypto/rand/rand_solaris.go @@ -0,0 +1,10 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +// maxGetRandomRead is the maximum number of bytes to ask for in one call to the +// getrandom() syscall. Across all the Solaris platforms, 256 bytes is the +// lowest number of bytes returned atomically per call. +const maxGetRandomRead = 1 << 8 diff --git a/libgo/go/crypto/rand/rand_unix.go b/libgo/go/crypto/rand/rand_unix.go index 9ff4d358..01458c6 100644 --- a/libgo/go/crypto/rand/rand_unix.go +++ b/libgo/go/crypto/rand/rand_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || plan9 || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd plan9 solaris // Unix cryptographically secure pseudorandom number diff --git a/libgo/go/crypto/rsa/pss.go b/libgo/go/crypto/rsa/pss.go index b2adbed..814522d 100644 --- a/libgo/go/crypto/rsa/pss.go +++ b/libgo/go/crypto/rsa/pss.go @@ -269,7 +269,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, saltLength := opts.saltLength() switch saltLength { case PSSSaltLengthAuto: - saltLength = priv.Size() - 2 - hash.Size() + saltLength = (priv.N.BitLen()-1+7)/8 - 2 - hash.Size() case PSSSaltLengthEqualsHash: saltLength = hash.Size() } diff --git a/libgo/go/crypto/rsa/pss_test.go b/libgo/go/crypto/rsa/pss_test.go index dfa8d8b..c3a6d46 100644 --- a/libgo/go/crypto/rsa/pss_test.go +++ b/libgo/go/crypto/rsa/pss_test.go @@ -12,7 +12,7 @@ import ( _ "crypto/md5" "crypto/rand" "crypto/sha1" - _ "crypto/sha256" + "crypto/sha256" "encoding/hex" "math/big" "os" @@ -233,6 +233,24 @@ func TestPSSSigning(t *testing.T) { } } +func TestSignWithPSSSaltLengthAuto(t *testing.T) { + key, err := GenerateKey(rand.Reader, 513) + if err != nil { + t.Fatal(err) + } + digest := sha256.Sum256([]byte("message")) + signature, err := key.Sign(rand.Reader, digest[:], &PSSOptions{ + SaltLength: PSSSaltLengthAuto, + Hash: crypto.SHA256, + }) + if err != nil { + t.Fatal(err) + } + if len(signature) == 0 { + t.Fatal("empty signature returned") + } +} + func bigFromHex(hex string) *big.Int { n, ok := new(big.Int).SetString(hex, 16) if !ok { diff --git a/libgo/go/crypto/rsa/rsa.go b/libgo/go/crypto/rsa/rsa.go index 178ade6..6fd59b3 100644 --- a/libgo/go/crypto/rsa/rsa.go +++ b/libgo/go/crypto/rsa/rsa.go @@ -401,7 +401,7 @@ func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int { // // The label parameter may contain arbitrary data that will not be encrypted, // but which gives important context to the message. For example, if a given -// public key is used to decrypt two types of messages then distinct label +// public key is used to encrypt two types of messages then distinct label // values could be used to ensure that a ciphertext for one purpose cannot be // used for another by an attacker. If not required it can be empty. // diff --git a/libgo/go/crypto/sha1/fallback_test.go b/libgo/go/crypto/sha1/fallback_test.go index a47b3f4..b270d79 100644 --- a/libgo/go/crypto/sha1/fallback_test.go +++ b/libgo/go/crypto/sha1/fallback_test.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore -// +build s390x package sha1 diff --git a/libgo/go/crypto/sha1/issue15617_test.go b/libgo/go/crypto/sha1/issue15617_test.go index 98038e5..436f78c 100644 --- a/libgo/go/crypto/sha1/issue15617_test.go +++ b/libgo/go/crypto/sha1/issue15617_test.go @@ -1,3 +1,4 @@ +//go:build amd64 && (linux || darwin) // +build amd64 // +build linux darwin diff --git a/libgo/go/crypto/sha1/sha1_test.go b/libgo/go/crypto/sha1/sha1_test.go index 681e928..c3e6010 100644 --- a/libgo/go/crypto/sha1/sha1_test.go +++ b/libgo/go/crypto/sha1/sha1_test.go @@ -156,7 +156,7 @@ func TestBlockGeneric(t *testing.T) { // Tests for unmarshaling hashes that have hashed a large amount of data // The initial hash generation is omitted from the test, because it takes a long time. // The test contains some already-generated states, and their expected sums -// Tests a problem that is outlined in Github issue #29543 +// Tests a problem that is outlined in GitHub issue #29543 // The problem is triggered when an amount of data has been hashed for which // the data length has a 1 in the 32nd bit. When casted to int, this changes // the sign of the value, and causes the modulus operation to return a diff --git a/libgo/go/crypto/sha1/sha1block_decl.go b/libgo/go/crypto/sha1/sha1block_decl.go index 88074c0..d0d527d 100644 --- a/libgo/go/crypto/sha1/sha1block_decl.go +++ b/libgo/go/crypto/sha1/sha1block_decl.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore -// +build arm 386 s390x package sha1 diff --git a/libgo/go/crypto/sha1/sha1block_generic.go b/libgo/go/crypto/sha1/sha1block_generic.go index 089b3c4..48629ee 100644 --- a/libgo/go/crypto/sha1/sha1block_generic.go +++ b/libgo/go/crypto/sha1/sha1block_generic.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//-go:build !amd64 && !386 && !arm && !s390x && !arm64 // -build !amd64,!386,!arm,!s390x,!arm64 package sha1 diff --git a/libgo/go/crypto/sha256/fallback_test.go b/libgo/go/crypto/sha256/fallback_test.go index 1a6e6a5..de1c154 100644 --- a/libgo/go/crypto/sha256/fallback_test.go +++ b/libgo/go/crypto/sha256/fallback_test.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore -// +build s390x package sha256 diff --git a/libgo/go/crypto/sha256/sha256_test.go b/libgo/go/crypto/sha256/sha256_test.go index 433c5a4..a2794b0 100644 --- a/libgo/go/crypto/sha256/sha256_test.go +++ b/libgo/go/crypto/sha256/sha256_test.go @@ -229,7 +229,7 @@ func TestBlockGeneric(t *testing.T) { // Tests for unmarshaling hashes that have hashed a large amount of data // The initial hash generation is omitted from the test, because it takes a long time. // The test contains some already-generated states, and their expected sums -// Tests a problem that is outlined in Github issue #29517 +// Tests a problem that is outlined in GitHub issue #29517 // The problem is triggered when an amount of data has been hashed for which // the data length has a 1 in the 32nd bit. When casted to int, this changes // the sign of the value, and causes the modulus operation to return a diff --git a/libgo/go/crypto/sha256/sha256block_decl.go b/libgo/go/crypto/sha256/sha256block_decl.go index e283c41..ccbd9d6 100644 --- a/libgo/go/crypto/sha256/sha256block_decl.go +++ b/libgo/go/crypto/sha256/sha256block_decl.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore -// +build 386 amd64 s390x ppc64le package sha256 diff --git a/libgo/go/crypto/sha256/sha256block_generic.go b/libgo/go/crypto/sha256/sha256block_generic.go index d1b5075..2d320b8 100644 --- a/libgo/go/crypto/sha256/sha256block_generic.go +++ b/libgo/go/crypto/sha256/sha256block_generic.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//-go:build !amd64 && !386 && !s390x && !ppc64le && !arm64 // -build !amd64,!386,!s390x,!ppc64le,!arm64 package sha256 diff --git a/libgo/go/crypto/sha512/fallback_test.go b/libgo/go/crypto/sha512/fallback_test.go index 1408131..30c161f 100644 --- a/libgo/go/crypto/sha512/fallback_test.go +++ b/libgo/go/crypto/sha512/fallback_test.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore -// +build s390x package sha512 diff --git a/libgo/go/crypto/sha512/sha512_test.go b/libgo/go/crypto/sha512/sha512_test.go index 59998b1..0e1528f 100644 --- a/libgo/go/crypto/sha512/sha512_test.go +++ b/libgo/go/crypto/sha512/sha512_test.go @@ -788,7 +788,7 @@ func TestMarshalMismatch(t *testing.T) { } if err := h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(state); err == nil { - t.Errorf("i=%d, j=%d: got no error , expected one: %v", i, j, err) + t.Errorf("i=%d, j=%d: got no error, expected one: %v", i, j, err) } } } @@ -835,7 +835,7 @@ func TestBlockGeneric(t *testing.T) { // Tests for unmarshaling hashes that have hashed a large amount of data // The initial hash generation is omitted from the test, because it takes a long time. // The test contains some already-generated states, and their expected sums -// Tests a problem that is outlined in Github issue #29541 +// Tests a problem that is outlined in GitHub issue #29541 // The problem is triggered when an amount of data has been hashed for which // the data length has a 1 in the 32nd bit. When casted to int, this changes // the sign of the value, and causes the modulus operation to return a diff --git a/libgo/go/crypto/sha512/sha512block_amd64.go b/libgo/go/crypto/sha512/sha512block_amd64.go index 0ce599b..8ec87c3 100644 --- a/libgo/go/crypto/sha512/sha512block_amd64.go +++ b/libgo/go/crypto/sha512/sha512block_amd64.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore -// +build amd64 package sha512 diff --git a/libgo/go/crypto/sha512/sha512block_decl.go b/libgo/go/crypto/sha512/sha512block_decl.go index 3d098c5..e4e5858 100644 --- a/libgo/go/crypto/sha512/sha512block_decl.go +++ b/libgo/go/crypto/sha512/sha512block_decl.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore -// +build s390x ppc64le package sha512 diff --git a/libgo/go/crypto/sha512/sha512block_generic.go b/libgo/go/crypto/sha512/sha512block_generic.go index d3998a82..2b0854b 100644 --- a/libgo/go/crypto/sha512/sha512block_generic.go +++ b/libgo/go/crypto/sha512/sha512block_generic.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//-go:build !amd64 && !s390x && !ppc64le // -build !amd64,!s390x,!ppc64le package sha512 diff --git a/libgo/go/crypto/tls/cipher_suites.go b/libgo/go/crypto/tls/cipher_suites.go index 9a35675..4bf0646 100644 --- a/libgo/go/crypto/tls/cipher_suites.go +++ b/libgo/go/crypto/tls/cipher_suites.go @@ -13,9 +13,10 @@ import ( "crypto/rc4" "crypto/sha1" "crypto/sha256" - "crypto/x509" "fmt" "hash" + "internal/cpu" + "runtime" "golang.org/x/crypto/chacha20poly1305" ) @@ -46,10 +47,10 @@ var ( // InsecureCipherSuites. // // The list is sorted by ID. Note that the default cipher suites selected by -// this package might depend on logic that can't be captured by a static list. +// this package might depend on logic that can't be captured by a static list, +// and might not match those returned by this function. func CipherSuites() []*CipherSuite { return []*CipherSuite{ - {TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, false}, {TLS_RSA_WITH_AES_128_CBC_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA", supportedUpToTLS12, false}, {TLS_RSA_WITH_AES_256_CBC_SHA, "TLS_RSA_WITH_AES_256_CBC_SHA", supportedUpToTLS12, false}, {TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS_RSA_WITH_AES_128_GCM_SHA256", supportedOnlyTLS12, false}, @@ -61,7 +62,6 @@ func CipherSuites() []*CipherSuite { {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", supportedUpToTLS12, false}, {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", supportedUpToTLS12, false}, - {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, false}, {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", supportedUpToTLS12, false}, {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", supportedUpToTLS12, false}, {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", supportedOnlyTLS12, false}, @@ -79,13 +79,15 @@ func CipherSuites() []*CipherSuite { // Most applications should not use the cipher suites in this list, and should // only use those returned by CipherSuites. func InsecureCipherSuites() []*CipherSuite { - // RC4 suites are broken because RC4 is. - // CBC-SHA256 suites have no Lucky13 countermeasures. + // This list includes RC4, CBC_SHA256, and 3DES cipher suites. See + // cipherSuitesPreferenceOrder for details. return []*CipherSuite{ {TLS_RSA_WITH_RC4_128_SHA, "TLS_RSA_WITH_RC4_128_SHA", supportedUpToTLS12, true}, + {TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, true}, {TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true}, {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", supportedUpToTLS12, true}, {TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS_ECDHE_RSA_WITH_RC4_128_SHA", supportedUpToTLS12, true}, + {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, true}, {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true}, {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true}, } @@ -108,25 +110,6 @@ func CipherSuiteName(id uint16) string { return fmt.Sprintf("0x%04X", id) } -// a keyAgreement implements the client and server side of a TLS key agreement -// protocol by generating and processing key exchange messages. -type keyAgreement interface { - // On the server side, the first two methods are called in order. - - // In the case that the key agreement protocol doesn't use a - // ServerKeyExchange message, generateServerKeyExchange can return nil, - // nil. - generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error) - processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error) - - // On the client side, the next two methods are called in order. - - // This method may not be called if the server doesn't send a - // ServerKeyExchange message. - processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error - generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) -} - const ( // suiteECDHE indicates that the cipher suite involves elliptic curve // Diffie-Hellman. This means that it should only be selected when the @@ -144,12 +127,10 @@ const ( // suiteSHA384 indicates that the cipher suite uses SHA384 as the // handshake hash. suiteSHA384 - // suiteDefaultOff indicates that this cipher suite is not included by - // default. - suiteDefaultOff ) -// A cipherSuite is a specific combination of key agreement, cipher and MAC function. +// A cipherSuite is a TLS 1.0–1.2 cipher suite, and defines the key exchange +// mechanism, as well as the cipher+MAC pair or the AEAD. type cipherSuite struct { id uint16 // the lengths, in bytes, of the key material needed for each component. @@ -164,37 +145,33 @@ type cipherSuite struct { aead func(key, fixedNonce []byte) aead } -var cipherSuites = []*cipherSuite{ - // Ciphersuite order is chosen so that ECDHE comes before plain RSA and - // AEADs are the top preference. +var cipherSuites = []*cipherSuite{ // TODO: replace with a map, since the order doesn't matter. {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 32, 0, 12, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadChaCha20Poly1305}, {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, 32, 0, 12, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, nil, nil, aeadChaCha20Poly1305}, {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM}, {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, nil, nil, aeadAESGCM}, {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, - {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteDefaultOff, cipherAES, macSHA256, nil}, + {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12, cipherAES, macSHA256, nil}, {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, - {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12 | suiteDefaultOff, cipherAES, macSHA256, nil}, + {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, cipherAES, macSHA256, nil}, {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherAES, macSHA1, nil}, {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherAES, macSHA1, nil}, {TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM}, {TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, - {TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12 | suiteDefaultOff, cipherAES, macSHA256, nil}, + {TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil}, {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil}, {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil}, {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil}, {TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil}, - - // RC4-based cipher suites are disabled by default. - {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteDefaultOff, cipherRC4, macSHA1, nil}, - {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE | suiteDefaultOff, cipherRC4, macSHA1, nil}, - {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteDefaultOff, cipherRC4, macSHA1, nil}, + {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, 0, cipherRC4, macSHA1, nil}, + {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE, cipherRC4, macSHA1, nil}, + {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherRC4, macSHA1, nil}, } -// selectCipherSuite returns the first cipher suite from ids which is also in -// supportedIDs and passes the ok filter. +// selectCipherSuite returns the first TLS 1.0–1.2 cipher suite from ids which +// is also in supportedIDs and passes the ok filter. func selectCipherSuite(ids, supportedIDs []uint16, ok func(*cipherSuite) bool) *cipherSuite { for _, id := range ids { candidate := cipherSuiteByID(id) @@ -220,12 +197,208 @@ type cipherSuiteTLS13 struct { hash crypto.Hash } -var cipherSuitesTLS13 = []*cipherSuiteTLS13{ +var cipherSuitesTLS13 = []*cipherSuiteTLS13{ // TODO: replace with a map. {TLS_AES_128_GCM_SHA256, 16, aeadAESGCMTLS13, crypto.SHA256}, {TLS_CHACHA20_POLY1305_SHA256, 32, aeadChaCha20Poly1305, crypto.SHA256}, {TLS_AES_256_GCM_SHA384, 32, aeadAESGCMTLS13, crypto.SHA384}, } +// cipherSuitesPreferenceOrder is the order in which we'll select (on the +// server) or advertise (on the client) TLS 1.0–1.2 cipher suites. +// +// Cipher suites are filtered but not reordered based on the application and +// peer's preferences, meaning we'll never select a suite lower in this list if +// any higher one is available. This makes it more defensible to keep weaker +// cipher suites enabled, especially on the server side where we get the last +// word, since there are no known downgrade attacks on cipher suites selection. +// +// The list is sorted by applying the following priority rules, stopping at the +// first (most important) applicable one: +// +// - Anything else comes before RC4 +// +// RC4 has practically exploitable biases. See https://www.rc4nomore.com. +// +// - Anything else comes before CBC_SHA256 +// +// SHA-256 variants of the CBC ciphersuites don't implement any Lucky13 +// countermeasures. See http://www.isg.rhul.ac.uk/tls/Lucky13.html and +// https://www.imperialviolet.org/2013/02/04/luckythirteen.html. +// +// - Anything else comes before 3DES +// +// 3DES has 64-bit blocks, which makes it fundamentally susceptible to +// birthday attacks. See https://sweet32.info. +// +// - ECDHE comes before anything else +// +// Once we got the broken stuff out of the way, the most important +// property a cipher suite can have is forward secrecy. We don't +// implement FFDHE, so that means ECDHE. +// +// - AEADs come before CBC ciphers +// +// Even with Lucky13 countermeasures, MAC-then-Encrypt CBC cipher suites +// are fundamentally fragile, and suffered from an endless sequence of +// padding oracle attacks. See https://eprint.iacr.org/2015/1129, +// https://www.imperialviolet.org/2014/12/08/poodleagain.html, and +// https://blog.cloudflare.com/yet-another-padding-oracle-in-openssl-cbc-ciphersuites/. +// +// - AES comes before ChaCha20 +// +// When AES hardware is available, AES-128-GCM and AES-256-GCM are faster +// than ChaCha20Poly1305. +// +// When AES hardware is not available, AES-128-GCM is one or more of: much +// slower, way more complex, and less safe (because not constant time) +// than ChaCha20Poly1305. +// +// We use this list if we think both peers have AES hardware, and +// cipherSuitesPreferenceOrderNoAES otherwise. +// +// - AES-128 comes before AES-256 +// +// The only potential advantages of AES-256 are better multi-target +// margins, and hypothetical post-quantum properties. Neither apply to +// TLS, and AES-256 is slower due to its four extra rounds (which don't +// contribute to the advantages above). +// +// - ECDSA comes before RSA +// +// The relative order of ECDSA and RSA cipher suites doesn't matter, +// as they depend on the certificate. Pick one to get a stable order. +// +var cipherSuitesPreferenceOrder = []uint16{ + // AEADs w/ ECDHE + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + + // CBC w/ ECDHE + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + + // AEADs w/o ECDHE + TLS_RSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_AES_256_GCM_SHA384, + + // CBC w/o ECDHE + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_RSA_WITH_AES_256_CBC_SHA, + + // 3DES + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_RSA_WITH_3DES_EDE_CBC_SHA, + + // CBC_SHA256 + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_RSA_WITH_AES_128_CBC_SHA256, + + // RC4 + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, + TLS_RSA_WITH_RC4_128_SHA, +} + +var cipherSuitesPreferenceOrderNoAES = []uint16{ + // ChaCha20Poly1305 + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + + // AES-GCM w/ ECDHE + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + + // The rest of cipherSuitesPreferenceOrder. + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + TLS_RSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_AES_256_GCM_SHA384, + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_RSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, + TLS_RSA_WITH_RC4_128_SHA, +} + +// disabledCipherSuites are not used unless explicitly listed in +// Config.CipherSuites. They MUST be at the end of cipherSuitesPreferenceOrder. +var disabledCipherSuites = []uint16{ + // CBC_SHA256 + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_RSA_WITH_AES_128_CBC_SHA256, + + // RC4 + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, + TLS_RSA_WITH_RC4_128_SHA, +} + +var ( + defaultCipherSuitesLen = len(cipherSuitesPreferenceOrder) - len(disabledCipherSuites) + defaultCipherSuites = cipherSuitesPreferenceOrder[:defaultCipherSuitesLen] +) + +// defaultCipherSuitesTLS13 is also the preference order, since there are no +// disabled by default TLS 1.3 cipher suites. The same AES vs ChaCha20 logic as +// cipherSuitesPreferenceOrder applies. +var defaultCipherSuitesTLS13 = []uint16{ + TLS_AES_128_GCM_SHA256, + TLS_AES_256_GCM_SHA384, + TLS_CHACHA20_POLY1305_SHA256, +} + +var defaultCipherSuitesTLS13NoAES = []uint16{ + TLS_CHACHA20_POLY1305_SHA256, + TLS_AES_128_GCM_SHA256, + TLS_AES_256_GCM_SHA384, +} + +var ( + hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ + hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL + // Keep in sync with crypto/aes/cipher_s390x.go. + hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && + (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM) + + hasAESGCMHardwareSupport = runtime.GOARCH == "amd64" && hasGCMAsmAMD64 || + runtime.GOARCH == "arm64" && hasGCMAsmARM64 || + runtime.GOARCH == "s390x" && hasGCMAsmS390X +) + +var aesgcmCiphers = map[uint16]bool{ + // TLS 1.2 + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: true, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: true, + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: true, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: true, + // TLS 1.3 + TLS_AES_128_GCM_SHA256: true, + TLS_AES_256_GCM_SHA384: true, +} + +var nonAESGCMAEADCiphers = map[uint16]bool{ + // TLS 1.2 + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: true, + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: true, + // TLS 1.3 + TLS_CHACHA20_POLY1305_SHA256: true, +} + +// aesgcmPreferred returns whether the first known cipher in the preference list +// is an AES-GCM cipher, implying the peer has hardware support for it. +func aesgcmPreferred(ciphers []uint16) bool { + for _, cID := range ciphers { + if c := cipherSuiteByID(cID); c != nil { + return aesgcmCiphers[cID] + } + if c := cipherSuiteTLS13ByID(cID); c != nil { + return aesgcmCiphers[cID] + } + } + return false +} + func cipherRC4(key, iv []byte, isRead bool) interface{} { cipher, _ := rc4.NewCipher(key) return cipher diff --git a/libgo/go/crypto/tls/common.go b/libgo/go/crypto/tls/common.go index eec6e1e..d561e61 100644 --- a/libgo/go/crypto/tls/common.go +++ b/libgo/go/crypto/tls/common.go @@ -7,6 +7,7 @@ package tls import ( "bytes" "container/list" + "context" "crypto" "crypto/ecdsa" "crypto/ed25519" @@ -17,11 +18,8 @@ import ( "crypto/x509" "errors" "fmt" - "internal/cpu" "io" "net" - "runtime" - "sort" "strings" "sync" "time" @@ -443,6 +441,16 @@ type ClientHelloInfo struct { // config is embedded by the GetCertificate or GetConfigForClient caller, // for use with SupportsCertificate. config *Config + + // ctx is the context of the handshake that is in progress. + ctx context.Context +} + +// Context returns the context of the handshake that is in progress. +// This context is a child of the context passed to HandshakeContext, +// if any, and is canceled when the handshake concludes. +func (c *ClientHelloInfo) Context() context.Context { + return c.ctx } // CertificateRequestInfo contains information from a server's @@ -461,6 +469,16 @@ type CertificateRequestInfo struct { // Version is the TLS version that was negotiated for this connection. Version uint16 + + // ctx is the context of the handshake that is in progress. + ctx context.Context +} + +// Context returns the context of the handshake that is in progress. +// This context is a child of the context passed to HandshakeContext, +// if any, and is canceled when the handshake concludes. +func (c *CertificateRequestInfo) Context() context.Context { + return c.ctx } // RenegotiationSupport enumerates the different levels of support for TLS @@ -597,7 +615,11 @@ type Config struct { RootCAs *x509.CertPool // NextProtos is a list of supported application level protocols, in - // order of preference. + // order of preference. If both peers support ALPN, the selected + // protocol will be one from this list, and the connection will fail + // if there is no mutually supported protocol. If NextProtos is empty + // or the peer doesn't support ALPN, the connection will succeed and + // ConnectionState.NegotiatedProtocol will be empty. NextProtos []string // ServerName is used to verify the hostname on the returned @@ -623,17 +645,21 @@ type Config struct { // testing or in combination with VerifyConnection or VerifyPeerCertificate. InsecureSkipVerify bool - // CipherSuites is a list of supported cipher suites for TLS versions up to - // TLS 1.2. If CipherSuites is nil, a default list of secure cipher suites - // is used, with a preference order based on hardware performance. The - // default cipher suites might change over Go versions. Note that TLS 1.3 - // ciphersuites are not configurable. + // CipherSuites is a list of enabled TLS 1.0–1.2 cipher suites. The order of + // the list is ignored. Note that TLS 1.3 ciphersuites are not configurable. + // + // If CipherSuites is nil, a safe default list is used. The default cipher + // suites might change over time. CipherSuites []uint16 - // PreferServerCipherSuites controls whether the server selects the - // client's most preferred ciphersuite, or the server's most preferred - // ciphersuite. If true then the server's preference, as expressed in - // the order of elements in CipherSuites, is used. + // PreferServerCipherSuites is a legacy field and has no effect. + // + // It used to control whether the server would follow the client's or the + // server's preference. Servers now select the best mutually supported + // cipher suite based on logic that takes into account inferred client + // hardware, server hardware, and security. + // + // Deprected: PreferServerCipherSuites is ignored. PreferServerCipherSuites bool // SessionTicketsDisabled may be set to true to disable session ticket and @@ -925,11 +951,10 @@ func (c *Config) time() time.Time { } func (c *Config) cipherSuites() []uint16 { - s := c.CipherSuites - if s == nil { - s = defaultCipherSuites() + if c.CipherSuites != nil { + return c.CipherSuites } - return s + return defaultCipherSuites } var supportedVersions = []uint16{ @@ -1419,87 +1444,6 @@ func defaultConfig() *Config { return &emptyConfig } -var ( - once sync.Once - varDefaultCipherSuites []uint16 - varDefaultCipherSuitesTLS13 []uint16 -) - -func defaultCipherSuites() []uint16 { - once.Do(initDefaultCipherSuites) - return varDefaultCipherSuites -} - -func defaultCipherSuitesTLS13() []uint16 { - once.Do(initDefaultCipherSuites) - return varDefaultCipherSuitesTLS13 -} - -var ( - hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ - hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL - // Keep in sync with crypto/aes/cipher_s390x.go. - hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM) - - hasAESGCMHardwareSupport = runtime.GOARCH == "amd64" && hasGCMAsmAMD64 || - runtime.GOARCH == "arm64" && hasGCMAsmARM64 || - runtime.GOARCH == "s390x" && hasGCMAsmS390X -) - -func initDefaultCipherSuites() { - var topCipherSuites []uint16 - - if hasAESGCMHardwareSupport { - // If AES-GCM hardware is provided then prioritise AES-GCM - // cipher suites. - topCipherSuites = []uint16{ - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, - } - varDefaultCipherSuitesTLS13 = []uint16{ - TLS_AES_128_GCM_SHA256, - TLS_CHACHA20_POLY1305_SHA256, - TLS_AES_256_GCM_SHA384, - } - } else { - // Without AES-GCM hardware, we put the ChaCha20-Poly1305 - // cipher suites first. - topCipherSuites = []uint16{ - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - } - varDefaultCipherSuitesTLS13 = []uint16{ - TLS_CHACHA20_POLY1305_SHA256, - TLS_AES_128_GCM_SHA256, - TLS_AES_256_GCM_SHA384, - } - } - - varDefaultCipherSuites = make([]uint16, 0, len(cipherSuites)) - varDefaultCipherSuites = append(varDefaultCipherSuites, topCipherSuites...) - -NextCipherSuite: - for _, suite := range cipherSuites { - if suite.flags&suiteDefaultOff != 0 { - continue - } - for _, existing := range varDefaultCipherSuites { - if existing == suite.id { - continue NextCipherSuite - } - } - varDefaultCipherSuites = append(varDefaultCipherSuites, suite.id) - } -} - func unexpectedMessageError(wanted, got interface{}) error { return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted) } @@ -1512,51 +1456,3 @@ func isSupportedSignatureAlgorithm(sigAlg SignatureScheme, supportedSignatureAlg } return false } - -var aesgcmCiphers = map[uint16]bool{ - // 1.2 - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: true, - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: true, - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: true, - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: true, - // 1.3 - TLS_AES_128_GCM_SHA256: true, - TLS_AES_256_GCM_SHA384: true, -} - -var nonAESGCMAEADCiphers = map[uint16]bool{ - // 1.2 - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: true, - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: true, - // 1.3 - TLS_CHACHA20_POLY1305_SHA256: true, -} - -// aesgcmPreferred returns whether the first valid cipher in the preference list -// is an AES-GCM cipher, implying the peer has hardware support for it. -func aesgcmPreferred(ciphers []uint16) bool { - for _, cID := range ciphers { - c := cipherSuiteByID(cID) - if c == nil { - c13 := cipherSuiteTLS13ByID(cID) - if c13 == nil { - continue - } - return aesgcmCiphers[cID] - } - return aesgcmCiphers[cID] - } - return false -} - -// deprioritizeAES reorders cipher preference lists by rearranging -// adjacent AEAD ciphers such that AES-GCM based ciphers are moved -// after other AEAD ciphers. It returns a fresh slice. -func deprioritizeAES(ciphers []uint16) []uint16 { - reordered := make([]uint16, len(ciphers)) - copy(reordered, ciphers) - sort.SliceStable(reordered, func(i, j int) bool { - return nonAESGCMAEADCiphers[reordered[i]] && aesgcmCiphers[reordered[j]] - }) - return reordered -} diff --git a/libgo/go/crypto/tls/conn.go b/libgo/go/crypto/tls/conn.go index 72ad52c..969f357 100644 --- a/libgo/go/crypto/tls/conn.go +++ b/libgo/go/crypto/tls/conn.go @@ -8,6 +8,7 @@ package tls import ( "bytes" + "context" "crypto/cipher" "crypto/subtle" "crypto/x509" @@ -27,7 +28,7 @@ type Conn struct { // constant conn net.Conn isClient bool - handshakeFn func() error // (*Conn).clientHandshake or serverHandshake + handshakeFn func(context.Context) error // (*Conn).clientHandshake or serverHandshake // handshakeStatus is 1 if the connection is currently transferring // application data (i.e. is not currently processing a handshake). @@ -1190,7 +1191,7 @@ func (c *Conn) handleRenegotiation() error { defer c.handshakeMutex.Unlock() atomic.StoreUint32(&c.handshakeStatus, 0) - if c.handshakeErr = c.clientHandshake(); c.handshakeErr == nil { + if c.handshakeErr = c.clientHandshake(context.Background()); c.handshakeErr == nil { c.handshakes++ } return c.handshakeErr @@ -1373,8 +1374,61 @@ func (c *Conn) closeNotify() error { // first Read or Write will call it automatically. // // For control over canceling or setting a timeout on a handshake, use -// the Dialer's DialContext method. +// HandshakeContext or the Dialer's DialContext method instead. func (c *Conn) Handshake() error { + return c.HandshakeContext(context.Background()) +} + +// HandshakeContext runs the client or server handshake +// protocol if it has not yet been run. +// +// The provided Context must be non-nil. If the context is canceled before +// the handshake is complete, the handshake is interrupted and an error is returned. +// Once the handshake has completed, cancellation of the context will not affect the +// connection. +// +// Most uses of this package need not call HandshakeContext explicitly: the +// first Read or Write will call it automatically. +func (c *Conn) HandshakeContext(ctx context.Context) error { + // Delegate to unexported method for named return + // without confusing documented signature. + return c.handshakeContext(ctx) +} + +func (c *Conn) handshakeContext(ctx context.Context) (ret error) { + handshakeCtx, cancel := context.WithCancel(ctx) + // Note: defer this before starting the "interrupter" goroutine + // so that we can tell the difference between the input being canceled and + // this cancellation. In the former case, we need to close the connection. + defer cancel() + + // Start the "interrupter" goroutine, if this context might be canceled. + // (The background context cannot). + // + // The interrupter goroutine waits for the input context to be done and + // closes the connection if this happens before the function returns. + if ctx.Done() != nil { + done := make(chan struct{}) + interruptRes := make(chan error, 1) + defer func() { + close(done) + if ctxErr := <-interruptRes; ctxErr != nil { + // Return context error to user. + ret = ctxErr + } + }() + go func() { + select { + case <-handshakeCtx.Done(): + // Close the connection, discarding the error + _ = c.conn.Close() + interruptRes <- handshakeCtx.Err() + case <-done: + interruptRes <- nil + } + }() + } + c.handshakeMutex.Lock() defer c.handshakeMutex.Unlock() @@ -1388,7 +1442,7 @@ func (c *Conn) Handshake() error { c.in.Lock() defer c.in.Unlock() - c.handshakeErr = c.handshakeFn() + c.handshakeErr = c.handshakeFn(handshakeCtx) if c.handshakeErr == nil { c.handshakes++ } else { diff --git a/libgo/go/crypto/tls/generate_cert.go b/libgo/go/crypto/tls/generate_cert.go index 1857185..7ea90f8 100644 --- a/libgo/go/crypto/tls/generate_cert.go +++ b/libgo/go/crypto/tls/generate_cert.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // Generate a self-signed X.509 certificate for a TLS server. Outputs to diff --git a/libgo/go/crypto/tls/handshake_client.go b/libgo/go/crypto/tls/handshake_client.go index e684b21..4af3d99 100644 --- a/libgo/go/crypto/tls/handshake_client.go +++ b/libgo/go/crypto/tls/handshake_client.go @@ -6,6 +6,7 @@ package tls import ( "bytes" + "context" "crypto" "crypto/ecdsa" "crypto/ed25519" @@ -24,6 +25,7 @@ import ( type clientHandshakeState struct { c *Conn + ctx context.Context serverHello *serverHelloMsg hello *clientHelloMsg suite *cipherSuite @@ -82,22 +84,24 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) { hello.secureRenegotiation = c.clientFinished[:] } - possibleCipherSuites := config.cipherSuites() - hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites)) + preferenceOrder := cipherSuitesPreferenceOrder + if !hasAESGCMHardwareSupport { + preferenceOrder = cipherSuitesPreferenceOrderNoAES + } + configCipherSuites := config.cipherSuites() + hello.cipherSuites = make([]uint16, 0, len(configCipherSuites)) - for _, suiteId := range possibleCipherSuites { - for _, suite := range cipherSuites { - if suite.id != suiteId { - continue - } - // Don't advertise TLS 1.2-only cipher suites unless - // we're attempting TLS 1.2. - if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 { - break - } - hello.cipherSuites = append(hello.cipherSuites, suiteId) - break + for _, suiteId := range preferenceOrder { + suite := mutualCipherSuite(configCipherSuites, suiteId) + if suite == nil { + continue + } + // Don't advertise TLS 1.2-only cipher suites unless + // we're attempting TLS 1.2. + if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 { + continue } + hello.cipherSuites = append(hello.cipherSuites, suiteId) } _, err := io.ReadFull(config.rand(), hello.random) @@ -118,7 +122,11 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) { var params ecdheParameters if hello.supportedVersions[0] == VersionTLS13 { - hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13()...) + if hasAESGCMHardwareSupport { + hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13...) + } else { + hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...) + } curveID := config.curvePreferences()[0] if _, ok := curveForCurveID(curveID); curveID != X25519 && !ok { @@ -134,7 +142,7 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) { return hello, params, nil } -func (c *Conn) clientHandshake() (err error) { +func (c *Conn) clientHandshake(ctx context.Context) (err error) { if c.config == nil { c.config = defaultConfig() } @@ -198,6 +206,7 @@ func (c *Conn) clientHandshake() (err error) { if c.vers == VersionTLS13 { hs := &clientHandshakeStateTLS13{ c: c, + ctx: ctx, serverHello: serverHello, hello: hello, ecdheParams: ecdheParams, @@ -212,6 +221,7 @@ func (c *Conn) clientHandshake() (err error) { hs := &clientHandshakeState{ c: c, + ctx: ctx, serverHello: serverHello, hello: hello, session: session, @@ -540,7 +550,7 @@ func (hs *clientHandshakeState) doFullHandshake() error { certRequested = true hs.finishedHash.Write(certReq.marshal()) - cri := certificateRequestInfoFromMsg(c.vers, certReq) + cri := certificateRequestInfoFromMsg(hs.ctx, c.vers, certReq) if chainToSend, err = c.getClientCertificate(cri); err != nil { c.sendAlert(alertInternalError) return err @@ -701,17 +711,11 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) { } } - if hs.serverHello.alpnProtocol != "" { - if len(hs.hello.alpnProtocols) == 0 { - c.sendAlert(alertUnsupportedExtension) - return false, errors.New("tls: server advertised unrequested ALPN extension") - } - if mutualProtocol([]string{hs.serverHello.alpnProtocol}, hs.hello.alpnProtocols) == "" { - c.sendAlert(alertUnsupportedExtension) - return false, errors.New("tls: server selected unadvertised ALPN protocol") - } - c.clientProtocol = hs.serverHello.alpnProtocol + if err := checkALPN(hs.hello.alpnProtocols, hs.serverHello.alpnProtocol); err != nil { + c.sendAlert(alertUnsupportedExtension) + return false, err } + c.clientProtocol = hs.serverHello.alpnProtocol c.scts = hs.serverHello.scts @@ -743,6 +747,23 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) { return true, nil } +// checkALPN ensure that the server's choice of ALPN protocol is compatible with +// the protocols that we advertised in the Client Hello. +func checkALPN(clientProtos []string, serverProto string) error { + if serverProto == "" { + return nil + } + if len(clientProtos) == 0 { + return errors.New("tls: server advertised unrequested ALPN extension") + } + for _, proto := range clientProtos { + if proto == serverProto { + return nil + } + } + return errors.New("tls: server selected unadvertised ALPN protocol") +} + func (hs *clientHandshakeState) readFinished(out []byte) error { c := hs.c @@ -880,10 +901,11 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error { // certificateRequestInfoFromMsg generates a CertificateRequestInfo from a TLS // <= 1.2 CertificateRequest, making an effort to fill in missing information. -func certificateRequestInfoFromMsg(vers uint16, certReq *certificateRequestMsg) *CertificateRequestInfo { +func certificateRequestInfoFromMsg(ctx context.Context, vers uint16, certReq *certificateRequestMsg) *CertificateRequestInfo { cri := &CertificateRequestInfo{ AcceptableCAs: certReq.certificateAuthorities, Version: vers, + ctx: ctx, } var rsaAvail, ecAvail bool @@ -968,19 +990,6 @@ func clientSessionCacheKey(serverAddr net.Addr, config *Config) string { return serverAddr.String() } -// mutualProtocol finds the mutual ALPN protocol given list of possible -// protocols and a list of the preference order. -func mutualProtocol(protos, preferenceProtos []string) string { - for _, s := range preferenceProtos { - for _, c := range protos { - if s == c { - return s - } - } - } - return "" -} - // hostnameInSNI converts name into an appropriate hostname for SNI. // Literal IP addresses and absolute FQDNs are not permitted as SNI values. // See RFC 6066, Section 3. diff --git a/libgo/go/crypto/tls/handshake_client_test.go b/libgo/go/crypto/tls/handshake_client_test.go index 12b0254..b6eb488 100644 --- a/libgo/go/crypto/tls/handshake_client_test.go +++ b/libgo/go/crypto/tls/handshake_client_test.go @@ -6,6 +6,7 @@ package tls import ( "bytes" + "context" "crypto/rsa" "crypto/x509" "encoding/base64" @@ -20,6 +21,7 @@ import ( "os/exec" "path/filepath" "reflect" + "runtime" "strconv" "strings" "testing" @@ -42,7 +44,7 @@ const ( // opensslSentinel on the connection. opensslSendSentinel - // opensslKeyUpdate causes OpenSSL to send send a key update message to the + // opensslKeyUpdate causes OpenSSL to send a key update message to the // client and request one back. opensslKeyUpdate ) @@ -1222,6 +1224,56 @@ func TestHandshakeClientALPNMatch(t *testing.T) { runClientTestTLS13(t, test) } +func TestServerSelectingUnconfiguredApplicationProtocol(t *testing.T) { + // This checks that the server can't select an application protocol that the + // client didn't offer. + + c, s := localPipe(t) + errChan := make(chan error, 1) + + go func() { + client := Client(c, &Config{ + ServerName: "foo", + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, + NextProtos: []string{"http", "something-else"}, + }) + errChan <- client.Handshake() + }() + + var header [5]byte + if _, err := io.ReadFull(s, header[:]); err != nil { + t.Fatal(err) + } + recordLen := int(header[3])<<8 | int(header[4]) + + record := make([]byte, recordLen) + if _, err := io.ReadFull(s, record); err != nil { + t.Fatal(err) + } + + serverHello := &serverHelloMsg{ + vers: VersionTLS12, + random: make([]byte, 32), + cipherSuite: TLS_RSA_WITH_AES_128_GCM_SHA256, + alpnProtocol: "how-about-this", + } + serverHelloBytes := serverHello.marshal() + + s.Write([]byte{ + byte(recordTypeHandshake), + byte(VersionTLS12 >> 8), + byte(VersionTLS12 & 0xff), + byte(len(serverHelloBytes) >> 8), + byte(len(serverHelloBytes)), + }) + s.Write(serverHelloBytes) + s.Close() + + if err := <-errChan; !strings.Contains(err.Error(), "server selected unadvertised ALPN protocol") { + t.Fatalf("Expected error about unconfigured cipher suite but got %q", err) + } +} + // sctsBase64 contains data from `openssl s_client -serverinfo 18 -connect ritter.vg:443` const sctsBase64 = "ABIBaQFnAHUApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFHl5nuFgAABAMARjBEAiAcS4JdlW5nW9sElUv2zvQyPoZ6ejKrGGB03gjaBZFMLwIgc1Qbbn+hsH0RvObzhS+XZhr3iuQQJY8S9G85D9KeGPAAdgBo9pj4H2SCvjqM7rkoHUz8cVFdZ5PURNEKZ6y7T0/7xAAAAUeX4bVwAAAEAwBHMEUCIDIhFDgG2HIuADBkGuLobU5a4dlCHoJLliWJ1SYT05z6AiEAjxIoZFFPRNWMGGIjskOTMwXzQ1Wh2e7NxXE1kd1J0QsAdgDuS723dc5guuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAUhcZIqHAAAEAwBHMEUCICmJ1rBT09LpkbzxtUC+Hi7nXLR0J+2PmwLp+sJMuqK+AiEAr0NkUnEVKVhAkccIFpYDqHOlZaBsuEhWWrYpg2RtKp0=" @@ -1528,7 +1580,7 @@ func testVerifyConnection(t *testing.T, version uint16) { } if c.DidResume { return nil - // The SCTs and OCSP Responce are dropped on resumption. + // The SCTs and OCSP Response are dropped on resumption. // See http://golang.org/issue/39075. } if len(c.OCSPResponse) == 0 { @@ -1569,7 +1621,7 @@ func testVerifyConnection(t *testing.T, version uint16) { } if c.DidResume { return nil - // The SCTs and OCSP Responce are dropped on resumption. + // The SCTs and OCSP Response are dropped on resumption. // See http://golang.org/issue/39075. } if len(c.OCSPResponse) == 0 { @@ -1619,7 +1671,7 @@ func testVerifyConnection(t *testing.T, version uint16) { } if c.DidResume { return nil - // The SCTs and OCSP Responce are dropped on resumption. + // The SCTs and OCSP Response are dropped on resumption. // See http://golang.org/issue/39075. } if len(c.OCSPResponse) == 0 { @@ -2511,3 +2563,35 @@ func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) { serverConfig.Certificates[0].SignedCertificateTimestamps, ccs.SignedCertificateTimestamps) } } + +// TestClientHandshakeContextCancellation tests that cancelling +// the context given to the client side conn.HandshakeContext +// interrupts the in-progress handshake. +func TestClientHandshakeContextCancellation(t *testing.T) { + c, s := localPipe(t) + ctx, cancel := context.WithCancel(context.Background()) + unblockServer := make(chan struct{}) + defer close(unblockServer) + go func() { + cancel() + <-unblockServer + _ = s.Close() + }() + cli := Client(c, testConfig) + // Initiates client side handshake, which will block until the client hello is read + // by the server, unless the cancellation works. + err := cli.HandshakeContext(ctx) + if err == nil { + t.Fatal("Client handshake did not error when the context was canceled") + } + if err != context.Canceled { + t.Errorf("Unexpected client handshake error: %v", err) + } + if runtime.GOARCH == "wasm" { + t.Skip("conn.Close does not error as expected when called multiple times on WASM") + } + err = cli.Close() + if err == nil { + t.Error("Client connection was not closed when the context was canceled") + } +} diff --git a/libgo/go/crypto/tls/handshake_client_tls13.go b/libgo/go/crypto/tls/handshake_client_tls13.go index daa5d97..eb59ac9 100644 --- a/libgo/go/crypto/tls/handshake_client_tls13.go +++ b/libgo/go/crypto/tls/handshake_client_tls13.go @@ -6,6 +6,7 @@ package tls import ( "bytes" + "context" "crypto" "crypto/hmac" "crypto/rsa" @@ -17,6 +18,7 @@ import ( type clientHandshakeStateTLS13 struct { c *Conn + ctx context.Context serverHello *serverHelloMsg hello *clientHelloMsg ecdheParams ecdheParameters @@ -394,17 +396,11 @@ func (hs *clientHandshakeStateTLS13) readServerParameters() error { } hs.transcript.Write(encryptedExtensions.marshal()) - if encryptedExtensions.alpnProtocol != "" { - if len(hs.hello.alpnProtocols) == 0 { - c.sendAlert(alertUnsupportedExtension) - return errors.New("tls: server advertised unrequested ALPN extension") - } - if mutualProtocol([]string{encryptedExtensions.alpnProtocol}, hs.hello.alpnProtocols) == "" { - c.sendAlert(alertUnsupportedExtension) - return errors.New("tls: server selected unadvertised ALPN protocol") - } - c.clientProtocol = encryptedExtensions.alpnProtocol + if err := checkALPN(hs.hello.alpnProtocols, encryptedExtensions.alpnProtocol); err != nil { + c.sendAlert(alertUnsupportedExtension) + return err } + c.clientProtocol = encryptedExtensions.alpnProtocol return nil } @@ -555,6 +551,7 @@ func (hs *clientHandshakeStateTLS13) sendClientCertificate() error { AcceptableCAs: hs.certReq.certificateAuthorities, SignatureSchemes: hs.certReq.supportedSignatureAlgorithms, Version: c.vers, + ctx: hs.ctx, }) if err != nil { return err diff --git a/libgo/go/crypto/tls/handshake_server.go b/libgo/go/crypto/tls/handshake_server.go index 9c3e0f6..43f30e2 100644 --- a/libgo/go/crypto/tls/handshake_server.go +++ b/libgo/go/crypto/tls/handshake_server.go @@ -5,6 +5,7 @@ package tls import ( + "context" "crypto" "crypto/ecdsa" "crypto/ed25519" @@ -23,6 +24,7 @@ import ( // It's discarded once the handshake has completed. type serverHandshakeState struct { c *Conn + ctx context.Context clientHello *clientHelloMsg hello *serverHelloMsg suite *cipherSuite @@ -37,8 +39,8 @@ type serverHandshakeState struct { } // serverHandshake performs a TLS handshake as a server. -func (c *Conn) serverHandshake() error { - clientHello, err := c.readClientHello() +func (c *Conn) serverHandshake(ctx context.Context) error { + clientHello, err := c.readClientHello(ctx) if err != nil { return err } @@ -46,6 +48,7 @@ func (c *Conn) serverHandshake() error { if c.vers == VersionTLS13 { hs := serverHandshakeStateTLS13{ c: c, + ctx: ctx, clientHello: clientHello, } return hs.handshake() @@ -53,6 +56,7 @@ func (c *Conn) serverHandshake() error { hs := serverHandshakeState{ c: c, + ctx: ctx, clientHello: clientHello, } return hs.handshake() @@ -124,7 +128,7 @@ func (hs *serverHandshakeState) handshake() error { } // readClientHello reads a ClientHello message and selects the protocol version. -func (c *Conn) readClientHello() (*clientHelloMsg, error) { +func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) { msg, err := c.readHandshake() if err != nil { return nil, err @@ -138,7 +142,7 @@ func (c *Conn) readClientHello() (*clientHelloMsg, error) { var configForClient *Config originalConfig := c.config if c.config.GetConfigForClient != nil { - chi := clientHelloInfo(c, clientHello) + chi := clientHelloInfo(ctx, c, clientHello) if configForClient, err = c.config.GetConfigForClient(chi); err != nil { c.sendAlert(alertInternalError) return nil, err @@ -213,14 +217,15 @@ func (hs *serverHandshakeState) processClientHello() error { c.serverName = hs.clientHello.serverName } - if len(hs.clientHello.alpnProtocols) > 0 { - if selectedProto := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); selectedProto != "" { - hs.hello.alpnProtocol = selectedProto - c.clientProtocol = selectedProto - } + selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols) + if err != nil { + c.sendAlert(alertNoApplicationProtocol) + return err } + hs.hello.alpnProtocol = selectedProto + c.clientProtocol = selectedProto - hs.cert, err = c.config.getCertificate(clientHelloInfo(c, hs.clientHello)) + hs.cert, err = c.config.getCertificate(clientHelloInfo(hs.ctx, c, hs.clientHello)) if err != nil { if err == errNoCertificates { c.sendAlert(alertUnrecognizedName) @@ -270,6 +275,34 @@ func (hs *serverHandshakeState) processClientHello() error { return nil } +// negotiateALPN picks a shared ALPN protocol that both sides support in server +// preference order. If ALPN is not configured or the peer doesn't support it, +// it returns "" and no error. +func negotiateALPN(serverProtos, clientProtos []string) (string, error) { + if len(serverProtos) == 0 || len(clientProtos) == 0 { + return "", nil + } + var http11fallback bool + for _, s := range serverProtos { + for _, c := range clientProtos { + if s == c { + return s, nil + } + if s == "h2" && c == "http/1.1" { + http11fallback = true + } + } + } + // As a special case, let http/1.1 clients connect to h2 servers as if they + // didn't support ALPN. We used not to enforce protocol overlap, so over + // time a number of HTTP servers were configured with only "h2", but + // expected to accept connections from "http/1.1" clients. See Issue 46310. + if http11fallback { + return "", nil + } + return "", fmt.Errorf("tls: client requested unsupported application protocols (%s)", clientProtos) +} + // supportsECDHE returns whether ECDHE key exchanges can be used with this // pre-TLS 1.3 client. func supportsECDHE(c *Config, supportedCurves []CurveID, supportedPoints []uint8) bool { @@ -295,30 +328,23 @@ func supportsECDHE(c *Config, supportedCurves []CurveID, supportedPoints []uint8 func (hs *serverHandshakeState) pickCipherSuite() error { c := hs.c - var preferenceList, supportedList []uint16 - if c.config.PreferServerCipherSuites { - preferenceList = c.config.cipherSuites() - supportedList = hs.clientHello.cipherSuites - - // If the client does not seem to have hardware support for AES-GCM, - // and the application did not specify a cipher suite preference order, - // prefer other AEAD ciphers even if we prioritized AES-GCM ciphers - // by default. - if c.config.CipherSuites == nil && !aesgcmPreferred(hs.clientHello.cipherSuites) { - preferenceList = deprioritizeAES(preferenceList) - } - } else { - preferenceList = hs.clientHello.cipherSuites - supportedList = c.config.cipherSuites() + preferenceOrder := cipherSuitesPreferenceOrder + if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) { + preferenceOrder = cipherSuitesPreferenceOrderNoAES + } - // If we don't have hardware support for AES-GCM, prefer other AEAD - // ciphers even if the client prioritized AES-GCM. - if !hasAESGCMHardwareSupport { - preferenceList = deprioritizeAES(preferenceList) + configCipherSuites := c.config.cipherSuites() + preferenceList := make([]uint16, 0, len(configCipherSuites)) + for _, suiteID := range preferenceOrder { + for _, id := range configCipherSuites { + if id == suiteID { + preferenceList = append(preferenceList, id) + break + } } } - hs.suite = selectCipherSuite(preferenceList, supportedList, hs.cipherSuiteOk) + hs.suite = selectCipherSuite(preferenceList, hs.clientHello.cipherSuites, hs.cipherSuiteOk) if hs.suite == nil { c.sendAlert(alertHandshakeFailure) return errors.New("tls: no cipher suite supported by both client and server") @@ -828,7 +854,7 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error { return nil } -func clientHelloInfo(c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo { +func clientHelloInfo(ctx context.Context, c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo { supportedVersions := clientHello.supportedVersions if len(clientHello.supportedVersions) == 0 { supportedVersions = supportedVersionsFromMax(clientHello.vers) @@ -844,5 +870,6 @@ func clientHelloInfo(c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo { SupportedVersions: supportedVersions, Conn: c.conn, config: c.config, + ctx: ctx, } } diff --git a/libgo/go/crypto/tls/handshake_server_test.go b/libgo/go/crypto/tls/handshake_server_test.go index d6bf9e4..f61b4c8 100644 --- a/libgo/go/crypto/tls/handshake_server_test.go +++ b/libgo/go/crypto/tls/handshake_server_test.go @@ -6,6 +6,7 @@ package tls import ( "bytes" + "context" "crypto" "crypto/elliptic" "crypto/x509" @@ -17,6 +18,7 @@ import ( "os" "os/exec" "path/filepath" + "runtime" "strings" "testing" "time" @@ -38,10 +40,12 @@ func testClientHelloFailure(t *testing.T, serverConfig *Config, m handshakeMessa cli.writeRecord(recordTypeHandshake, m.marshal()) c.Close() }() + ctx := context.Background() conn := Server(s, serverConfig) - ch, err := conn.readClientHello() + ch, err := conn.readClientHello(ctx) hs := serverHandshakeState{ c: conn, + ctx: ctx, clientHello: ch, } if err == nil { @@ -393,30 +397,30 @@ func TestVersion(t *testing.T) { func TestCipherSuitePreference(t *testing.T) { serverConfig := &Config{ - CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA}, + CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256}, Certificates: testConfig.Certificates, - MaxVersion: VersionTLS11, + MaxVersion: VersionTLS12, + GetConfigForClient: func(chi *ClientHelloInfo) (*Config, error) { + if chi.CipherSuites[0] != TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 { + t.Error("the advertised order should not depend on Config.CipherSuites") + } + if len(chi.CipherSuites) != 2+len(defaultCipherSuitesTLS13) { + t.Error("the advertised TLS 1.2 suites should be filtered by Config.CipherSuites") + } + return nil, nil + }, } clientConfig := &Config{ - CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_RC4_128_SHA}, + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256}, InsecureSkipVerify: true, } state, _, err := testHandshake(t, clientConfig, serverConfig) if err != nil { t.Fatalf("handshake failed: %s", err) } - if state.CipherSuite != TLS_RSA_WITH_AES_128_CBC_SHA { - // By default the server should use the client's preference. - t.Fatalf("Client's preference was not used, got %x", state.CipherSuite) - } - - serverConfig.PreferServerCipherSuites = true - state, _, err = testHandshake(t, clientConfig, serverConfig) - if err != nil { - t.Fatalf("handshake failed: %s", err) - } - if state.CipherSuite != TLS_RSA_WITH_RC4_128_SHA { - t.Fatalf("Server's preference was not used, got %x", state.CipherSuite) + if state.CipherSuite != TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 { + t.Error("the preference order should not depend on Config.CipherSuites") } } @@ -916,13 +920,48 @@ func TestHandshakeServerALPNNoMatch(t *testing.T) { name: "ALPN-NoMatch", // Note that this needs OpenSSL 1.0.2 because that is the first // version that supports the -alpn flag. + command: []string{"openssl", "s_client", "-alpn", "proto2,proto1", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"}, + config: config, + expectHandshakeErrorIncluding: "client requested unsupported application protocol", + } + runServerTestTLS12(t, test) + runServerTestTLS13(t, test) +} + +func TestHandshakeServerALPNNotConfigured(t *testing.T) { + config := testConfig.Clone() + config.NextProtos = nil + + test := &serverTest{ + name: "ALPN-NotConfigured", + // Note that this needs OpenSSL 1.0.2 because that is the first + // version that supports the -alpn flag. command: []string{"openssl", "s_client", "-alpn", "proto2,proto1", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"}, config: config, validate: func(state ConnectionState) error { - // Rather than reject the connection, Go doesn't select - // a protocol when there is no overlap. if state.NegotiatedProtocol != "" { - return fmt.Errorf("Got protocol %q, wanted ''", state.NegotiatedProtocol) + return fmt.Errorf("Got protocol %q, wanted nothing", state.NegotiatedProtocol) + } + return nil + }, + } + runServerTestTLS12(t, test) + runServerTestTLS13(t, test) +} + +func TestHandshakeServerALPNFallback(t *testing.T) { + config := testConfig.Clone() + config.NextProtos = []string{"proto1", "h2", "proto2"} + + test := &serverTest{ + name: "ALPN-Fallback", + // Note that this needs OpenSSL 1.0.2 because that is the first + // version that supports the -alpn flag. + command: []string{"openssl", "s_client", "-alpn", "proto3,http/1.1,proto4", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"}, + config: config, + validate: func(state ConnectionState) error { + if state.NegotiatedProtocol != "" { + return fmt.Errorf("Got protocol %q, wanted nothing", state.NegotiatedProtocol) } return nil }, @@ -1032,37 +1071,6 @@ func TestHandshakeServerEmptyCertificates(t *testing.T) { testClientHelloFailure(t, serverConfig, clientHello, "no certificates") } -// TestCipherSuiteCertPreferance ensures that we select an RSA ciphersuite with -// an RSA certificate and an ECDSA ciphersuite with an ECDSA certificate. -func TestCipherSuiteCertPreferenceECDSA(t *testing.T) { - config := testConfig.Clone() - config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA} - config.PreferServerCipherSuites = true - - test := &serverTest{ - name: "CipherSuiteCertPreferenceRSA", - config: config, - } - runServerTestTLS12(t, test) - - config = testConfig.Clone() - config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA} - config.Certificates = []Certificate{ - { - Certificate: [][]byte{testECDSACertificate}, - PrivateKey: testECDSAPrivateKey, - }, - } - config.BuildNameToCertificate() - config.PreferServerCipherSuites = true - - test = &serverTest{ - name: "CipherSuiteCertPreferenceECDSA", - config: config, - } - runServerTestTLS12(t, test) -} - func TestServerResumption(t *testing.T) { sessionFilePath := tempFile("") defer os.Remove(sessionFilePath) @@ -1160,7 +1168,7 @@ func TestFallbackSCSV(t *testing.T) { func TestHandshakeServerExportKeyingMaterial(t *testing.T) { test := &serverTest{ name: "ExportKeyingMaterial", - command: []string{"openssl", "s_client", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"}, + command: []string{"openssl", "s_client", "-cipher", "ECDHE-RSA-AES256-SHA", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"}, config: testConfig.Clone(), validate: func(state ConnectionState) error { if km, err := state.ExportKeyingMaterial("test", nil, 42); err != nil { @@ -1421,9 +1429,11 @@ func TestSNIGivenOnFailure(t *testing.T) { c.Close() }() conn := Server(s, serverConfig) - ch, err := conn.readClientHello() + ctx := context.Background() + ch, err := conn.readClientHello(ctx) hs := serverHandshakeState{ c: conn, + ctx: ctx, clientHello: ch, } if err == nil { @@ -1679,15 +1689,14 @@ func TestMultipleCertificates(t *testing.T) { func TestAESCipherReordering(t *testing.T) { currentAESSupport := hasAESGCMHardwareSupport - defer func() { hasAESGCMHardwareSupport = currentAESSupport; initDefaultCipherSuites() }() + defer func() { hasAESGCMHardwareSupport = currentAESSupport }() tests := []struct { - name string - clientCiphers []uint16 - serverHasAESGCM bool - preferServerCipherSuites bool - serverCiphers []uint16 - expectedCipher uint16 + name string + clientCiphers []uint16 + serverHasAESGCM bool + serverCiphers []uint16 + expectedCipher uint16 }{ { name: "server has hardware AES, client doesn't (pick ChaCha)", @@ -1696,25 +1705,8 @@ func TestAESCipherReordering(t *testing.T) { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA, }, - serverHasAESGCM: true, - preferServerCipherSuites: true, - expectedCipher: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, - }, - { - name: "server strongly prefers AES-GCM, client doesn't (pick AES-GCM)", - clientCiphers: []uint16{ - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - TLS_RSA_WITH_AES_128_CBC_SHA, - }, - serverHasAESGCM: true, - preferServerCipherSuites: true, - serverCiphers: []uint16{ - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, - TLS_RSA_WITH_AES_128_CBC_SHA, - }, - expectedCipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + serverHasAESGCM: true, + expectedCipher: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, }, { name: "client prefers AES-GCM, server doesn't have hardware AES (pick ChaCha)", @@ -1758,14 +1750,14 @@ func TestAESCipherReordering(t *testing.T) { expectedCipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, }, { - name: "client prefers AES-GCM and AES-CBC over ChaCha, server doesn't have hardware AES (pick AES-GCM)", + name: "client prefers AES-GCM and AES-CBC over ChaCha, server doesn't have hardware AES (pick ChaCha)", clientCiphers: []uint16{ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, }, serverHasAESGCM: false, - expectedCipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + expectedCipher: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, }, { name: "client prefers AES-GCM over ChaCha and sends GREASE, server doesn't have hardware AES (pick ChaCha)", @@ -1779,7 +1771,7 @@ func TestAESCipherReordering(t *testing.T) { expectedCipher: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, }, { - name: "client supports multiple AES-GCM, server doesn't have hardware AES and doesn't support ChaCha (pick corrent AES-GCM)", + name: "client supports multiple AES-GCM, server doesn't have hardware AES and doesn't support ChaCha (AES-GCM)", clientCiphers: []uint16{ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, @@ -1790,19 +1782,30 @@ func TestAESCipherReordering(t *testing.T) { TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, }, - expectedCipher: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + expectedCipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + }, + { + name: "client prefers AES-GCM, server has hardware but doesn't support AES (pick ChaCha)", + clientCiphers: []uint16{ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + TLS_RSA_WITH_AES_128_CBC_SHA, + }, + serverHasAESGCM: true, + serverCiphers: []uint16{ + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + }, + expectedCipher: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { hasAESGCMHardwareSupport = tc.serverHasAESGCM - initDefaultCipherSuites() hs := &serverHandshakeState{ c: &Conn{ config: &Config{ - PreferServerCipherSuites: tc.preferServerCipherSuites, - CipherSuites: tc.serverCiphers, + CipherSuites: tc.serverCiphers, }, vers: VersionTLS12, }, @@ -1827,16 +1830,15 @@ func TestAESCipherReordering(t *testing.T) { } } -func TestAESCipherReordering13(t *testing.T) { +func TestAESCipherReorderingTLS13(t *testing.T) { currentAESSupport := hasAESGCMHardwareSupport - defer func() { hasAESGCMHardwareSupport = currentAESSupport; initDefaultCipherSuites() }() + defer func() { hasAESGCMHardwareSupport = currentAESSupport }() tests := []struct { - name string - clientCiphers []uint16 - serverHasAESGCM bool - preferServerCipherSuites bool - expectedCipher uint16 + name string + clientCiphers []uint16 + serverHasAESGCM bool + expectedCipher uint16 }{ { name: "server has hardware AES, client doesn't (pick ChaCha)", @@ -1844,9 +1846,8 @@ func TestAESCipherReordering13(t *testing.T) { TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256, }, - serverHasAESGCM: true, - preferServerCipherSuites: true, - expectedCipher: TLS_CHACHA20_POLY1305_SHA256, + serverHasAESGCM: true, + expectedCipher: TLS_CHACHA20_POLY1305_SHA256, }, { name: "neither server nor client have hardware AES (pick ChaCha)", @@ -1854,37 +1855,25 @@ func TestAESCipherReordering13(t *testing.T) { TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256, }, - serverHasAESGCM: false, - preferServerCipherSuites: true, - expectedCipher: TLS_CHACHA20_POLY1305_SHA256, + serverHasAESGCM: false, + expectedCipher: TLS_CHACHA20_POLY1305_SHA256, }, { - name: "client prefers AES, server doesn't have hardware, prefer server ciphers (pick ChaCha)", + name: "client prefers AES, server doesn't have hardware (pick ChaCha)", clientCiphers: []uint16{ TLS_AES_128_GCM_SHA256, TLS_CHACHA20_POLY1305_SHA256, }, - serverHasAESGCM: false, - preferServerCipherSuites: true, - expectedCipher: TLS_CHACHA20_POLY1305_SHA256, + serverHasAESGCM: false, + expectedCipher: TLS_CHACHA20_POLY1305_SHA256, }, { - name: "client prefers AES and sends GREASE, server doesn't have hardware, prefer server ciphers (pick ChaCha)", + name: "client prefers AES and sends GREASE, server doesn't have hardware (pick ChaCha)", clientCiphers: []uint16{ 0x0A0A, // GREASE value TLS_AES_128_GCM_SHA256, TLS_CHACHA20_POLY1305_SHA256, }, - serverHasAESGCM: false, - preferServerCipherSuites: true, - expectedCipher: TLS_CHACHA20_POLY1305_SHA256, - }, - { - name: "client prefers AES, server doesn't (pick ChaCha)", - clientCiphers: []uint16{ - TLS_AES_128_GCM_SHA256, - TLS_CHACHA20_POLY1305_SHA256, - }, serverHasAESGCM: false, expectedCipher: TLS_CHACHA20_POLY1305_SHA256, }, @@ -1912,13 +1901,10 @@ func TestAESCipherReordering13(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { hasAESGCMHardwareSupport = tc.serverHasAESGCM - initDefaultCipherSuites() hs := &serverHandshakeStateTLS13{ c: &Conn{ - config: &Config{ - PreferServerCipherSuites: tc.preferServerCipherSuites, - }, - vers: VersionTLS13, + config: &Config{}, + vers: VersionTLS13, }, clientHello: &clientHelloMsg{ cipherSuites: tc.clientCiphers, @@ -1939,3 +1925,104 @@ func TestAESCipherReordering13(t *testing.T) { }) } } + +// TestServerHandshakeContextCancellation tests that cancelling +// the context given to the server side conn.HandshakeContext +// interrupts the in-progress handshake. +func TestServerHandshakeContextCancellation(t *testing.T) { + c, s := localPipe(t) + ctx, cancel := context.WithCancel(context.Background()) + unblockClient := make(chan struct{}) + defer close(unblockClient) + go func() { + cancel() + <-unblockClient + _ = c.Close() + }() + conn := Server(s, testConfig) + // Initiates server side handshake, which will block until a client hello is read + // unless the cancellation works. + err := conn.HandshakeContext(ctx) + if err == nil { + t.Fatal("Server handshake did not error when the context was canceled") + } + if err != context.Canceled { + t.Errorf("Unexpected server handshake error: %v", err) + } + if runtime.GOARCH == "wasm" { + t.Skip("conn.Close does not error as expected when called multiple times on WASM") + } + err = conn.Close() + if err == nil { + t.Error("Server connection was not closed when the context was canceled") + } +} + +// TestHandshakeContextHierarchy tests whether the contexts +// available to GetClientCertificate and GetCertificate are +// derived from the context provided to HandshakeContext, and +// that those contexts are canceled after HandshakeContext has +// returned. +func TestHandshakeContextHierarchy(t *testing.T) { + c, s := localPipe(t) + clientErr := make(chan error, 1) + clientConfig := testConfig.Clone() + serverConfig := testConfig.Clone() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + key := struct{}{} + ctx = context.WithValue(ctx, key, true) + go func() { + defer close(clientErr) + defer c.Close() + var innerCtx context.Context + clientConfig.Certificates = nil + clientConfig.GetClientCertificate = func(certificateRequest *CertificateRequestInfo) (*Certificate, error) { + if val, ok := certificateRequest.Context().Value(key).(bool); !ok || !val { + t.Errorf("GetClientCertificate context was not child of HandshakeContext") + } + innerCtx = certificateRequest.Context() + return &Certificate{ + Certificate: [][]byte{testRSACertificate}, + PrivateKey: testRSAPrivateKey, + }, nil + } + cli := Client(c, clientConfig) + err := cli.HandshakeContext(ctx) + if err != nil { + clientErr <- err + return + } + select { + case <-innerCtx.Done(): + default: + t.Errorf("GetClientCertificate context was not canceled after HandshakeContext returned.") + } + }() + var innerCtx context.Context + serverConfig.Certificates = nil + serverConfig.ClientAuth = RequestClientCert + serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) { + if val, ok := clientHello.Context().Value(key).(bool); !ok || !val { + t.Errorf("GetClientCertificate context was not child of HandshakeContext") + } + innerCtx = clientHello.Context() + return &Certificate{ + Certificate: [][]byte{testRSACertificate}, + PrivateKey: testRSAPrivateKey, + }, nil + } + conn := Server(s, serverConfig) + err := conn.HandshakeContext(ctx) + if err != nil { + t.Errorf("Unexpected server handshake error: %v", err) + } + select { + case <-innerCtx.Done(): + default: + t.Errorf("GetCertificate context was not canceled after HandshakeContext returned.") + } + if err := <-clientErr; err != nil { + t.Errorf("Unexpected client error: %v", err) + } +} diff --git a/libgo/go/crypto/tls/handshake_server_tls13.go b/libgo/go/crypto/tls/handshake_server_tls13.go index c2c288a..08251b8 100644 --- a/libgo/go/crypto/tls/handshake_server_tls13.go +++ b/libgo/go/crypto/tls/handshake_server_tls13.go @@ -6,6 +6,7 @@ package tls import ( "bytes" + "context" "crypto" "crypto/hmac" "crypto/rsa" @@ -23,6 +24,7 @@ const maxClientPSKIdentities = 5 type serverHandshakeStateTLS13 struct { c *Conn + ctx context.Context clientHello *clientHelloMsg hello *serverHelloMsg sentDummyCCS bool @@ -147,29 +149,12 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error { hs.hello.sessionId = hs.clientHello.sessionId hs.hello.compressionMethod = compressionNone - var preferenceList, supportedList []uint16 - if c.config.PreferServerCipherSuites { - preferenceList = defaultCipherSuitesTLS13() - supportedList = hs.clientHello.cipherSuites - - // If the client does not seem to have hardware support for AES-GCM, - // prefer other AEAD ciphers even if we prioritized AES-GCM ciphers - // by default. - if !aesgcmPreferred(hs.clientHello.cipherSuites) { - preferenceList = deprioritizeAES(preferenceList) - } - } else { - preferenceList = hs.clientHello.cipherSuites - supportedList = defaultCipherSuitesTLS13() - - // If we don't have hardware support for AES-GCM, prefer other AEAD - // ciphers even if the client prioritized AES-GCM. - if !hasAESGCMHardwareSupport { - preferenceList = deprioritizeAES(preferenceList) - } + preferenceList := defaultCipherSuitesTLS13 + if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) { + preferenceList = defaultCipherSuitesTLS13NoAES } for _, suiteID := range preferenceList { - hs.suite = mutualCipherSuiteTLS13(supportedList, suiteID) + hs.suite = mutualCipherSuiteTLS13(hs.clientHello.cipherSuites, suiteID) if hs.suite != nil { break } @@ -374,7 +359,7 @@ func (hs *serverHandshakeStateTLS13) pickCertificate() error { return c.sendAlert(alertMissingExtension) } - certificate, err := c.config.getCertificate(clientHelloInfo(c, hs.clientHello)) + certificate, err := c.config.getCertificate(clientHelloInfo(hs.ctx, c, hs.clientHello)) if err != nil { if err == errNoCertificates { c.sendAlert(alertUnrecognizedName) @@ -565,12 +550,13 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error { encryptedExtensions := new(encryptedExtensionsMsg) - if len(hs.clientHello.alpnProtocols) > 0 { - if selectedProto := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); selectedProto != "" { - encryptedExtensions.alpnProtocol = selectedProto - c.clientProtocol = selectedProto - } + selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols) + if err != nil { + c.sendAlert(alertNoApplicationProtocol) + return err } + encryptedExtensions.alpnProtocol = selectedProto + c.clientProtocol = selectedProto hs.transcript.Write(encryptedExtensions.marshal()) if _, err := c.writeRecord(recordTypeHandshake, encryptedExtensions.marshal()); err != nil { diff --git a/libgo/go/crypto/tls/handshake_test.go b/libgo/go/crypto/tls/handshake_test.go index d9ff9fe..9bfb117 100644 --- a/libgo/go/crypto/tls/handshake_test.go +++ b/libgo/go/crypto/tls/handshake_test.go @@ -335,15 +335,9 @@ func TestMain(m *testing.M) { } func runMain(m *testing.M) int { - // TLS 1.3 cipher suites preferences are not configurable and change based - // on the architecture. Force them to the version with AES acceleration for - // test consistency. - once.Do(initDefaultCipherSuites) - varDefaultCipherSuitesTLS13 = []uint16{ - TLS_AES_128_GCM_SHA256, - TLS_CHACHA20_POLY1305_SHA256, - TLS_AES_256_GCM_SHA384, - } + // Cipher suites preferences change based on the architecture. Force them to + // the version without AES acceleration for test consistency. + hasAESGCMHardwareSupport = false // Set up localPipe. l, err := net.Listen("tcp", "127.0.0.1:0") diff --git a/libgo/go/crypto/tls/handshake_unix_test.go b/libgo/go/crypto/tls/handshake_unix_test.go index 7271854..19fc698 100644 --- a/libgo/go/crypto/tls/handshake_unix_test.go +++ b/libgo/go/crypto/tls/handshake_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package tls diff --git a/libgo/go/crypto/tls/key_agreement.go b/libgo/go/crypto/tls/key_agreement.go index 7e6534b..c28a64f 100644 --- a/libgo/go/crypto/tls/key_agreement.go +++ b/libgo/go/crypto/tls/key_agreement.go @@ -15,6 +15,25 @@ import ( "io" ) +// a keyAgreement implements the client and server side of a TLS key agreement +// protocol by generating and processing key exchange messages. +type keyAgreement interface { + // On the server side, the first two methods are called in order. + + // In the case that the key agreement protocol doesn't use a + // ServerKeyExchange message, generateServerKeyExchange can return nil, + // nil. + generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error) + processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error) + + // On the client side, the next two methods are called in order. + + // This method may not be called if the server doesn't send a + // ServerKeyExchange message. + processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error + generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) +} + var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message") var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message") @@ -67,7 +86,11 @@ func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello return nil, nil, err } - encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret) + rsaKey, ok := cert.PublicKey.(*rsa.PublicKey) + if !ok { + return nil, nil, errors.New("tls: server certificate contains incorrect key type for selected ciphersuite") + } + encrypted, err := rsa.EncryptPKCS1v15(config.rand(), rsaKey, preMasterSecret) if err != nil { return nil, nil, err } diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA index 9de3f14..c7fa530 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA +++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 01 00 59 02 00 00 55 03 01 94 1f ba 79 da |....Y...U.....y.| -00000010 4b 58 3e 08 2c c5 31 36 a4 7e 32 bf e1 a0 f7 71 |KX>.,.16.~2....q| -00000020 01 48 63 3c 5f cb 08 7a 25 80 c7 20 35 0c c0 8b |.Hc<_..z%.. 5...| -00000030 df 30 fc dc 3d f1 48 96 0d b6 ff a8 cd 35 29 57 |.0..=.H......5)W| -00000040 7d 3f c2 9d e2 32 b1 c2 4c 05 5e 3b c0 09 00 00 |}?...2..L.^;....| +00000000 16 03 01 00 59 02 00 00 55 03 01 92 4c b7 e6 07 |....Y...U...L...| +00000010 09 b4 4a 47 6a 29 c7 79 18 0d 43 37 86 26 21 5a |..JGj).y..C7.&!Z| +00000020 25 35 db 5f ae d0 20 0d 85 67 f7 20 75 e5 cb 25 |%5._.. ..g. u..%| +00000030 4b 5d 95 87 78 00 fc 3f 78 26 e8 77 b5 0d d4 0e |K]..x..?x&.w....| +00000040 54 06 66 b4 14 dc 6b db f2 af f3 2a c0 09 00 00 |T.f...k....*....| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 01 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| 00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| @@ -55,18 +55,18 @@ 00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| 00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| 00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| -00000270 2a 16 03 01 00 b5 0c 00 00 b1 03 00 1d 20 1a 74 |*............ .t| -00000280 c4 96 9e 65 45 9a 0a 01 7c ed 7b 51 01 d8 ba 5b |...eE...|.{Q...[| -00000290 3e 2f b1 4b 36 69 e8 47 75 7e 27 be b3 2f 00 8b |>/.K6i.Gu~'../..| -000002a0 30 81 88 02 42 01 cb 20 d9 1e ae 05 6f 1f 37 ce |0...B.. ....o.7.| -000002b0 dc 38 20 2f 8f 52 9a 92 f6 80 d6 f9 97 99 a5 8b |.8 /.R..........| -000002c0 6e 73 0b 95 a4 4e 82 67 bd 1a 34 d9 5c 4e b4 d7 |ns...N.g..4.\N..| -000002d0 35 e6 45 81 14 23 9c 4e 5a 4c 1b 93 fd 7f 43 18 |5.E..#.NZL....C.| -000002e0 db 54 4b e0 d1 d3 fa 02 42 00 ab 8e 34 d5 c2 04 |.TK.....B...4...| -000002f0 d0 a4 44 b1 b3 25 a0 af c8 80 b3 88 ae da b3 c6 |..D..%..........| -00000300 4f 57 ae 31 54 c6 d9 ee 4e 21 56 01 cc b9 6a e9 |OW.1T...N!V...j.| -00000310 e9 7e 62 2a 64 0e a4 a0 79 1e a3 64 52 70 b1 a5 |.~b*d...y..dRp..| -00000320 19 2c a4 6d 4b 3b a3 63 ed 56 2f 16 03 01 00 0a |.,.mK;.c.V/.....| +00000270 2a 16 03 01 00 b5 0c 00 00 b1 03 00 1d 20 d7 b5 |*............ ..| +00000280 51 8e b5 01 4f 02 2f 43 11 2b de 94 7d 82 e6 49 |Q...O./C.+..}..I| +00000290 1b a6 ee a0 7f 12 35 a2 3a 62 46 ce 07 25 00 8b |......5.:bF..%..| +000002a0 30 81 88 02 42 00 83 45 db 03 db b9 74 ce 77 35 |0...B..E....t.w5| +000002b0 1b e5 76 18 dc 3a d3 ee 32 18 f3 16 a6 c3 62 be |..v..:..2.....b.| +000002c0 46 47 40 80 2d a0 08 c5 1e 5a 4a 42 69 8c ee e5 |FG@.-....ZJBi...| +000002d0 70 b5 71 30 2f 54 32 54 5f 5b 26 62 e1 81 52 9e |p.q0/T2T_[&b..R.| +000002e0 49 70 d4 81 e4 76 f1 02 42 01 70 f6 87 84 bb 58 |Ip...v..B.p....X| +000002f0 5d e4 a1 72 87 d5 35 53 99 9c 3f 30 2b 80 7e c9 |]..r..5S..?0+.~.| +00000300 79 eb d8 97 3c 82 ff 37 a5 8d 36 bc 27 c1 51 58 |y...<..7..6.'.QX| +00000310 e6 2a 48 05 bf 9b a4 a5 b1 7f 77 b8 d9 3e 37 c6 |.*H.......w..>7.| +00000320 67 ad ef 8c 72 ea f6 ba bb af 00 16 03 01 00 0a |g...r...........| 00000330 0d 00 00 06 03 01 02 40 00 00 16 03 01 00 04 0e |.......@........| 00000340 00 00 00 |...| >>> Flow 3 (client to server) @@ -105,30 +105,30 @@ 00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| 00000210 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd 62 |...%...! /.}.G.b| 00000220 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| -00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 90 0f 00 |...._X.;t.......| -00000240 00 8c 00 8a 30 81 87 02 42 01 89 0f 43 df a8 34 |....0...B...C..4| -00000250 dd d7 c9 d4 2b 8d ec 29 77 7b 64 d0 0e 8c e8 2b |....+..)w{d....+| -00000260 e3 25 1c ed 0a 1b 05 e0 66 42 37 c0 e6 fa 3e 81 |.%......fB7...>.| -00000270 ec e1 06 99 f4 62 3f ea 55 79 ae 68 56 9e e3 3c |.....b?.Uy.hV..<| -00000280 83 ba 9b 1c 65 b9 eb a6 e7 f7 4e 02 41 61 2c 52 |....e.....N.Aa,R| -00000290 4c 48 92 b0 93 d8 31 58 c3 90 b0 e3 7d 55 94 fc |LH....1X....}U..| -000002a0 70 bf 18 42 51 73 d0 45 17 2e 0e 00 b0 12 76 0d |p..BQs.E......v.| -000002b0 35 78 cb fd 34 60 36 ff ed 19 ef 0a 1e 21 cc 4c |5x..4`6......!.L| -000002c0 9a ff a0 f7 cf 72 03 cd 00 bb 73 0d 1d e5 14 03 |.....r....s.....| -000002d0 01 00 01 01 16 03 01 00 30 69 76 1f 5b 81 5f 62 |........0iv.[._b| -000002e0 cf d5 d9 2c 19 71 80 d0 2a 97 8a 89 21 7f 6d 02 |...,.q..*...!.m.| -000002f0 b6 01 a4 ed fe 18 9f 34 ae 95 f6 a1 29 0b 9a 1c |.......4....)...| -00000300 04 b6 ce c7 d1 0c 5a b5 3f |......Z.?| +00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 91 0f 00 |...._X.;t.......| +00000240 00 8d 00 8b 30 81 88 02 42 01 f0 c3 b2 6e e2 a3 |....0...B....n..| +00000250 cd 76 02 7a d5 b5 66 fa b6 66 4e 4b a0 17 d6 bd |.v.z..f..fNK....| +00000260 ec f6 8c 1f f9 b4 32 18 a9 ba 66 a8 67 a4 fa c8 |......2...f.g...| +00000270 f7 73 5f 22 fb f2 22 e2 4d a1 f6 30 a2 55 76 51 |.s_"..".M..0.UvQ| +00000280 b7 61 7d 13 68 0a 89 9d 34 31 46 02 42 01 fa 8b |.a}.h...41F.B...| +00000290 61 f6 91 8e 88 ca 84 e6 33 e0 da 92 7e ee 21 1c |a.......3...~.!.| +000002a0 df 47 c2 5d 07 d8 ae 1b 04 58 f9 50 16 13 74 ea |.G.].....X.P..t.| +000002b0 04 cc 18 2d 2b 9a 08 89 24 e8 b8 01 bb c6 84 6c |...-+...$......l| +000002c0 e6 9a c6 8a 44 74 1c 3a 79 0c e9 3c 11 ba 1b 14 |....Dt.:y..<....| +000002d0 03 01 00 01 01 16 03 01 00 30 1d 4b df 00 de 1c |.........0.K....| +000002e0 b5 30 7b ea 64 a0 09 89 8c c5 be fc 9b 07 7e 45 |.0{.d.........~E| +000002f0 27 00 e7 78 da 3e a3 04 97 87 b0 c2 17 32 01 91 |'..x.>.......2..| +00000300 6e 66 7b dd 9e 28 bc cc 66 65 |nf{..(..fe| >>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 30 7d 4b fc 73 20 |..........0}K.s | -00000010 e4 ac c4 39 15 79 e3 89 e1 24 ce 28 30 e5 f1 87 |...9.y...$.(0...| -00000020 cd c0 cc 39 a8 77 3b 06 a5 f9 b0 a1 3d 54 53 3b |...9.w;.....=TS;| -00000030 53 ec ac b2 ea 24 1b 2d 6a ef c3 |S....$.-j..| +00000000 14 03 01 00 01 01 16 03 01 00 30 51 68 ca 97 63 |..........0Qh..c| +00000010 c6 c0 24 1c 87 20 70 ac f7 47 16 45 44 17 cc 92 |..$.. p..G.ED...| +00000020 b3 6d 8b fa d1 3c b8 10 d7 da e4 a7 35 3c a2 d0 |.m...<......5<..| +00000030 da 4b 50 e4 89 94 4b bc 20 6b e3 |.KP...K. k.| >>> Flow 5 (client to server) -00000000 17 03 01 00 20 9d 57 d2 4b 5b 7e 7d 7c 28 f7 8e |.... .W.K[~}|(..| -00000010 00 0a b6 1c 3c 6b df 4d 06 c0 f8 db 86 2e 8f 8e |....<k.M........| -00000020 28 a9 ab 6c c2 17 03 01 00 20 b4 4e cc 55 14 1c |(..l..... .N.U..| -00000030 64 a4 3d 69 1a dc 3b 12 8e d8 15 f2 31 3a 71 1f |d.=i..;.....1:q.| -00000040 eb fe c3 b3 22 f7 2c 6e 01 e9 15 03 01 00 20 2a |....".,n...... *| -00000050 2e 34 ca 96 e5 a3 a0 53 c4 0c e2 0a b1 14 a3 c8 |.4.....S........| -00000060 a5 db 72 09 31 25 11 11 2f ce 61 3a 55 48 0c |..r.1%../.a:UH.| +00000000 17 03 01 00 20 fc fa 90 90 d0 51 0d 35 0f 6a 6d |.... .....Q.5.jm| +00000010 c2 32 ec 92 46 9f d7 e9 66 37 02 2a f6 c6 2e e2 |.2..F...f7.*....| +00000020 13 aa fa fa d3 17 03 01 00 20 45 a9 36 19 7d a8 |......... E.6.}.| +00000030 44 4c 8b aa 4e 47 c8 79 0c 97 a5 20 fa 6f 1f f7 |DL..NG.y... .o..| +00000040 d3 bc d7 6d c2 67 23 c8 d6 05 15 03 01 00 20 f1 |...m.g#....... .| +00000050 f1 ed f9 fc c2 f6 61 c8 42 9d c9 8a b0 d0 de d3 |......a.B.......| +00000060 42 c7 04 64 eb 9e eb 58 3b c3 7d 0d 4d 16 d4 |B..d...X;.}.M..| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA index 754b76e..81e5191 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA +++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 01 00 59 02 00 00 55 03 01 97 0c 7e fc 7f |....Y...U....~..| -00000010 96 47 02 21 a7 19 45 a5 79 5c 5e fc c2 15 b3 fa |.G.!..E.y\^.....| -00000020 84 98 7d 67 65 c8 48 58 a1 5d 67 20 ad 2a c6 b3 |..}ge.HX.]g .*..| -00000030 a4 17 82 12 4a c5 97 af 12 6b 7d f6 9e 49 f1 38 |....J....k}..I.8| -00000040 d0 56 76 bc 81 23 ad 3a 3e 7f bc 2d c0 13 00 00 |.Vv..#.:>..-....| +00000000 16 03 01 00 59 02 00 00 55 03 01 ca 72 6a a1 69 |....Y...U...rj.i| +00000010 18 a4 f8 76 4a c3 5c e8 d5 c1 fb 06 c6 9a 14 67 |...vJ.\........g| +00000020 ce e4 f6 52 67 ab 64 48 28 5a 63 20 55 ea ff 87 |...Rg.dH(Zc U...| +00000030 5a 78 5c cb 21 af 83 a5 ed 1b d3 2c 39 81 e5 ca |Zx\.!......,9...| +00000040 63 d2 5c 57 27 1d d0 f9 41 40 43 b0 c0 13 00 00 |c.\W'...A@C.....| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 01 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,17 +60,17 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 01 00 |.=.`.\!.;.......| -000002c0 aa 0c 00 00 a6 03 00 1d 20 a4 24 f7 67 e3 da fa |........ .$.g...| -000002d0 10 33 95 b4 46 00 c0 3c cd 74 12 e4 a3 3b 01 70 |.3..F..<.t...;.p| -000002e0 fb 98 01 9a e9 2d d0 18 7b 00 80 ce c5 7b 4b 87 |.....-..{....{K.| -000002f0 cd bc 5d 63 09 7e d4 ce 09 53 7a 1b e5 b4 10 54 |..]c.~...Sz....T| -00000300 89 52 ac 82 9c 78 88 ed e8 1a 8c 3a 7a 2c 9a c5 |.R...x.....:z,..| -00000310 2b 97 1c 79 43 bd b1 ee 93 6f 4c 4d fc 3c 47 91 |+..yC....oLM.<G.| -00000320 a6 ac ad be a9 39 12 98 40 f7 6a a3 e7 21 76 90 |.....9..@.j..!v.| -00000330 c9 80 2b bc 80 3f 7e 60 59 7d cd 38 84 a8 53 2a |..+..?~`Y}.8..S*| -00000340 92 24 08 8f 84 da cd 9a 86 80 10 05 8f 1b fd 86 |.$..............| -00000350 93 b6 ef 13 70 e5 6a d5 0e a5 bf 80 bf 50 a8 d4 |....p.j......P..| -00000360 87 99 b8 d6 f0 4f 45 d5 e6 8b e1 16 03 01 00 0a |.....OE.........| +000002c0 aa 0c 00 00 a6 03 00 1d 20 e8 a5 9c e4 73 3d 75 |........ ....s=u| +000002d0 0c 3e f2 de 21 9c 0f 91 b4 fd 94 f0 27 f6 d9 7d |.>..!.......'..}| +000002e0 cd 0c 4c 50 b0 47 db dd 12 00 80 04 c0 be d5 bb |..LP.G..........| +000002f0 e8 e2 a2 2e d9 2e 75 fa b6 07 d0 f7 75 52 fb 2f |......u.....uR./| +00000300 50 cd 43 68 bd 42 11 6d d6 9f a3 d1 00 fd a9 14 |P.Ch.B.m........| +00000310 0c 2a dd 76 ea 73 21 52 00 3a 83 cf d7 07 c7 bd |.*.v.s!R.:......| +00000320 78 21 ce 35 80 b3 06 22 f1 96 a7 20 41 f8 aa 61 |x!.5..."... A..a| +00000330 94 b4 77 d4 d9 92 f2 66 c5 1c d1 82 f3 b9 e2 9d |..w....f........| +00000340 a9 30 1c e2 4e ec 0d 32 3d 0d 61 22 c8 e5 95 9f |.0..N..2=.a"....| +00000350 cf 3e fc a8 c5 c3 f8 45 45 29 ea a7 e7 b7 a6 17 |.>.....EE)......| +00000360 9e 5f 83 d4 b3 f0 da 31 73 94 f2 16 03 01 00 0a |._.....1s.......| 00000370 0d 00 00 06 03 01 02 40 00 00 16 03 01 00 04 0e |.......@........| 00000380 00 00 00 |...| >>> Flow 3 (client to server) @@ -110,29 +110,29 @@ 00000210 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd 62 |...%...! /.}.G.b| 00000220 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| 00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 91 0f 00 |...._X.;t.......| -00000240 00 8d 00 8b 30 81 88 02 42 01 71 f3 c4 3a 85 08 |....0...B.q..:..| -00000250 3b 18 26 48 5c 3f c3 8a 4f e9 d7 29 48 59 1a 35 |;.&H\?..O..)HY.5| -00000260 ee b3 0d 5e 29 03 1d 34 95 0e 40 73 85 13 14 d0 |...^)..4..@s....| -00000270 fb fb 96 77 21 fb d8 43 d7 e2 bf 2c 95 7b 75 5d |...w!..C...,.{u]| -00000280 59 15 81 71 d2 b6 82 96 d9 cc 78 02 42 01 d3 51 |Y..q......x.B..Q| -00000290 af 25 d0 f8 a4 e2 e7 8e 7e 46 56 53 8f d1 09 f6 |.%......~FVS....| -000002a0 76 88 5a 42 83 89 92 7b c7 e4 40 9c 3d 05 ac 43 |v.ZB...{..@.=..C| -000002b0 bf 6e 24 14 fe 36 f8 43 a6 90 8e a1 bd e2 92 84 |.n$..6.C........| -000002c0 60 e3 92 34 1c 7b 53 d5 57 6d 23 32 12 a8 23 14 |`..4.{S.Wm#2..#.| -000002d0 03 01 00 01 01 16 03 01 00 30 6f 06 c7 84 fa 7f |.........0o.....| -000002e0 c9 66 a9 6f 26 37 45 db 42 c8 8f 63 c3 5b 05 07 |.f.o&7E.B..c.[..| -000002f0 ef 07 41 be 71 60 35 d3 16 8f 92 f6 89 cb c7 dc |..A.q`5.........| -00000300 4e 45 61 99 31 45 66 40 36 86 |NEa.1Ef@6.| +00000240 00 8d 00 8b 30 81 88 02 42 00 9a b9 f6 98 e3 ed |....0...B.......| +00000250 ed 0d a3 0e 54 51 9f 73 d4 87 40 4e a9 39 4b 2d |....TQ.s..@N.9K-| +00000260 2a b9 4d 8d e3 46 c3 b6 39 f2 ca a9 c9 0f 79 c1 |*.M..F..9.....y.| +00000270 0c 90 6f de 58 97 72 fc a8 c1 4c 12 aa a4 85 57 |..o.X.r...L....W| +00000280 50 7c a0 02 8a 12 c5 80 aa b6 39 02 42 00 9c b7 |P|........9.B...| +00000290 95 b4 04 83 5b 3a e1 ac da 78 86 11 f5 30 75 4a |....[:...x...0uJ| +000002a0 25 67 6c fd ef 5a d8 56 d3 60 93 cf 65 07 2b 1f |%gl..Z.V.`..e.+.| +000002b0 a9 40 a8 ba cd 0e 41 2d 10 43 a4 61 93 b7 0a 11 |.@....A-.C.a....| +000002c0 78 d1 72 2b 20 07 49 5a 76 02 17 57 87 78 c7 14 |x.r+ .IZv..W.x..| +000002d0 03 01 00 01 01 16 03 01 00 30 93 de 1b 64 0e 56 |.........0...d.V| +000002e0 d9 a8 da f7 37 cb ac ac 3e f5 e2 f9 87 19 f2 79 |....7...>......y| +000002f0 24 76 19 a4 a2 41 d6 9e 7d ca aa 3e 1d d7 22 dd |$v...A..}..>..".| +00000300 05 aa dd 74 03 db fd a2 de ee |...t......| >>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 30 d3 83 ac 08 7f |..........0.....| -00000010 a1 91 51 7c b7 99 6f 24 cd b1 cd 31 7b 12 20 47 |..Q|..o$...1{. G| -00000020 66 08 22 f6 28 ea 81 fe 92 b5 c8 40 60 bc 5b 19 |f.".(......@`.[.| -00000030 e0 2b d1 26 fd 4c 12 22 c5 13 9a |.+.&.L."...| +00000000 14 03 01 00 01 01 16 03 01 00 30 4d 4f d6 67 05 |..........0MO.g.| +00000010 32 8c 16 cb 19 35 b3 b9 02 d8 5e 24 b6 c8 b7 3a |2....5....^$...:| +00000020 17 34 98 77 e1 73 e0 cd a9 30 a8 15 60 8c f4 9a |.4.w.s...0..`...| +00000030 dc cf 7a fd 86 85 1c 2b 33 21 e8 |..z....+3!.| >>> Flow 5 (client to server) -00000000 17 03 01 00 20 79 06 89 7e e0 17 9a e3 dc 4c ee |.... y..~.....L.| -00000010 70 63 13 bc 27 f5 43 fa f8 90 49 d9 89 43 7a 15 |pc..'.C...I..Cz.| -00000020 d4 e2 a8 e6 3e 17 03 01 00 20 ea 84 0e 21 62 d5 |....>.... ...!b.| -00000030 ee 26 5e fc 3e 0c 83 3b 91 01 c4 a7 8e 9b c4 1a |.&^.>..;........| -00000040 86 f8 a0 44 21 44 2f 31 cf a1 15 03 01 00 20 c6 |...D!D/1...... .| -00000050 11 f1 65 ea f3 39 d1 d2 ac 95 1f 81 36 ae db b1 |..e..9......6...| -00000060 88 a8 42 25 86 ec 1b c1 7e 12 60 a9 6b 7f 66 |..B%....~.`.k.f| +00000000 17 03 01 00 20 b8 c5 17 b7 92 d8 93 7a b2 fd 4f |.... .......z..O| +00000010 15 d1 db b9 47 54 00 a0 f6 77 92 03 a8 89 e5 ba |....GT...w......| +00000020 cc eb d9 bd 27 17 03 01 00 20 57 d5 9a f6 36 b2 |....'.... W...6.| +00000030 57 ba cd 64 77 36 b9 74 fb bd 95 51 03 61 e8 45 |W..dw6.t...Q.a.E| +00000040 cb b8 35 f0 05 17 b3 08 c6 cb 15 03 01 00 20 28 |..5........... (| +00000050 43 03 ab 3f e2 f5 d0 33 4c 7f 50 a4 ee 7b 46 e6 |C..?...3L.P..{F.| +00000060 12 76 d0 fd c3 99 5c 63 a4 04 ea 4b e3 bd 99 |.v....\c...K...| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA index 641ab1b..3ee661e 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA +++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 01 00 59 02 00 00 55 03 01 3b 4c b9 76 d2 |....Y...U..;L.v.| -00000010 c3 d1 ea 81 71 1a 10 e1 b1 69 5c 54 c2 df 17 0a |....q....i\T....| -00000020 de 41 cb d1 69 c3 9a da 90 fd 25 20 1e 02 11 16 |.A..i.....% ....| -00000030 ab 66 13 56 3d 94 00 a9 80 7c d8 57 12 99 1c 5f |.f.V=....|.W..._| -00000040 7a b2 02 8c 23 f3 76 b8 59 5e 16 dd c0 09 00 00 |z...#.v.Y^......| +00000000 16 03 01 00 59 02 00 00 55 03 01 b4 ff c0 49 36 |....Y...U.....I6| +00000010 1d 31 9a a7 f6 33 f5 16 78 d7 10 9e 19 eb 1d 67 |.1...3..x......g| +00000020 20 39 f8 73 7e 27 e2 dc d1 ab 03 20 79 64 67 f7 | 9.s~'..... ydg.| +00000030 8b c8 97 f0 b4 87 0e 2d 4b 22 6c ed 92 48 85 52 |.......-K"l..H.R| +00000040 eb 57 56 a8 cf 19 9f 4d e3 38 5e a0 c0 09 00 00 |.WV....M.8^.....| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 01 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| 00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| @@ -55,20 +55,20 @@ 00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| 00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| 00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| -00000270 2a 16 03 01 00 b5 0c 00 00 b1 03 00 1d 20 16 64 |*............ .d| -00000280 ca 24 70 6f 61 2f 9e 2d 43 0a 73 ac 67 f0 7a e5 |.$poa/.-C.s.g.z.| -00000290 c7 4e c4 1f ad 13 0d eb df ff 0d ff a3 27 00 8b |.N...........'..| -000002a0 30 81 88 02 42 01 1a 33 8b 88 78 ed 5c c1 56 0d |0...B..3..x.\.V.| -000002b0 75 51 69 a0 e7 45 6d ae b0 67 55 3f be 23 3e 92 |uQi..Em..gU?.#>.| -000002c0 fe 26 68 a2 30 84 2f b3 33 66 f6 dd 71 67 99 5e |.&h.0./.3f..qg.^| -000002d0 1c 6f bf 87 ed 33 a0 87 69 f6 35 65 8d cb 3a 7e |.o...3..i.5e..:~| -000002e0 95 a7 a4 40 54 cb 97 02 42 00 a3 fe 50 34 68 9f |...@T...B...P4h.| -000002f0 f2 43 98 23 e4 24 ad 36 e9 d3 e0 75 2c 11 46 6c |.C.#.$.6...u,.Fl| -00000300 48 33 c5 bc 2d 04 ff cc bb ec 38 ec f4 b3 55 31 |H3..-.....8...U1| -00000310 8a 6e 38 a5 6d a0 9c fc f6 98 75 48 c6 79 53 de |.n8.m.....uH.yS.| -00000320 dd 91 49 f0 b6 32 83 45 61 89 4e 16 03 01 00 0a |..I..2.Ea.N.....| -00000330 0d 00 00 06 03 01 02 40 00 00 16 03 01 00 04 0e |.......@........| -00000340 00 00 00 |...| +00000270 2a 16 03 01 00 b4 0c 00 00 b0 03 00 1d 20 ec 38 |*............ .8| +00000280 f7 41 d0 f3 f4 6a ca 47 18 74 f1 22 2c 47 ee 39 |.A...j.G.t.",G.9| +00000290 c9 a2 db 64 05 01 ae 5d 08 65 53 7f 24 78 00 8a |...d...].eS.$x..| +000002a0 30 81 87 02 41 64 39 65 56 fa d4 69 e7 c5 a5 32 |0...Ad9eV..i...2| +000002b0 4c 52 55 96 fe 01 cd 41 3c 18 ed df fd 09 c3 89 |LRU....A<.......| +000002c0 80 bd 88 9e d7 a1 85 16 d1 a4 5a f0 9a 76 e9 2f |..........Z..v./| +000002d0 d2 a4 42 a4 89 98 6c 87 64 b1 49 4e 6a 68 d2 43 |..B...l.d.INjh.C| +000002e0 41 a2 c7 a6 2f f7 02 42 01 6c bb 32 c0 47 7e 08 |A.../..B.l.2.G~.| +000002f0 6b 7a 44 18 b7 5d 4c 4d 6d 80 92 bb e5 65 98 1b |kzD..]LMm....e..| +00000300 d7 a6 a3 1b b5 f3 46 1a e7 e0 89 04 40 b0 29 aa |......F.....@.).| +00000310 fe 85 6a 9a 4b 18 75 ab 00 52 71 54 41 8d eb 31 |..j.K.u..RqTA..1| +00000320 47 69 9b 9d dc 3b 1b 3e 76 27 16 03 01 00 0a 0d |Gi...;.>v'......| +00000330 00 00 06 03 01 02 40 00 00 16 03 01 00 04 0e 00 |......@.........| +00000340 00 00 |..| >>> Flow 3 (client to server) 00000000 16 03 01 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0| 00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.| @@ -105,29 +105,29 @@ 00000200 e5 35 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| 00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| 00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 |......._X.;t....| -00000230 86 0f 00 00 82 00 80 90 68 a8 2f 6f 2b 70 e4 25 |........h./o+p.%| -00000240 7d fb b7 85 db 44 ec 1a ad 6d 84 fb 95 21 fa 24 |}....D...m...!.$| -00000250 7b 31 6a 97 4f 06 ee 87 22 c3 7c 81 70 ed e3 2a |{1j.O...".|.p..*| -00000260 d5 2c d1 4e 6d f0 12 52 2f 98 05 08 af 41 fa 87 |.,.Nm..R/....A..| -00000270 d1 62 98 6c 06 47 ec 7a 44 e0 7d ae 7a 7d ef 1b |.b.l.G.zD.}.z}..| -00000280 d5 2c fa 1b 70 a3 fb 9a 5d 8c 60 b4 44 6a e5 b8 |.,..p...].`.Dj..| -00000290 80 4c 29 fc f1 2d f1 11 46 81 c4 01 e4 11 2e 05 |.L)..-..F.......| -000002a0 cb 2b ca d9 4a 14 39 06 93 77 19 db 80 03 82 38 |.+..J.9..w.....8| -000002b0 e5 c1 0f 11 17 47 a7 14 03 01 00 01 01 16 03 01 |.....G..........| -000002c0 00 30 a6 68 28 50 75 6d eb f4 32 c8 a3 57 3f b1 |.0.h(Pum..2..W?.| -000002d0 37 84 8e 7e 1d 1d 93 7d 9f ec ff ac 1c 8d bf 30 |7..~...}.......0| -000002e0 d2 b0 0f 3f 02 c3 ef ac a3 62 94 26 1c 8f 7e 8d |...?.....b.&..~.| -000002f0 74 99 |t.| +00000230 86 0f 00 00 82 00 80 05 7e 70 eb cb ef e3 d9 6f |........~p.....o| +00000240 59 29 b5 da f2 07 f5 42 62 4e 74 9b cf 00 e1 5c |Y).....BbNt....\| +00000250 69 a5 67 3a b0 b2 ca f2 10 ed 1c b4 81 5d 7d 9e |i.g:.........]}.| +00000260 1a 45 69 42 13 c5 b0 86 dc 3d 60 e5 cf fd ae 0f |.EiB.....=`.....| +00000270 17 bb 4a ed d7 06 eb f1 6d 47 98 b7 e8 87 eb 3c |..J.....mG.....<| +00000280 12 55 2c 06 de 55 48 c7 59 85 cb 62 d6 e7 1d 05 |.U,..UH.Y..b....| +00000290 1e 6d 69 84 cd 16 8e dd ed 5b 5a 2f f2 97 b7 78 |.mi......[Z/...x| +000002a0 93 c1 fb 75 26 c8 b5 58 43 17 c7 52 54 20 4f 7d |...u&..XC..RT O}| +000002b0 7c 46 89 65 fe 51 29 14 03 01 00 01 01 16 03 01 ||F.e.Q).........| +000002c0 00 30 d9 59 e6 7e c0 a6 2a af 36 0c 2e cf 0f 42 |.0.Y.~..*.6....B| +000002d0 54 d4 41 c6 3c f8 84 d9 2a a6 82 94 22 2d ac ae |T.A.<...*..."-..| +000002e0 d9 f7 68 22 f6 f0 2e 56 c1 97 80 73 0d b3 f0 70 |..h"...V...s...p| +000002f0 49 78 |Ix| >>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 30 80 3e 0d 50 13 |..........0.>.P.| -00000010 5f 00 ba 2e 47 46 5d 63 1b 72 a8 02 24 1c 3e 1f |_...GF]c.r..$.>.| -00000020 ed e2 3a 45 d7 7d 3a f2 33 97 c3 ab 13 9b 0e 4a |..:E.}:.3......J| -00000030 04 f0 08 48 ab d3 46 0b 40 7d 5c |...H..F.@}\| +00000000 14 03 01 00 01 01 16 03 01 00 30 06 19 79 49 41 |..........0..yIA| +00000010 f9 9c 75 84 73 95 96 bd 1e 25 56 a9 49 ed 8e 38 |..u.s....%V.I..8| +00000020 34 40 60 dc f0 2d f3 6c cf 5b 80 84 2b 81 db 5f |4@`..-.l.[..+.._| +00000030 f4 27 03 ad b8 8d 80 0c 99 69 6f |.'.......io| >>> Flow 5 (client to server) -00000000 17 03 01 00 20 f7 32 e7 36 4f 77 2f 4a 05 fd 27 |.... .2.6Ow/J..'| -00000010 19 57 52 f7 8a 0c 7f fb 14 78 b2 06 bf ca 86 73 |.WR......x.....s| -00000020 32 13 33 04 91 17 03 01 00 20 7e e4 fe c5 6d f7 |2.3...... ~...m.| -00000030 d4 69 30 57 89 a0 76 70 40 a7 b5 17 74 2f 5d 16 |.i0W..vp@...t/].| -00000040 c1 19 30 73 f8 37 c4 10 5b b7 15 03 01 00 20 08 |..0s.7..[..... .| -00000050 41 5e 0b 9f 36 23 bd 9a 09 f7 58 9d a3 d7 26 3a |A^..6#....X...&:| -00000060 f4 5e 6b bf 9c d4 6f 0c d3 9e cd de cb 95 57 |.^k...o.......W| +00000000 17 03 01 00 20 20 67 bd ff 84 9b 0e 58 f3 45 1e |.... g.....X.E.| +00000010 7a 25 d5 ae f0 26 4b 42 c7 f3 a5 77 7b 2f 42 21 |z%...&KB...w{/B!| +00000020 2e c6 c9 81 23 17 03 01 00 20 69 1c 2a b9 05 16 |....#.... i.*...| +00000030 8b 71 3a c2 18 76 bd 25 1f de 83 e9 14 e2 a3 5c |.q:..v.%.......\| +00000040 9b 33 ee 14 39 da e2 e7 a3 a7 15 03 01 00 20 e9 |.3..9......... .| +00000050 dc 16 0c 13 56 7a e5 fd ce b9 4f d1 c7 20 3f ca |....Vz....O.. ?.| +00000060 72 20 15 f7 11 81 fe 88 ab 90 4c dc 0b a5 11 |r ........L....| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA index c46a967..980f933 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA +++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 01 00 59 02 00 00 55 03 01 97 fe 7f 92 37 |....Y...U......7| -00000010 67 99 e0 d8 62 a9 31 80 bd 1f 31 8e 7d 0b 08 0a |g...b.1...1.}...| -00000020 de a5 82 a2 f2 d0 c1 35 66 34 6e 20 39 46 b1 b0 |.......5f4n 9F..| -00000030 6e 2d 0e fe 8c 48 ea ab 1c c4 49 ee f4 21 cf cb |n-...H....I..!..| -00000040 2a 20 57 78 18 99 a1 b9 7f 88 4f 64 c0 13 00 00 |* Wx......Od....| +00000000 16 03 01 00 59 02 00 00 55 03 01 4d 6d 71 59 6b |....Y...U..MmqYk| +00000010 cd 8c 6e b0 11 bf 4a 9e 25 90 12 cc ac b4 3f be |..n...J.%.....?.| +00000020 86 1b 13 47 a6 be 3d a0 8f 0b 77 20 6b b5 57 6d |...G..=...w k.Wm| +00000030 39 74 b0 9d b4 ae 2e 72 7e 90 d2 ab ed 32 fa 65 |9t.....r~....2.e| +00000040 ed 85 63 d2 16 ef 47 af a6 37 17 88 c0 13 00 00 |..c...G..7......| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 01 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,17 +60,17 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 01 00 |.=.`.\!.;.......| -000002c0 aa 0c 00 00 a6 03 00 1d 20 07 80 79 40 4b b1 0e |........ ..y@K..| -000002d0 05 ce e4 ca 9d f5 d7 ad a6 98 f2 40 f9 b9 66 a8 |...........@..f.| -000002e0 04 6e ae b5 da 99 67 09 69 00 80 01 4a f2 c1 c9 |.n....g.i...J...| -000002f0 2f 46 4f b8 9e 8b 2c c4 a1 32 44 3c dc 2c 5e b9 |/FO...,..2D<.,^.| -00000300 76 5f 41 20 23 1b 82 dd ec 37 b4 24 68 6d a7 39 |v_A #....7.$hm.9| -00000310 4f f2 e5 97 09 75 64 2a 64 16 b8 99 04 8a 74 77 |O....ud*d.....tw| -00000320 19 bb 12 5f 27 f6 41 09 f7 2e 1c 33 80 3b 01 57 |..._'.A....3.;.W| -00000330 5c f9 20 6e 0c 48 76 59 e1 8b 1f bb 2a 33 1a 28 |\. n.HvY....*3.(| -00000340 a0 5a 05 44 94 eb 35 62 5e ae 7f e4 01 76 b6 b4 |.Z.D..5b^....v..| -00000350 64 91 bf 25 09 ff 88 8a af 73 00 d0 7e ea 0f ca |d..%.....s..~...| -00000360 4a 2b d4 6f 02 26 98 28 5a ed 11 16 03 01 00 0a |J+.o.&.(Z.......| +000002c0 aa 0c 00 00 a6 03 00 1d 20 96 0b 2f 57 e1 1e 07 |........ ../W...| +000002d0 e0 7f a4 91 67 97 d0 a0 19 d3 9a b2 49 79 f9 5f |....g.......Iy._| +000002e0 7f b5 65 d4 3a 89 92 8f 11 00 80 08 29 72 0b f7 |..e.:.......)r..| +000002f0 7b 68 38 5e 47 15 89 f1 ee be f3 a9 26 a4 9c 6d |{h8^G.......&..m| +00000300 2c 2a ff f0 d6 2d 25 a5 b0 93 66 7d 8c fb fe a5 |,*...-%...f}....| +00000310 3b cc b6 71 f4 1b 55 c4 ef 08 73 b1 49 47 2c e6 |;..q..U...s.IG,.| +00000320 a1 ef 53 ca bb 15 e3 25 ea e7 48 44 18 88 e1 d2 |..S....%..HD....| +00000330 3b e9 f6 92 61 5e 5c 06 44 83 37 6c e6 b6 26 32 |;...a^\.D.7l..&2| +00000340 fd d6 00 fc 87 a2 37 e3 84 d2 ad 2d 99 0d e1 ba |......7....-....| +00000350 bb 2f 3b 0b dd 56 5c c2 14 af 86 58 2c 8b f8 64 |./;..V\....X,..d| +00000360 75 ab d3 35 41 59 fa fe a5 48 26 16 03 01 00 0a |u..5AY...H&.....| 00000370 0d 00 00 06 03 01 02 40 00 00 16 03 01 00 04 0e |.......@........| 00000380 00 00 00 |...| >>> Flow 3 (client to server) @@ -109,29 +109,29 @@ 00000200 e5 35 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| 00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| 00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 |......._X.;t....| -00000230 86 0f 00 00 82 00 80 81 aa 68 1f a9 a4 de f1 4d |.........h.....M| -00000240 30 9a fe e6 a5 f6 f6 18 b6 3e d2 c7 f1 e6 77 e3 |0........>....w.| -00000250 6a cd 61 01 81 3a 02 31 a5 aa d6 db b6 02 9d 4b |j.a..:.1.......K| -00000260 f5 78 50 c3 95 fe 43 88 33 3a 95 32 bc e8 02 1a |.xP...C.3:.2....| -00000270 e6 f4 d5 54 b9 fc e0 4a 4e f0 92 21 35 4b de c8 |...T...JN..!5K..| -00000280 a4 b0 01 c3 ca 3a 87 ed cb 21 1c ce c2 14 7b 8d |.....:...!....{.| -00000290 90 68 b9 21 49 13 dd cd e7 68 83 41 7c 84 6a 75 |.h.!I....h.A|.ju| -000002a0 76 ee 19 8b fa d5 a6 57 3d a7 f1 f1 6f 11 ca 77 |v......W=...o..w| -000002b0 95 0e b5 c7 3d 99 d4 14 03 01 00 01 01 16 03 01 |....=...........| -000002c0 00 30 5e be 40 82 f8 db 05 20 23 45 a4 42 48 e8 |.0^.@.... #E.BH.| -000002d0 06 69 eb 4c ef 79 53 52 4a 5a 3a ba cc d6 99 59 |.i.L.ySRJZ:....Y| -000002e0 4d c2 b0 34 0f 14 68 03 93 8b a4 95 7e cf 26 f8 |M..4..h.....~.&.| -000002f0 5c 8a |\.| +00000230 86 0f 00 00 82 00 80 8f 5d a5 27 13 09 5e 49 5f |........].'..^I_| +00000240 ff fd d6 88 75 83 cc 74 f3 e1 af 44 76 6a 35 16 |....u..t...Dvj5.| +00000250 e8 36 5f b7 dc 21 69 77 61 12 c5 69 f7 0d 98 1f |.6_..!iwa..i....| +00000260 d5 15 f1 e8 88 c5 30 e8 b5 c3 2a e5 26 93 cc a4 |......0...*.&...| +00000270 eb 31 c6 d7 f5 f4 7c d5 f7 a2 3f 1f 75 cd b2 b2 |.1....|...?.u...| +00000280 82 3a 03 8c 5e 15 0a d2 98 b8 65 cb 5f d5 db d0 |.:..^.....e._...| +00000290 b6 36 8c 89 7e 48 fa 3a 9f 9a bd c1 48 e7 d6 20 |.6..~H.:....H.. | +000002a0 ef 45 5b 24 32 04 58 82 b3 7b 42 fd fe ba 78 32 |.E[$2.X..{B...x2| +000002b0 2a f5 b7 81 33 da db 14 03 01 00 01 01 16 03 01 |*...3...........| +000002c0 00 30 5f 96 98 94 17 6d ff 84 72 d3 63 fd 14 59 |.0_....m..r.c..Y| +000002d0 eb bf 5f 3e 8f dc f1 c1 dc 77 8a 33 f6 2e a2 4a |.._>.....w.3...J| +000002e0 15 d1 2e a4 ec 0d 3c 0b 18 07 09 6c 0d 09 34 2e |......<....l..4.| +000002f0 a4 6f |.o| >>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 30 ef 9b 5c da 0a |..........0..\..| -00000010 2e c4 79 fa ea 8a 9c 78 4a 1f 08 77 56 73 6e fa |..y....xJ..wVsn.| -00000020 3a 5b 3c cd cd e9 0c a8 bb 59 9e 22 ab 67 2c 03 |:[<......Y.".g,.| -00000030 de ad 7c e4 cb 85 d7 8f c1 1c e3 |..|........| +00000000 14 03 01 00 01 01 16 03 01 00 30 b7 4a 5c 0c e6 |..........0.J\..| +00000010 7c d9 43 7c e7 b4 2f d7 b5 c6 5e 36 c7 87 dd 82 ||.C|../...^6....| +00000020 da d3 b2 4e 05 ae f5 8c b0 4d db c2 53 62 55 73 |...N.....M..SbUs| +00000030 8c 2a 1b d5 df e4 7c a4 cf db 8b |.*....|....| >>> Flow 5 (client to server) -00000000 17 03 01 00 20 48 1a 1a 1c 6c 7d 6c 2a e0 b2 e3 |.... H...l}l*...| -00000010 b3 9f ec 39 a8 cd 9a f9 a2 3e 2d 46 3b cf 17 ed |...9.....>-F;...| -00000020 70 99 ce d7 3c 17 03 01 00 20 69 27 e9 89 78 e6 |p...<.... i'..x.| -00000030 64 c0 a9 40 4f 0d 97 53 b2 2e 15 f3 2b 54 3b 77 |d..@O..S....+T;w| -00000040 f2 24 2c 94 dc b3 8b f0 c4 ce 15 03 01 00 20 1b |.$,........... .| -00000050 50 55 83 d8 6b b4 04 b2 f0 2d 1c 9c 0d fa de 58 |PU..k....-.....X| -00000060 cd 0a 1d 55 d6 36 f4 a4 fb cc 55 c5 b1 f3 d3 |...U.6....U....| +00000000 17 03 01 00 20 b9 26 60 87 38 9c d9 c4 65 17 8e |.... .&`.8...e..| +00000010 3c 7f 1a b4 23 cd 27 fd 4e 92 ee 0e f2 11 dc e2 |<...#.'.N.......| +00000020 23 e4 26 f3 55 17 03 01 00 20 5e 89 33 21 f0 dc |#.&.U.... ^.3!..| +00000030 e8 4f 33 1c 66 56 99 38 a5 4c 0e 0e 93 41 b7 48 |.O3.fV.8.L...A.H| +00000040 5d ce 49 d0 d2 8a 56 a6 2d 68 15 03 01 00 20 05 |].I...V.-h.... .| +00000050 e0 ed f9 c2 56 ec 64 e5 e7 0b f4 8a e2 41 96 9e |....V.d......A..| +00000060 ed 94 c8 95 69 d7 ce 2d 0e bb 5b 18 5f 30 52 |....i..-..[._0R| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES index 7d6683c..6fc506f 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES +++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 01 00 59 02 00 00 55 03 01 a7 ea 63 8c 7d |....Y...U....c.}| -00000010 54 70 04 d5 5e a2 2e 8b 75 4f 17 c8 a8 8c 3d bc |Tp..^...uO....=.| -00000020 08 aa 82 48 85 ed 1a ff 42 e1 54 20 3b 77 9d 32 |...H....B.T ;w.2| -00000030 4d 60 f2 81 f8 20 aa d2 b0 eb ea 7c 6a 39 52 20 |M`... .....|j9R | -00000040 94 4a 2a 88 05 8a fe 6c 50 5c 95 39 c0 09 00 00 |.J*....lP\.9....| +00000000 16 03 01 00 59 02 00 00 55 03 01 a3 4e 79 27 af |....Y...U...Ny'.| +00000010 c8 a3 15 a4 c2 7a 54 58 54 0e 0d 93 c2 ff e1 f9 |.....zTXT.......| +00000020 55 ab 2c ea 32 cf d2 47 2e d7 8e 20 49 08 d1 66 |U.,.2..G... I..f| +00000030 9b 9e aa af c9 90 95 ec cb 64 2e 3d f6 27 d5 f6 |.........d.=.'..| +00000040 23 10 d5 6e 50 5f bc 89 fe c7 d7 de c0 09 00 00 |#..nP_..........| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 01 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| 00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| @@ -55,37 +55,37 @@ 00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| 00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| 00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| -00000270 2a 16 03 01 00 b5 0c 00 00 b1 03 00 1d 20 3a 1f |*............ :.| -00000280 18 e9 f2 09 3e 79 4b a0 62 73 ef 87 0d ea 90 51 |....>yK.bs.....Q| -00000290 7f 9d d2 79 59 e4 11 7f 69 f7 a9 d7 78 7f 00 8b |...yY...i...x...| -000002a0 30 81 88 02 42 01 65 ac eb e6 b0 86 73 95 a4 27 |0...B.e.....s..'| -000002b0 e3 82 55 cf 88 16 80 c2 68 4b 39 77 2a b1 a9 d3 |..U.....hK9w*...| -000002c0 08 d5 ac 77 ce 5b 16 73 2c ad b5 57 2a 7a 75 34 |...w.[.s,..W*zu4| -000002d0 ec 99 23 bd df b2 27 36 5a 4b 40 e0 d3 b0 d2 31 |..#...'6ZK@....1| -000002e0 9b c7 9e 0a cb 5b 69 02 42 00 88 d7 5a 6a 9e 4c |.....[i.B...Zj.L| -000002f0 c5 7b 2c 8e 93 3b 75 27 b4 00 11 88 ba cf 99 8c |.{,..;u'........| -00000300 e5 f2 60 22 de f2 fe 86 a6 48 86 9c 40 31 08 75 |..`".....H..@1.u| -00000310 aa bc 5d 6d fa 2e a4 a9 a1 0d fc e1 d9 5a a1 60 |..]m.........Z.`| -00000320 93 b9 69 c7 c2 3e f5 a9 cb 31 41 16 03 01 00 04 |..i..>...1A.....| +00000270 2a 16 03 01 00 b5 0c 00 00 b1 03 00 1d 20 4a 7c |*............ J|| +00000280 0a 86 8a 81 f2 60 4a 3c ac d7 7d 3b fc 00 a5 b4 |.....`J<..};....| +00000290 85 45 45 45 fb 09 53 d7 4a cf 24 9d c8 1a 00 8b |.EEE..S.J.$.....| +000002a0 30 81 88 02 42 01 7a c9 c0 76 8c 26 98 63 4e a3 |0...B.z..v.&.cN.| +000002b0 ad 4f 4e a3 d7 c7 d6 4a 69 28 cf d2 7b 0b 36 fb |.ON....Ji(..{.6.| +000002c0 a3 ae 2f e1 83 ea ea 4a b7 2d ef a8 2d 13 96 e4 |../....J.-..-...| +000002d0 73 83 66 70 5e 5c d9 5a d1 1c d1 33 18 0b b3 30 |s.fp^\.Z...3...0| +000002e0 2a 21 d7 78 d8 70 18 02 42 00 c4 ab 80 33 8f f1 |*!.x.p..B....3..| +000002f0 c2 74 1b 58 2f 59 d4 27 a1 19 42 bf 14 ea a8 a2 |.t.X/Y.'..B.....| +00000300 cb bf 96 2d 60 7b 84 40 cc 31 f5 c4 e8 51 87 b8 |...-`{.@.1...Q..| +00000310 7b 47 ec c4 c0 4a 9b 09 59 1e f8 b5 9a e1 45 a4 |{G...J..Y.....E.| +00000320 a1 9b ee 78 55 f8 f5 fa 1a fb c5 16 03 01 00 04 |...xU...........| 00000330 0e 00 00 00 |....| >>> Flow 3 (client to server) 00000000 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 01 00 01 01 |....._X.;t......| -00000030 16 03 01 00 30 30 25 15 82 a1 7f 11 32 13 52 17 |....00%.....2.R.| -00000040 b8 bd 5b b9 1e 69 88 0b b3 5f 12 40 e3 4b 03 cb |..[..i..._.@.K..| -00000050 cd 07 3c 43 4f ab f7 5d 2c 6a a3 02 a9 64 d0 77 |..<CO..],j...d.w| -00000060 27 dc 4a ae 8a |'.J..| +00000030 16 03 01 00 30 b0 5e 4a 8a 07 e3 86 43 05 16 68 |....0.^J....C..h| +00000040 0e d1 58 a6 05 49 e9 a6 42 89 2c 3f 33 68 8b 26 |..X..I..B.,?3h.&| +00000050 23 21 3b 62 ab 7a 21 74 d8 49 15 03 b3 1e c6 53 |#!;b.z!t.I.....S| +00000060 74 1e 1c 4e 0f |t..N.| >>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 30 b5 3e 18 97 a1 |..........0.>...| -00000010 ca 2e 7f 5f b9 72 cb aa d4 f6 85 86 d3 27 40 13 |..._.r.......'@.| -00000020 e3 99 35 13 67 a8 9e 6e bb 63 15 97 96 42 e4 b3 |..5.g..n.c...B..| -00000030 fc 15 ee b7 d8 cb a2 64 3d 55 b8 |.......d=U.| +00000000 14 03 01 00 01 01 16 03 01 00 30 64 4b 3c 1a e3 |..........0dK<..| +00000010 7d bb bb bb 64 d8 51 c3 eb 92 65 65 58 35 dd 7b |}...d.Q...eeX5.{| +00000020 d2 fd f0 0c c1 10 71 a5 a8 f7 14 84 69 b4 81 18 |......q.....i...| +00000030 1e 0d d3 19 b6 23 72 1a a7 43 0e |.....#r..C.| >>> Flow 5 (client to server) -00000000 17 03 01 00 20 12 6c bf f2 39 2d e6 ad a8 38 d5 |.... .l..9-...8.| -00000010 1c ea 5b 79 e5 c7 4a 41 eb 58 70 f0 7d f7 60 e7 |..[y..JA.Xp.}.`.| -00000020 ee 77 98 75 f2 17 03 01 00 20 ac 5e 6d b0 81 0b |.w.u..... .^m...| -00000030 14 ca c2 70 53 d8 6d 55 49 63 da 8a 61 66 80 2d |...pS.mUIc..af.-| -00000040 e4 7c 2e 60 1f eb 3c f2 27 66 15 03 01 00 20 7a |.|.`..<.'f.... z| -00000050 2b 80 f8 00 0f 06 f5 6e fe b7 b7 6b 12 6c 8d 8e |+......n...k.l..| -00000060 c4 11 23 2b a2 bb 16 93 b4 e0 e0 fd 8c 42 db |..#+.........B.| +00000000 17 03 01 00 20 c3 e6 70 2c 44 4f 04 0c fb 0b 7f |.... ..p,DO.....| +00000010 1d 2c ef 4d cc c3 21 ba a2 db 74 76 46 ea 00 40 |.,.M..!...tvF..@| +00000020 54 2d 4a fe 59 17 03 01 00 20 0c 6b 39 0d b5 f3 |T-J.Y.... .k9...| +00000030 ed 7e d0 de 01 18 0c 32 4e 59 93 46 d3 c5 4f c0 |.~.....2NY.F..O.| +00000040 f5 fd f1 d2 79 07 7d 07 b0 24 15 03 01 00 20 1d |....y.}..$.... .| +00000050 f7 53 a2 e7 3f 88 87 35 01 6e a5 b1 d6 81 37 5b |.S..?..5.n....7[| +00000060 a7 64 4c 29 f4 71 59 a1 36 c1 1a 24 93 31 7d |.dL).qY.6..$.1}| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES index c0e842d..24da556 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES +++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 01 00 59 02 00 00 55 03 01 16 f4 24 01 94 |....Y...U....$..| -00000010 68 d2 0f 15 4d d6 65 54 84 73 ab 2c b2 11 c5 64 |h...M.eT.s.,...d| -00000020 d8 93 66 50 cd b0 f0 ab 11 5c 72 20 b1 13 c1 f5 |..fP.....\r ....| -00000030 63 ed 70 0b 21 52 85 36 84 99 1d b6 bb dc d3 1c |c.p.!R.6........| -00000040 b3 76 13 d9 ef 47 c4 c0 18 57 23 3b c0 13 00 00 |.v...G...W#;....| +00000000 16 03 01 00 59 02 00 00 55 03 01 63 68 ea 52 0b |....Y...U..ch.R.| +00000010 dc 68 c7 d0 75 3e 7d 6f 0b 8c cb 25 48 b0 bb df |.h..u>}o...%H...| +00000020 7a 56 93 a9 d5 4f 0c 3a e2 37 ab 20 1f 0f a4 d3 |zV...O.:.7. ....| +00000030 b4 f6 66 6f 39 6f 62 fb 6a 1f 41 09 4b 02 5c 15 |..fo9ob.j.A.K.\.| +00000040 a0 ba cb a6 f9 bd 3b ec cb 76 6e ea c0 13 00 00 |......;..vn.....| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 01 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,36 +60,36 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 01 00 |.=.`.\!.;.......| -000002c0 aa 0c 00 00 a6 03 00 1d 20 7e aa 30 94 7b fb 09 |........ ~.0.{..| -000002d0 b5 55 ce b3 e9 e0 5b 55 82 f4 e6 7c d0 e4 57 eb |.U....[U...|..W.| -000002e0 9b ec 82 48 d6 0e 2a bb 16 00 80 80 da c5 75 4f |...H..*.......uO| -000002f0 82 95 ee 47 28 af 09 08 d5 13 68 33 5d 91 dd 13 |...G(.....h3]...| -00000300 43 84 e9 54 d9 e7 39 7c 38 74 d5 92 8f 46 37 86 |C..T..9|8t...F7.| -00000310 44 68 ae c7 3a ad e1 33 5f cd d8 c6 a5 7c 5e 83 |Dh..:..3_....|^.| -00000320 44 ba b1 09 44 ec 42 7f 41 80 d6 b6 4c 6d ae 24 |D...D.B.A...Lm.$| -00000330 a9 3b 53 87 2f 3b 3a 1f da 87 2b 7d cf 9e ed a5 |.;S./;:...+}....| -00000340 04 54 ad c2 3c 7b 21 60 55 67 41 47 60 02 1e 62 |.T..<{!`UgAG`..b| -00000350 bb 9f ee 2c 6e 79 20 6e 65 e2 d0 ae 73 70 3e a7 |...,ny ne...sp>.| -00000360 3f 74 96 8e 2a 6e a6 7e 7a e0 e4 16 03 01 00 04 |?t..*n.~z.......| +000002c0 aa 0c 00 00 a6 03 00 1d 20 04 9f 8b 4f 13 83 26 |........ ...O..&| +000002d0 a3 cf 08 6e 59 bf b5 49 b8 ff 95 94 21 8d 2a 56 |...nY..I....!.*V| +000002e0 2e 4b be ad ac 89 6e 52 4d 00 80 5f 63 93 43 a2 |.K....nRM.._c.C.| +000002f0 a6 fb 53 b0 ac 93 3f 55 1d c1 0f 71 1e 96 ba 9f |..S...?U...q....| +00000300 86 19 f3 83 7d 90 ce 06 24 9a 60 69 f0 35 24 5d |....}...$.`i.5$]| +00000310 9d ce 49 0d 6f ba 31 59 3c f2 64 27 66 76 0e f1 |..I.o.1Y<.d'fv..| +00000320 33 eb b8 70 61 d3 0c 93 a3 62 c7 5e c2 06 9d 48 |3..pa....b.^...H| +00000330 16 2e a6 62 50 18 f6 c0 79 c2 09 f3 d5 74 bf db |...bP...y....t..| +00000340 b8 d4 25 06 a7 be 4a b0 62 82 86 d0 00 86 5e a2 |..%...J.b.....^.| +00000350 34 49 9b 37 37 9a b6 eb cc b9 8b 17 1f 29 4b a3 |4I.77........)K.| +00000360 51 e3 c3 e8 3e 6e df c4 1d e5 48 16 03 01 00 04 |Q...>n....H.....| 00000370 0e 00 00 00 |....| >>> Flow 3 (client to server) 00000000 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 01 00 01 01 |....._X.;t......| -00000030 16 03 01 00 30 5a cb 36 c8 1c 43 a8 e1 88 db c9 |....0Z.6..C.....| -00000040 ae 78 b0 af 97 e4 c3 f6 25 51 8e 4d 57 94 ee ca |.x......%Q.MW...| -00000050 a4 8b 3f 4d 17 75 34 58 c3 fa a6 6f d4 e5 ae 3a |..?M.u4X...o...:| -00000060 cb 5a cb 11 ef |.Z...| +00000030 16 03 01 00 30 a6 3a 66 02 e6 09 6a dd 68 56 bc |....0.:f...j.hV.| +00000040 aa ec 82 c4 69 9b b9 45 44 ec e2 c2 5b 49 5d 9b |....i..ED...[I].| +00000050 f8 0e 81 1e 23 9e 13 72 d1 d2 0c 24 01 4f 35 aa |....#..r...$.O5.| +00000060 27 fc b3 cc 08 |'....| >>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 30 96 92 50 6f f0 |..........0..Po.| -00000010 d1 ff 7c 39 fb 75 0c 8b c9 d7 29 7d 9d 32 4c 19 |..|9.u....)}.2L.| -00000020 2e 93 ea 11 87 07 fc 5a 7d 3c 30 e1 bd 64 7f 90 |.......Z}<0..d..| -00000030 fd 70 1d 50 eb ec f2 d6 de 09 61 |.p.P......a| +00000000 14 03 01 00 01 01 16 03 01 00 30 0e 25 d7 a9 c0 |..........0.%...| +00000010 18 3b bf 55 c0 47 3a 95 2d cb 6f c2 2c de e3 94 |.;.U.G:.-.o.,...| +00000020 32 d3 eb e2 b6 6b 5f 42 9c 1e 47 d6 76 0c eb 95 |2....k_B..G.v...| +00000030 fd 2d c3 9a ee ee 83 87 e8 8d 83 |.-.........| >>> Flow 5 (client to server) -00000000 17 03 01 00 20 fd a4 ba f1 78 a9 a2 45 d3 d2 5a |.... ....x..E..Z| -00000010 1e 41 6b 89 8d bd a4 21 69 03 a1 7c b8 56 ff df |.Ak....!i..|.V..| -00000020 67 bc 85 5e 21 17 03 01 00 20 a7 6d 4c 11 d0 f3 |g..^!.... .mL...| -00000030 7d e2 f0 69 18 7c 42 71 78 e4 3b 71 7d 13 27 bb |}..i.|Bqx.;q}.'.| -00000040 79 fd d7 b2 d7 28 ca 92 83 f1 15 03 01 00 20 10 |y....(........ .| -00000050 b3 79 d4 1d 70 db b7 6c f2 15 05 3c 4d 65 ba ec |.y..p..l...<Me..| -00000060 e8 0e 6a ba 88 90 53 2e 6e 29 9c 56 9f 52 5e |..j...S.n).V.R^| +00000000 17 03 01 00 20 ba b0 c4 22 ee 52 81 ca 55 97 4d |.... ...".R..U.M| +00000010 39 16 b9 37 bf df 7b d1 ae 4b 47 ac 10 12 a9 77 |9..7..{..KG....w| +00000020 69 50 f3 60 13 17 03 01 00 20 90 d5 17 e4 96 38 |iP.`..... .....8| +00000030 cd f7 30 6e 19 45 4e 32 ad 5f 1b 00 bf 22 9d c2 |..0n.EN2._..."..| +00000040 16 30 fe 92 c7 fc 91 38 29 30 15 03 01 00 20 c0 |.0.....8)0.... .| +00000050 02 ff 81 82 c9 25 c6 b0 06 ee 18 61 19 c8 d2 20 |.....%.....a... | +00000060 d8 4e 7b a4 a5 57 17 64 4d ad 1e 1e 16 1e 52 |.N{..W.dM.....R| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ExportKeyingMaterial b/libgo/go/crypto/tls/testdata/Client-TLSv10-ExportKeyingMaterial index 1c65914..6a40d83 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv10-ExportKeyingMaterial +++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ExportKeyingMaterial @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 01 00 59 02 00 00 55 03 01 7a a4 22 4f 19 |....Y...U..z."O.| -00000010 54 37 47 cb e5 dd b4 54 86 9e 9e d6 3f f1 bd ca |T7G....T....?...| -00000020 9a 3e 16 3c 7e 1a 29 22 0d c8 95 20 ac 85 42 c1 |.>.<~.)"... ..B.| -00000030 e7 f3 38 62 38 24 a8 24 d2 67 bd 0d 06 44 74 cf |..8b8$.$.g...Dt.| -00000040 3d a4 37 17 bc 8c 5d 41 9f 5a 74 69 c0 13 00 00 |=.7...]A.Zti....| +00000000 16 03 01 00 59 02 00 00 55 03 01 05 31 9d 41 04 |....Y...U...1.A.| +00000010 c0 d4 34 1a fc 0f 63 26 47 d6 13 7f a0 d8 aa bf |..4...c&G.......| +00000020 28 92 04 80 02 75 58 e6 01 e1 30 20 3c fc b0 02 |(....uX...0 <...| +00000030 8b a4 9e 9e b2 5c 17 3c 48 0b 96 6f 15 80 d5 38 |.....\.<H..o...8| +00000040 25 a2 f8 fb 6b fd 47 27 c2 53 6c 60 c0 13 00 00 |%...k.G'.Sl`....| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 01 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,36 +60,36 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 01 00 |.=.`.\!.;.......| -000002c0 aa 0c 00 00 a6 03 00 1d 20 71 52 12 72 a7 56 0b |........ qR.r.V.| -000002d0 51 81 af 9f e1 95 43 44 54 0e 9e 3d cc 6f 3c 4c |Q.....CDT..=.o<L| -000002e0 d7 9c e4 ae d5 ad 13 8b 28 00 80 46 29 b1 46 71 |........(..F).Fq| -000002f0 ba 0a 3d be 29 0f 57 43 02 05 4e 49 a4 5b cd 39 |..=.).WC..NI.[.9| -00000300 1c 44 6d 84 02 60 84 b6 7f ff 4e d8 0e e7 16 5a |.Dm..`....N....Z| -00000310 dd 3b 5a e0 e5 d0 b6 2c fb 95 35 94 a0 b6 97 24 |.;Z....,..5....$| -00000320 92 d7 b1 71 78 ee 15 6f b2 47 fd c7 a6 a4 94 eb |...qx..o.G......| -00000330 44 61 9f 96 83 1d 89 a6 62 d9 9e 5b b2 3d 69 9d |Da......b..[.=i.| -00000340 59 c5 a4 4e e0 33 69 0c 56 6f 86 6c 6b e5 be c4 |Y..N.3i.Vo.lk...| -00000350 ed e4 39 53 f3 fd ea 60 d2 b7 d9 5e 90 fd a3 3e |..9S...`...^...>| -00000360 cb 59 5d 81 da 58 07 83 e7 af 25 16 03 01 00 04 |.Y]..X....%.....| +000002c0 aa 0c 00 00 a6 03 00 1d 20 a4 50 9a 0d c7 2a 1b |........ .P...*.| +000002d0 f6 d4 78 49 68 ac 5f 8b e7 78 68 05 4b f8 c6 b3 |..xIh._..xh.K...| +000002e0 eb 28 79 96 d5 e6 aa c1 54 00 80 22 66 ec fd 14 |.(y.....T.."f...| +000002f0 83 7b 03 86 14 75 84 a4 a6 d0 ee d3 d0 f7 95 d8 |.{...u..........| +00000300 43 48 a4 eb 83 af 96 ac cf e8 65 20 05 c3 18 9a |CH........e ....| +00000310 54 63 f5 2f b7 17 06 e0 2a b3 65 6a 2f cc cd 93 |Tc./....*.ej/...| +00000320 1e b3 5a 4d 09 da 70 b0 12 46 60 11 e4 9f ee 9f |..ZM..p..F`.....| +00000330 3b 6f ef df bc db 69 22 5e e8 4c 41 d6 b7 7b 06 |;o....i"^.LA..{.| +00000340 b6 99 1c 6d 01 5a 61 7c 4e 3a af 3e 01 7e 46 bd |...m.Za|N:.>.~F.| +00000350 c8 15 28 ba 7f b3 d6 9d 95 74 04 36 6c 38 16 86 |..(......t.6l8..| +00000360 d2 1d 8a 85 d1 21 5c 33 17 50 a1 16 03 01 00 04 |.....!\3.P......| 00000370 0e 00 00 00 |....| >>> Flow 3 (client to server) 00000000 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 01 00 01 01 |....._X.;t......| -00000030 16 03 01 00 30 c3 26 49 92 5a 8c d0 da 48 ba 60 |....0.&I.Z...H.`| -00000040 29 c0 5c d5 44 04 11 7a 25 b5 d6 9f a4 cf fe bf |).\.D..z%.......| -00000050 33 a7 ba c2 96 2b 4d c1 fb dc 4c ba b8 2b 6f 20 |3....+M...L..+o | -00000060 2d 2a 02 ee 17 |-*...| +00000030 16 03 01 00 30 f0 15 ea 81 0f a6 22 0a cd a5 a1 |....0......"....| +00000040 38 4a da 1b 6c 81 19 d5 35 b7 af e9 ec 16 4d 98 |8J..l...5.....M.| +00000050 21 c2 0e f7 0b fb ff d8 1e 2d 8b 04 56 82 48 c4 |!........-..V.H.| +00000060 e5 f9 38 8c d2 |..8..| >>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 30 f4 4e 0a ea 58 |..........0.N..X| -00000010 18 c6 9d 5f aa 5d f0 03 d4 63 0d e7 83 cb a8 18 |..._.]...c......| -00000020 06 fa b6 82 da df 16 89 5c 8b 5d 92 87 b1 42 da |........\.]...B.| -00000030 cd 2a ee dc 43 08 f1 0d 1f 18 5c |.*..C.....\| +00000000 14 03 01 00 01 01 16 03 01 00 30 f0 b5 a3 bb bb |..........0.....| +00000010 9d 85 7d 6f e7 a9 17 31 65 74 82 69 56 a9 33 21 |..}o...1et.iV.3!| +00000020 16 9d 75 3a 28 88 a5 c2 a9 e1 a7 43 6e 03 26 96 |..u:(......Cn.&.| +00000030 37 4b de 63 be 49 cb c8 d4 a2 b6 |7K.c.I.....| >>> Flow 5 (client to server) -00000000 17 03 01 00 20 e6 95 10 e0 98 07 9f 2b 42 06 b8 |.... .......+B..| -00000010 2a 6c 5d 4a 95 2a 2c 17 d5 cc 68 42 18 bd 72 58 |*l]J.*,...hB..rX| -00000020 c1 39 73 05 75 17 03 01 00 20 d4 ae 70 ee a0 ed |.9s.u.... ..p...| -00000030 3e dd f9 aa 93 03 ff f5 a4 f6 f3 0d e7 a6 59 a9 |>.............Y.| -00000040 40 b4 f6 ad a5 46 0b eb ee 0e 15 03 01 00 20 7c |@....F........ || -00000050 1a 29 f3 49 60 47 2e 52 ec 00 4a 62 44 30 93 5f |.).I`G.R..JbD0._| -00000060 df 73 2f 44 65 3f 77 c1 3d 04 32 c8 bb 86 ed |.s/De?w.=.2....| +00000000 17 03 01 00 20 a9 9c 8f 74 ce f9 77 bc b3 86 2e |.... ...t..w....| +00000010 a5 8e 94 3d 08 a6 96 bf 25 0b 10 c4 66 c2 59 9a |...=....%...f.Y.| +00000020 4a 1a b4 77 12 17 03 01 00 20 03 72 60 38 58 88 |J..w..... .r`8X.| +00000030 86 20 20 3f 18 52 c5 ca 55 3c 04 04 c7 e1 74 6f |. ?.R..U<....to| +00000040 ca 1f cd 27 64 f2 51 12 9c ee 15 03 01 00 20 30 |...'d.Q....... 0| +00000050 71 2a 78 bf 8b d5 11 7c 63 11 c7 25 0e 56 25 ce |q*x....|c..%.V%.| +00000060 24 d5 d7 de a0 ba c7 ba e6 dc db 8e e3 93 a6 |$..............| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4 b/libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4 index 1fe13b9..dcc18ad 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 01 00 51 02 00 00 4d 03 01 5a 4f 78 41 d5 |....Q...M..ZOxA.| -00000010 86 2f d2 0a c6 05 bc c9 8e cc bd b2 39 ac a5 78 |./..........9..x| -00000020 e3 e5 31 b9 cb 01 af cb ca fc 88 20 c9 61 c6 91 |..1........ .a..| -00000030 b2 e5 70 df ca d0 41 a8 20 61 ab 08 f6 dc fe c0 |..p...A. a......| -00000040 cc ea 1e 80 89 02 6a 26 ea f0 c8 71 00 05 00 00 |......j&...q....| +00000000 16 03 01 00 51 02 00 00 4d 03 01 2a 09 26 d2 61 |....Q...M..*.&.a| +00000010 ac 38 91 3d 18 3f f7 a9 3c 34 91 b0 b1 e1 29 68 |.8.=.?..<4....)h| +00000020 dd cb b9 a9 d8 39 0b 64 c6 93 7d 20 ea 51 ff 63 |.....9.d..} .Q.c| +00000030 97 03 b2 6f a3 d6 55 0d 64 65 2a 5d 3a fe e9 3e |...o..U.de*]:..>| +00000040 47 c1 7d c5 d8 03 c6 22 19 2f 6c 5a 00 05 00 00 |G.}...."./lZ....| 00000050 05 ff 01 00 01 00 16 03 01 02 59 0b 00 02 55 00 |..........Y...U.| 00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| 00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| @@ -70,15 +70,15 @@ 00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..| 00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| 00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 01 00 01 |.Y(.....ia5.....| -00000090 01 16 03 01 00 24 48 fd e6 fc 4a 94 33 82 22 ff |.....$H...J.3.".| -000000a0 af c3 44 98 d2 c6 4e 8a 39 43 dd 4b 2a 11 2b 4e |..D...N.9C.K*.+N| -000000b0 5b d9 a4 fc 6c 95 d7 69 05 f9 |[...l..i..| +00000090 01 16 03 01 00 24 29 ee 6c 54 d6 21 5e 31 30 9e |.....$).lT.!^10.| +000000a0 fd 02 69 bb 32 c2 9e ad 28 b1 2d 94 49 0a 12 0c |..i.2...(.-.I...| +000000b0 a1 12 b0 98 a6 33 eb 63 2b e4 |.....3.c+.| >>> Flow 4 (server to client) -00000000 14 03 01 00 01 01 16 03 01 00 24 61 d2 68 5e 12 |..........$a.h^.| -00000010 91 6e 7f fe bf b7 42 58 e9 06 38 09 c1 16 34 e5 |.n....BX..8...4.| -00000020 a1 46 d6 cf 23 ca 48 c1 ed 76 f9 48 a1 9a 2a |.F..#.H..v.H..*| +00000000 14 03 01 00 01 01 16 03 01 00 24 32 3e 45 f2 3a |..........$2>E.:| +00000010 01 05 50 db 37 25 f6 b5 67 8e 38 3d f5 ba b7 90 |..P.7%..g.8=....| +00000020 e0 05 a8 cb e0 33 1a 79 ab 44 86 d5 0c fd 86 |.....3.y.D.....| >>> Flow 5 (client to server) -00000000 17 03 01 00 1a 3a e1 39 7c fe 25 50 dc 66 3f b6 |.....:.9|.%P.f?.| -00000010 6f fd 79 3b 12 83 af 89 b1 c5 f6 75 56 ad a1 15 |o.y;.......uV...| -00000020 03 01 00 16 07 d1 d3 7a 54 1c 71 0b c8 64 10 46 |.......zT.q..d.F| -00000030 30 d0 bf df 75 a6 dc 10 b1 d1 |0...u.....| +00000000 17 03 01 00 1a ac 0c 1f 12 4e d4 31 10 dd c1 04 |.........N.1....| +00000010 8b 55 a2 2e a5 f4 e4 80 aa 23 7e bd 79 b0 ee 15 |.U.......#~.y...| +00000020 03 01 00 16 fa d9 ff 50 7d 41 01 2a d2 13 ee 33 |.......P}A.*...3| +00000030 52 ab 20 c5 e7 73 81 5d 81 60 |R. ..s.].`| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES index 9d18cd6..92cdc4c 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES +++ b/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 02 00 59 02 00 00 55 03 02 23 a8 e7 14 3f |....Y...U..#...?| -00000010 64 61 3c ee 80 a2 94 84 ab b8 66 76 30 84 06 78 |da<.......fv0..x| -00000020 96 ba a7 d3 1e 81 1b 16 64 76 88 20 3d 21 21 b3 |........dv. =!!.| -00000030 45 dd fe cb 5b d7 9a 86 39 ee 4f f8 60 eb 95 ea |E...[...9.O.`...| -00000040 ab 64 48 14 74 16 fd e9 47 07 66 60 c0 09 00 00 |.dH.t...G.f`....| +00000000 16 03 02 00 59 02 00 00 55 03 02 bf ac 6b 91 53 |....Y...U....k.S| +00000010 dc 1f d6 ee 0e 71 d6 a4 f5 a2 7c f0 10 69 41 dd |.....q....|..iA.| +00000020 4a b7 30 53 e6 28 07 31 34 8f e5 20 59 d1 bd e1 |J.0S.(.14.. Y...| +00000030 20 44 c4 05 07 e9 07 90 5d de 08 73 72 55 04 a6 | D......]..srU..| +00000040 11 20 bf 32 e0 dd 46 d4 1d ed 45 62 c0 09 00 00 |. .2..F...Eb....| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 02 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| 00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| @@ -55,39 +55,39 @@ 00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| 00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| 00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| -00000270 2a 16 03 02 00 b4 0c 00 00 b0 03 00 1d 20 a7 a4 |*............ ..| -00000280 33 20 48 6a 74 8e 07 fc c0 b6 10 61 84 d6 67 d1 |3 Hjt......a..g.| -00000290 ae cf 65 36 4d d5 13 a1 07 fc 1f aa 77 44 00 8a |..e6M.......wD..| -000002a0 30 81 87 02 42 01 02 5b f9 4a af 8d 0a d5 a3 de |0...B..[.J......| -000002b0 11 62 d8 f1 db 49 7a 0c 34 3e 2d 61 f9 6f 6b c2 |.b...Iz.4>-a.ok.| -000002c0 1d 32 4b 88 93 9b 22 b0 3d 09 c3 93 9e 25 31 d6 |.2K...".=....%1.| -000002d0 5f 06 3a f0 4a 61 0b 06 03 5d 6c 0e b3 5e 48 5a |_.:.Ja...]l..^HZ| -000002e0 f0 5b 21 48 58 8f b2 02 41 1c 57 f1 51 04 d6 f8 |.[!HX...A.W.Q...| -000002f0 a2 51 e6 e6 3e e0 99 63 aa d2 1c 7b 92 be 44 ec |.Q..>..c...{..D.| -00000300 86 c3 31 fa e7 9b 98 1a 59 a5 93 3e a9 73 f0 ec |..1.....Y..>.s..| -00000310 03 22 37 19 db 78 30 27 ab bf 52 07 6c 3a 79 f5 |."7..x0'..R.l:y.| -00000320 ad 70 59 76 84 44 f0 47 e0 3d 16 03 02 00 04 0e |.pYv.D.G.=......| -00000330 00 00 00 |...| +00000270 2a 16 03 02 00 b5 0c 00 00 b1 03 00 1d 20 ab ea |*............ ..| +00000280 ff 17 1e b1 ef f6 22 03 40 8b e1 1a fa ab 01 cf |......".@.......| +00000290 0f f0 b0 6d 43 3c 1f 03 a1 d6 4a 9d 79 43 00 8b |...mC<....J.yC..| +000002a0 30 81 88 02 42 00 a1 b4 50 4b 9b a3 a5 ec ef dc |0...B...PK......| +000002b0 bf c1 a2 65 24 2a 6c aa ab 26 01 ed d1 ad 2e 37 |...e$*l..&.....7| +000002c0 4f f5 8b ff 98 ac ef 15 3e d9 46 07 a3 d2 35 de |O.......>.F...5.| +000002d0 91 bc 3d a0 1f f1 68 55 28 ef 60 ad 13 05 ac 65 |..=...hU(.`....e| +000002e0 e5 67 02 3f 85 8b 1b 02 42 01 26 3f fc 62 e3 93 |.g.?....B.&?.b..| +000002f0 8e fa fb 93 0f 0b ff 68 25 46 ea 71 16 ae 6e d4 |.......h%F.q..n.| +00000300 36 9e 48 2c 77 2b d8 f5 f6 1d 69 68 ed 28 8f e7 |6.H,w+....ih.(..| +00000310 79 7e 78 56 52 ff e8 62 fc e2 bd 2e c7 e8 9f 3f |y~xVR..b.......?| +00000320 93 47 d2 62 6c f6 5c 0e a2 b8 fe 16 03 02 00 04 |.G.bl.\.........| +00000330 0e 00 00 00 |....| >>> Flow 3 (client to server) 00000000 16 03 02 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 02 00 01 01 |....._X.;t......| 00000030 16 03 02 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| -00000040 00 00 00 00 00 ef 0f 92 ac 11 fe 97 1a 46 69 e4 |.............Fi.| -00000050 b3 26 8d d7 92 46 02 25 5b 2e 86 3e 96 3d 64 ed |.&...F.%[..>.=d.| -00000060 37 92 dd ae a5 a6 9f 03 f0 c2 42 78 9f b9 78 ac |7.........Bx..x.| -00000070 97 ab 82 25 e2 |...%.| +00000040 00 00 00 00 00 0f 55 37 4b 93 d5 ce b1 1c 6f a3 |......U7K.....o.| +00000050 6d 56 32 f5 de 19 f6 a3 15 b0 6a 90 06 92 60 ca |mV2.......j...`.| +00000060 ec 0e 2b d4 24 16 0a 26 f3 bd 3d ca c5 9f d2 9b |..+.$..&..=.....| +00000070 79 2f af b6 b0 |y/...| >>> Flow 4 (server to client) -00000000 14 03 02 00 01 01 16 03 02 00 40 df a9 23 37 74 |..........@..#7t| -00000010 47 d8 98 87 53 b4 0a 4d b0 a5 fb cb d6 37 c8 7c |G...S..M.....7.|| -00000020 61 95 81 ef b3 63 78 2b 53 c2 86 fc 39 df c4 5f |a....cx+S...9.._| -00000030 e4 4b af 1d fe bc 4c fe 1b 6a 28 c3 46 6f 24 94 |.K....L..j(.Fo$.| -00000040 a8 bf ef ce e8 e8 ad 2c d9 10 32 |.......,..2| +00000000 14 03 02 00 01 01 16 03 02 00 40 4d e3 a9 af 51 |..........@M...Q| +00000010 f5 d1 cd 04 f1 cf c5 48 0f 2e 0b 6e 57 4c 11 28 |.......H...nWL.(| +00000020 dd 89 19 14 98 8e 2e 92 db 3c a4 0f 85 32 90 7e |.........<...2.~| +00000030 49 13 17 a0 85 fa c6 25 79 24 13 90 86 dc ec 45 |I......%y$.....E| +00000040 7c 74 35 92 e4 89 04 c2 51 27 66 ||t5.....Q'f| >>> Flow 5 (client to server) 00000000 17 03 02 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -00000010 00 00 00 00 00 34 50 ce 9c 7f f5 2d a2 c1 e4 5c |.....4P....-...\| -00000020 fa d1 a0 f4 38 e8 4f 51 54 36 07 da f1 af 6d ef |....8.OQT6....m.| -00000030 b8 b0 bc bc a6 15 03 02 00 30 00 00 00 00 00 00 |.........0......| -00000040 00 00 00 00 00 00 00 00 00 00 0b d4 8e e8 69 64 |..............id| -00000050 53 38 7c 72 d8 1d 9f d5 8a 83 74 a7 37 6b e2 c0 |S8|r......t.7k..| -00000060 8f 26 e7 5d 0e 06 ae e0 db fb |.&.]......| +00000010 00 00 00 00 00 f9 ac 17 1f 08 b7 80 fb 70 87 e2 |.............p..| +00000020 53 00 27 60 78 6c 80 5b 57 e7 70 72 8a e3 1b 32 |S.'`xl.[W.pr...2| +00000030 8c f0 67 82 82 15 03 02 00 30 00 00 00 00 00 00 |..g......0......| +00000040 00 00 00 00 00 00 00 00 00 00 01 e1 86 47 7f 65 |.............G.e| +00000050 a9 d2 1c 22 7d 99 7c 41 dc 17 f5 16 40 5b b3 7f |..."}.|A....@[..| +00000060 cc 0b 97 41 0c ae 1f 0c 39 e0 |...A....9.| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES index 4cc9610..b2b7ecb 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES +++ b/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 02 00 59 02 00 00 55 03 02 6e ff 3b 26 66 |....Y...U..n.;&f| -00000010 7c 32 3f 42 fd 92 7c 12 db 26 b2 45 6e 28 b9 49 ||2?B..|..&.En(.I| -00000020 86 6b 00 54 92 3b 65 a6 02 6d 94 20 ea 44 db 5c |.k.T.;e..m. .D.\| -00000030 d1 39 35 b2 ea 1c 6d 3e 94 bb 47 60 25 1e 9c 74 |.95...m>..G`%..t| -00000040 e7 bd 54 cc 2b 36 14 6a 12 54 5b 6c c0 13 00 00 |..T.+6.j.T[l....| +00000000 16 03 02 00 59 02 00 00 55 03 02 95 6e 24 5a ab |....Y...U...n$Z.| +00000010 ae 3c 73 52 9d 31 63 50 cf f9 50 99 3c e4 94 22 |.<sR.1cP..P.<.."| +00000020 5b 6f 0e f8 e3 a8 64 4c d2 8c 00 20 8b 2d 25 47 |[o....dL... .-%G| +00000030 f9 74 41 93 b1 82 b5 c5 fc 3e 42 c9 35 fc 68 27 |.tA......>B.5.h'| +00000040 c4 2b 35 0f f8 1c e3 28 e6 8a 59 dc c0 13 00 00 |.+5....(..Y.....| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 02 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,38 +60,38 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 02 00 |.=.`.\!.;.......| -000002c0 aa 0c 00 00 a6 03 00 1d 20 82 3b d2 56 dd cd d8 |........ .;.V...| -000002d0 e1 98 a7 90 d1 08 2d 37 dc e8 21 cd 29 af 29 a5 |......-7..!.).).| -000002e0 78 8e 59 9e 4c ac c9 d2 4b 00 80 25 20 91 4e 0d |x.Y.L...K..% .N.| -000002f0 74 12 9e 1c 98 fb 5f 4b ad fd c8 68 df 6b 82 98 |t....._K...h.k..| -00000300 a8 7c ee 17 44 47 91 2a 42 c1 82 d0 ce aa cd f8 |.|..DG.*B.......| -00000310 69 1e 85 79 27 fe ef 5a a2 e1 35 30 9a 2d c6 b0 |i..y'..Z..50.-..| -00000320 43 84 39 7f 8d 68 09 d6 6c 1a 84 0f c0 9a c0 9f |C.9..h..l.......| -00000330 64 56 cb fc 32 f2 4a a3 26 e8 c2 5f d7 16 3e 7c |dV..2.J.&.._..>|| -00000340 4e 8b 89 f8 7f f4 c2 26 fe 01 cd 48 b6 61 9c 93 |N......&...H.a..| -00000350 1a bc a1 d1 01 c5 bf ef 43 b4 ca 86 62 37 b4 99 |........C...b7..| -00000360 54 69 db 74 51 92 92 dd c1 b1 75 16 03 02 00 04 |Ti.tQ.....u.....| +000002c0 aa 0c 00 00 a6 03 00 1d 20 b5 75 ee e5 26 6b c0 |........ .u..&k.| +000002d0 af 34 8a 24 f7 c5 25 58 29 38 4c 08 d3 a2 0c 48 |.4.$..%X)8L....H| +000002e0 18 eb a0 5b e8 64 62 62 78 00 80 d0 1c 9c 11 1a |...[.dbbx.......| +000002f0 58 4c 46 5f 18 03 d7 d7 76 47 d5 56 7a bb bd 95 |XLF_....vG.Vz...| +00000300 16 46 e8 0b 28 6e df 15 65 1a f6 95 fb 4a 6c 42 |.F..(n..e....JlB| +00000310 1b 4c 5c 30 c5 de d0 83 08 d3 2e 4d 59 7e 7b 1b |.L\0.......MY~{.| +00000320 20 9e b5 19 76 fe a3 dd 87 04 f4 9a 3e 3c c0 4a | ...v.......><.J| +00000330 16 7f e3 4e 9a 1f 0a 36 1d f5 09 b4 88 09 b1 1b |...N...6........| +00000340 9b 60 97 dc d7 ea 97 f4 d6 06 16 45 98 ee 5c 39 |.`.........E..\9| +00000350 62 3f 7c 82 7b c3 52 59 01 d4 89 8c a6 e2 d5 eb |b?|.{.RY........| +00000360 e8 30 a6 78 49 1e ec a5 92 ad 24 16 03 02 00 04 |.0.xI.....$.....| 00000370 0e 00 00 00 |....| >>> Flow 3 (client to server) 00000000 16 03 02 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 02 00 01 01 |....._X.;t......| 00000030 16 03 02 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| -00000040 00 00 00 00 00 c5 bf e6 b3 86 12 92 df 68 fa 75 |.............h.u| -00000050 79 5f ee fe 60 91 d1 fd 8a 48 3b 97 b4 da 7f 58 |y_..`....H;....X| -00000060 3e 7e 40 d7 93 1d 6b e2 0e 2a a4 45 20 e0 9d f9 |>~@...k..*.E ...| -00000070 b6 5e b1 f1 4f |.^..O| +00000040 00 00 00 00 00 28 ab ed 77 d3 56 29 a8 4a 38 c8 |.....(..w.V).J8.| +00000050 64 1c a5 d9 4e f9 6b 0e fa 82 42 ad 0d be 15 69 |d...N.k...B....i| +00000060 9a ff 79 64 db 8f 3e 16 b3 86 93 82 6f 78 c4 2e |..yd..>.....ox..| +00000070 7c 54 6c 4f 90 ||TlO.| >>> Flow 4 (server to client) -00000000 14 03 02 00 01 01 16 03 02 00 40 bf 58 92 80 02 |..........@.X...| -00000010 75 91 40 30 35 e0 16 76 f4 97 bd 77 46 a3 a3 4e |u.@05..v...wF..N| -00000020 f1 be 53 eb b8 56 45 b1 71 c9 f8 a9 bf c6 9a 00 |..S..VE.q.......| -00000030 83 46 91 88 d5 7b 72 95 27 33 80 43 3f 3e f6 60 |.F...{r.'3.C?>.`| -00000040 c6 55 90 6a 87 8e 7d 48 27 e2 40 |.U.j..}H'.@| +00000000 14 03 02 00 01 01 16 03 02 00 40 15 e9 c5 15 59 |..........@....Y| +00000010 b3 0d 46 22 0c ae a6 41 02 b4 f3 da 11 dc 85 79 |..F"...A.......y| +00000020 bb d9 3f 23 38 51 24 1a 08 b5 a0 63 dc 4b 86 50 |..?#8Q$....c.K.P| +00000030 ef b2 32 07 fd b5 e1 01 06 19 42 ce ba 69 ab 1a |..2.......B..i..| +00000040 c9 bb db 7d d0 9f f9 7c f2 6c 18 |...}...|.l.| >>> Flow 5 (client to server) 00000000 17 03 02 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -00000010 00 00 00 00 00 f5 6b bc 6d 2c 70 b1 c0 f0 ab 78 |......k.m,p....x| -00000020 44 c9 97 f6 59 ef 15 e4 05 cf e0 55 ee a4 68 8c |D...Y......U..h.| -00000030 86 57 82 bd 84 15 03 02 00 30 00 00 00 00 00 00 |.W.......0......| -00000040 00 00 00 00 00 00 00 00 00 00 ef b2 a9 a5 bb a3 |................| -00000050 6e e5 d1 2b ef 83 1d 11 de 29 d2 30 2c fc 78 73 |n..+.....).0,.xs| -00000060 6b 6e 0a d2 55 67 5c d4 58 b3 |kn..Ug\.X.| +00000010 00 00 00 00 00 67 ef de df a4 91 69 58 b8 3f 06 |.....g.....iX.?.| +00000020 c4 05 4e ad 88 9b c5 12 35 cf 63 39 3a 61 e9 4c |..N.....5.c9:a.L| +00000030 49 22 93 f4 10 15 03 02 00 30 00 00 00 00 00 00 |I".......0......| +00000040 00 00 00 00 00 00 00 00 00 00 00 2a 5a ba 39 7e |...........*Z.9~| +00000050 a8 be 2e 72 f3 ba 7e 0a 32 b5 8c d8 f5 1b 93 6c |...r..~.2......l| +00000060 3e 35 d8 ba cc f3 9f f4 19 74 |>5.......t| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4 b/libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4 index 9dae5dd..aeba311 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 02 00 51 02 00 00 4d 03 02 96 ca 2a e7 23 |....Q...M....*.#| -00000010 af 2e 45 62 15 fa 5a 84 bc aa 7c 79 03 1b 37 69 |..Eb..Z...|y..7i| -00000020 a0 77 ce 03 81 b7 e5 7d 31 34 6e 20 93 83 5d 7c |.w.....}14n ..]|| -00000030 e8 c7 48 f9 67 ec 97 b1 27 b6 de de 89 07 5a cf |..H.g...'.....Z.| -00000040 44 77 48 4b e9 62 43 e3 87 fd de 87 00 05 00 00 |DwHK.bC.........| +00000000 16 03 02 00 51 02 00 00 4d 03 02 82 5b 12 ac 33 |....Q...M...[..3| +00000010 08 d4 28 8c 91 6e 52 c4 c6 09 13 24 bf 42 d2 37 |..(..nR....$.B.7| +00000020 6d 78 60 b0 ea bd 9e b3 08 99 43 20 05 5a 93 f9 |mx`.......C .Z..| +00000030 a4 39 43 4f c4 e3 27 20 7d 4c fa 7a 28 c1 c7 33 |.9CO..' }L.z(..3| +00000040 72 fa 14 b8 ba c3 89 b0 a5 54 a3 7c 00 05 00 00 |r........T.|....| 00000050 05 ff 01 00 01 00 16 03 02 02 59 0b 00 02 55 00 |..........Y...U.| 00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| 00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| @@ -70,15 +70,15 @@ 00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..| 00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| 00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 02 00 01 |.Y(.....ia5.....| -00000090 01 16 03 02 00 24 33 5d 7f cb 6e 36 19 8b db 35 |.....$3]..n6...5| -000000a0 88 16 87 7a 9d 5a 51 27 51 13 17 64 0e 57 d5 e1 |...z.ZQ'Q..d.W..| -000000b0 6e 34 8d e6 99 a8 38 b2 e7 3a |n4....8..:| +00000090 01 16 03 02 00 24 e1 1a bf e9 fd 4c fb 56 41 82 |.....$.....L.VA.| +000000a0 c2 48 fc ca d9 d5 ec 2a 0a ee 63 25 e0 5f 53 cf |.H.....*..c%._S.| +000000b0 24 ff fe da 6f f5 8b 61 b7 b9 |$...o..a..| >>> Flow 4 (server to client) -00000000 14 03 02 00 01 01 16 03 02 00 24 e0 8b 90 9b 83 |..........$.....| -00000010 f5 3d 00 e9 cf 7b 1d 75 cf c8 16 f2 29 8d de 0b |.=...{.u....)...| -00000020 75 82 b1 c4 6e 1c 1f ab e9 90 74 31 99 f2 ad |u...n.....t1...| +00000000 14 03 02 00 01 01 16 03 02 00 24 99 2c e7 fa d0 |..........$.,...| +00000010 29 d9 92 07 39 56 b0 0c ad 23 30 c8 d7 0b 38 da |)...9V...#0...8.| +00000020 6f d3 c7 f9 66 d2 ec 8c 52 85 cb db a6 22 50 |o...f...R...."P| >>> Flow 5 (client to server) -00000000 17 03 02 00 1a ca 2a 95 13 de 40 0d af 44 a4 aa |......*...@..D..| -00000010 9a 35 d7 38 c7 9f 74 4f 3a bf d1 9c cd 9e ee 15 |.5.8..tO:.......| -00000020 03 02 00 16 d3 a4 32 78 a9 00 1b 7a 48 3e 7c 2b |......2x...zH>|+| -00000030 f9 3b 92 32 20 0b f4 16 39 18 |.;.2 ...9.| +00000000 17 03 02 00 1a 9f 70 c4 77 f3 0a a8 e0 1a 75 87 |......p.w.....u.| +00000010 ab 2a f1 23 52 79 9f 5c 8e af 5d ba 27 45 f9 15 |.*.#Ry.\..].'E..| +00000020 03 02 00 16 f0 28 f3 71 a0 97 6b ba 7e 97 81 85 |.....(.q..k.~...| +00000030 11 59 1b c9 fa a0 48 32 e9 65 |.Y....H2.e| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256 b/libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256 index 4412f53..ce92872 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 51 02 00 00 4d 03 03 1d be be 1e eb |....Q...M.......| -00000010 59 2c d5 07 b9 7a 64 47 95 84 ef cf d9 3e 82 4c |Y,...zdG.....>.L| -00000020 00 c0 0a 69 8a 01 2a b3 42 78 02 20 5e 32 5c 88 |...i..*.Bx. ^2\.| -00000030 50 ed d5 44 41 4f bf a9 4e 49 83 5d aa 7c 2e 5d |P..DAO..NI.].|.]| -00000040 85 e8 64 92 5e 49 5d 8a d0 0e 89 eb 00 9c 00 00 |..d.^I].........| +00000000 16 03 03 00 51 02 00 00 4d 03 03 a4 26 bb e9 70 |....Q...M...&..p| +00000010 57 4e ec f8 ea 23 01 75 c3 f3 a9 d4 d6 e8 71 2b |WN...#.u......q+| +00000020 01 5e c0 73 19 2b b9 d8 8e 3e d1 20 c8 c3 0a 22 |.^.s.+...>. ..."| +00000030 7b ee cd 2e c9 e8 95 db 90 db 70 f5 59 e6 90 65 |{.........p.Y..e| +00000040 35 87 a6 d4 bb dd 85 34 43 e8 66 49 00 9c 00 00 |5......4C.fI....| 00000050 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.| 00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| 00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| @@ -70,17 +70,17 @@ 00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..| 00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| 00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 03 00 01 |.Y(.....ia5.....| -00000090 01 16 03 03 00 28 00 00 00 00 00 00 00 00 69 38 |.....(........i8| -000000a0 97 84 2e 77 5c b8 58 82 b5 78 85 2e f3 7b 92 81 |...w\.X..x...{..| -000000b0 00 72 91 23 41 ae 59 6c 18 64 f0 62 f2 c9 |.r.#A.Yl.d.b..| +00000090 01 16 03 03 00 28 00 00 00 00 00 00 00 00 64 6c |.....(........dl| +000000a0 08 78 1d 03 0c ed dd 01 30 d4 fb 7c 3f 24 45 cc |.x......0..|?$E.| +000000b0 f6 b2 e3 42 07 93 8f 34 a8 21 d1 b0 08 e3 |...B...4.!....| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 37 f7 98 2f 78 |..........(7../x| -00000010 54 85 5f 2e cb a9 b7 bf 4b 2d 62 06 e2 32 cd 18 |T._.....K-b..2..| -00000020 de f5 54 c8 e0 54 2d c5 b4 98 07 7e c7 b7 79 a0 |..T..T-....~..y.| -00000030 75 af 5c |u.\| +00000000 14 03 03 00 01 01 16 03 03 00 28 75 9b 91 cd 7d |..........(u...}| +00000010 8d f7 3c a0 d6 5e d4 f2 24 1a 0a f3 04 b1 d9 0b |..<..^..$.......| +00000020 1d 31 ca 1c 8b e7 38 c0 8e 7d 12 19 89 33 28 4d |.1....8..}...3(M| +00000030 83 28 b6 |.(.| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 78 c1 c0 |.............x..| -00000010 7d 1b a8 b2 80 0e a3 64 cf e0 fa 71 9d 37 5d 32 |}......d...q.7]2| -00000020 8d 36 38 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.68.............| -00000030 c2 f3 41 1a 2c a4 4f 48 fa 61 14 40 60 51 e5 99 |..A.,.OH.a.@`Q..| -00000040 c6 e5 |..| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 7d fe 53 |.............}.S| +00000010 73 aa ca 3d f3 27 b7 01 56 9e e7 c9 6d 79 2a 97 |s..=.'..V...my*.| +00000020 b2 21 42 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.!B.............| +00000030 de bd 3e 9e 8f c0 98 ec bd b4 9b 89 90 a2 26 a8 |..>...........&.| +00000040 28 97 |(.| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-SHA256 b/libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-SHA256 index d756884..15394c7 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-SHA256 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-SHA256 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 51 02 00 00 4d 03 03 c3 41 d7 9c 1b |....Q...M...A...| -00000010 9a ff f8 17 af 41 df 8d 96 70 bb b8 f6 9a 4c a2 |.....A...p....L.| -00000020 03 25 31 2c 58 fa 05 5b 12 85 6a 20 18 3c 34 d6 |.%1,X..[..j .<4.| -00000030 08 44 46 a5 5c b1 40 0d 38 33 c0 2d ea a6 46 53 |.DF.\.@.83.-..FS| -00000040 0e 09 39 6f 11 35 02 63 cf 21 74 c2 00 3c 00 00 |..9o.5.c.!t..<..| +00000000 16 03 03 00 51 02 00 00 4d 03 03 8a a8 2c 00 d8 |....Q...M....,..| +00000010 d8 87 53 14 1e 7b ff ca 19 a2 6d bc 47 6f 73 12 |..S..{....m.Gos.| +00000020 0d 54 6e 33 21 80 01 86 f8 81 9f 20 46 f6 8c e8 |.Tn3!...... F...| +00000030 8b 90 02 b2 da e2 83 3a 2a 0f b3 f7 96 2b f8 96 |.......:*....+..| +00000040 56 77 39 52 9e a1 bd 74 1e 2e b1 b0 00 3c 00 00 |Vw9R...t.....<..| 00000050 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.| 00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| 00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| @@ -71,25 +71,25 @@ 00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| 00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 03 00 01 |.Y(.....ia5.....| 00000090 01 16 03 03 00 50 00 00 00 00 00 00 00 00 00 00 |.....P..........| -000000a0 00 00 00 00 00 00 88 20 99 51 5e fb 72 79 7f f8 |....... .Q^.ry..| -000000b0 b2 a9 56 96 a3 03 1d a0 e0 38 1a be 4c ea 80 f9 |..V......8..L...| -000000c0 c0 ef 45 81 91 7f b9 1b f7 91 3b 4e 05 87 d6 73 |..E.......;N...s| -000000d0 c0 27 94 50 4f 00 ee c1 02 af 5f 6f 4c a5 0e 5b |.'.PO....._oL..[| -000000e0 6c 76 87 28 b4 bf |lv.(..| +000000a0 00 00 00 00 00 00 8f d8 ac 7f ec 16 9e d8 e9 f2 |................| +000000b0 ce 30 51 dc 87 e0 f9 80 57 66 d9 87 20 77 3a b1 |.0Q.....Wf.. w:.| +000000c0 43 db fc 36 f5 64 6e 96 e9 b8 e2 ab bb 00 48 36 |C..6.dn.......H6| +000000d0 60 9c 5a 7c 38 3f 13 e1 9c ef d9 15 96 91 56 e2 |`.Z|8?........V.| +000000e0 87 2e 23 1a 98 40 |..#..@| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 50 93 14 a5 13 16 |..........P.....| -00000010 d7 af 14 81 94 33 2d ae f7 7a b1 b1 a5 38 fb e8 |.....3-..z...8..| -00000020 c8 38 b3 ce f1 eb 70 e7 84 b6 fc 25 25 32 a9 09 |.8....p....%%2..| -00000030 d1 0d 2d 59 57 6d d0 42 e8 c1 81 92 d0 af fb 5a |..-YWm.B.......Z| -00000040 08 7e 0f 3d 10 e5 42 6d 27 cd 8c 32 b2 20 4b 0a |.~.=..Bm'..2. K.| -00000050 75 76 ed 08 54 fe 74 94 72 35 9e |uv..T.t.r5.| +00000000 14 03 03 00 01 01 16 03 03 00 50 80 01 08 cc d8 |..........P.....| +00000010 08 a8 81 20 b2 bb 5b 50 79 74 4a b5 10 c4 7a 30 |... ..[PytJ...z0| +00000020 6c 46 d6 e5 36 6e 4d cc e5 0c 2c ab 3b de 92 45 |lF..6nM...,.;..E| +00000030 ee 20 58 a9 0f 03 26 3e 6c 05 a7 ef f2 7c a7 9b |. X...&>l....|..| +00000040 57 c0 20 8d d0 69 0e b0 5a cc e6 26 5f e2 c3 24 |W. ..i..Z..&_..$| +00000050 c4 db df 20 03 08 e1 aa 59 2b d2 |... ....Y+.| >>> Flow 5 (client to server) 00000000 17 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| -00000010 00 00 00 00 00 53 91 38 34 33 20 94 0d 76 d7 72 |.....S.843 ..v.r| -00000020 48 f3 17 34 01 ae 0e 89 db 60 f1 4e 64 a5 cf 0c |H..4.....`.Nd...| -00000030 32 52 3f a0 18 f8 c5 57 ed 3a d1 41 19 81 cf 0a |2R?....W.:.A....| -00000040 f2 d8 90 4b ba 15 03 03 00 40 00 00 00 00 00 00 |...K.....@......| -00000050 00 00 00 00 00 00 00 00 00 00 05 2b 31 3c 1b a2 |...........+1<..| -00000060 11 87 5f 0f 49 72 bb 67 e6 75 18 9c b1 f4 6c ed |.._.Ir.g.u....l.| -00000070 4d 01 58 35 30 43 44 e8 ee 1d f2 81 9d 67 6d 77 |M.X50CD......gmw| -00000080 1e 36 61 7f f3 32 3d 60 73 6d |.6a..2=`sm| +00000010 00 00 00 00 00 a2 dd a6 ff 57 60 80 dd 97 cf 20 |.........W`.... | +00000020 10 04 60 80 53 17 37 ce ce 39 b6 21 f4 06 61 aa |..`.S.7..9.!..a.| +00000030 49 7b f0 d5 e0 72 4c 6f 38 d2 ab af 1c 94 bd 5b |I{...rLo8......[| +00000040 1b ee 8a 9b e3 15 03 03 00 40 00 00 00 00 00 00 |.........@......| +00000050 00 00 00 00 00 00 00 00 00 00 ba 18 32 e7 6d f5 |............2.m.| +00000060 fa 2e 61 55 cc fe 3c 4d 19 fd 84 6d c4 2a 46 92 |..aU..<M...m.*F.| +00000070 ae b7 f3 67 c8 3c ce cd b0 66 de ee 5d 3f 07 3b |...g.<...f..]?.;| +00000080 a9 85 a1 93 1f 98 f7 95 c9 ac |..........| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384 b/libgo/go/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384 index 2f552cb..766bf95 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 51 02 00 00 4d 03 03 2b 59 94 f3 9e |....Q...M..+Y...| -00000010 23 ae d3 58 82 1f 2e be 38 1d 14 e4 4c a4 b8 ed |#..X....8...L...| -00000020 95 08 b9 44 60 02 4b 0b a9 6e ae 20 9b 43 e5 2a |...D`.K..n. .C.*| -00000030 0f 08 8e a4 c1 c0 15 79 9f af a5 ab a3 67 9d 09 |.......y.....g..| -00000040 23 0e 8e 96 a9 aa 7d 26 74 d8 0c 9a 00 9d 00 00 |#.....}&t.......| +00000000 16 03 03 00 51 02 00 00 4d 03 03 de 7a 77 5b eb |....Q...M...zw[.| +00000010 fa 84 a0 ac ba 3b ca 25 dc b3 c0 06 44 da 31 5c |.....;.%....D.1\| +00000020 27 e0 4e af be 47 07 5a a5 ab 20 20 72 b2 67 0c |'.N..G.Z.. r.g.| +00000030 7e 71 5d e3 55 89 91 27 7f 65 ac 71 c6 e8 a5 4a |~q].U..'.e.q...J| +00000040 ae e1 a2 0d 3f a6 62 08 17 7e 26 fd 00 9d 00 00 |....?.b..~&.....| 00000050 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.| 00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| 00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| @@ -70,17 +70,17 @@ 00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..| 00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| 00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 03 00 01 |.Y(.....ia5.....| -00000090 01 16 03 03 00 28 00 00 00 00 00 00 00 00 59 fc |.....(........Y.| -000000a0 aa b1 84 ab 09 82 00 88 8e e4 82 6e cd 24 9f b5 |...........n.$..| -000000b0 01 95 d3 c3 f4 a2 16 54 25 91 77 76 fc f0 |.......T%.wv..| +00000090 01 16 03 03 00 28 00 00 00 00 00 00 00 00 0b 7d |.....(.........}| +000000a0 83 0f 79 e2 4b ef d3 0e ff 57 d2 55 cd ea e9 be |..y.K....W.U....| +000000b0 8b 38 1e 33 b0 6a eb e3 aa 51 52 82 e6 15 |.8.3.j...QR...| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 67 ac 20 d9 b6 |..........(g. ..| -00000010 a9 f0 ec f6 7b 34 31 3a 5e 06 20 0f 5b 32 86 1b |....{41:^. .[2..| -00000020 da 5a c5 54 47 d0 ad 4f 95 2c b5 1f 17 3f ec 17 |.Z.TG..O.,...?..| -00000030 a3 01 fc |...| +00000000 14 03 03 00 01 01 16 03 03 00 28 1a a3 bb d4 c4 |..........(.....| +00000010 53 c7 5c 09 8c fb e7 51 41 73 d5 76 ef e6 40 9a |S.\....QAs.v..@.| +00000020 06 27 c6 e8 9f 1b 25 f5 d1 7b 39 b7 74 ab e8 83 |.'....%..{9.t...| +00000030 26 f6 40 |&.@| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 6c 9c 0a |.............l..| -00000010 ae 0b 40 57 8b 24 6d 09 77 ae 2f 14 be 06 26 9e |..@W.$m.w./...&.| -00000020 0a bf 18 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................| -00000030 32 50 20 68 3d 05 68 ed 0c ac 7a db 24 21 7e e0 |2P h=.h...z.$!~.| -00000040 9e f0 |..| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 1c 0d 06 |................| +00000010 d2 25 8a 06 d9 b4 d6 76 89 1c c6 b7 22 9f 44 63 |.%.....v....".Dc| +00000020 a3 f9 89 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................| +00000030 cb 34 e8 4b f7 b1 ab 1a 74 60 2c 2d cf a4 7d 9f |.4.K....t`,-..}.| +00000040 f4 b4 |..| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN b/libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN index 358b211..8b9a510 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 8f 00 05 00 05 01 00 00 00 00 00 0a 00 |................| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -18,11 +18,11 @@ 00000100 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| 00000110 cb 3b 74 |.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 66 02 00 00 62 03 03 95 14 55 52 0b |....f...b....UR.| -00000010 e7 c1 15 6b dc 19 3b 17 9e bb 6a b7 61 82 dc 59 |...k..;...j.a..Y| -00000020 d3 a4 7c e1 c3 83 cc e2 e5 56 e0 20 3c 82 0d 54 |..|......V. <..T| -00000030 2b 78 fe 50 cb 4e c1 69 d7 6f b3 9f ac 2e 27 c8 |+x.P.N.i.o....'.| -00000040 c6 7a 70 27 1e 14 67 43 4c f1 7d d7 cc a8 00 00 |.zp'..gCL.}.....| +00000000 16 03 03 00 66 02 00 00 62 03 03 2d b3 e1 a8 44 |....f...b..-...D| +00000010 c6 3e 20 b9 50 49 ab b8 48 c3 bf d6 f3 7b 2e 0a |.> .PI..H....{..| +00000020 8c 49 ba e5 8e 54 5e 02 59 01 75 20 f0 a0 60 c2 |.I...T^.Y.u ..`.| +00000030 81 df 62 f9 f8 7d 3c 3c ee 1e 0c 1d c2 11 58 7f |..b..}<<......X.| +00000040 e0 dc b1 6c 17 9e 19 60 ca c2 40 84 cc a8 00 00 |...l...`..@.....| 00000050 1a ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 10 |................| 00000060 00 09 00 07 06 70 72 6f 74 6f 31 16 03 03 02 59 |.....proto1....Y| 00000070 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 |...U..R..O0..K0.| @@ -63,31 +63,31 @@ 000002a0 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 |.....@.a.Lr+...F| 000002b0 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 |..M...>...B...=.| 000002c0 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 ac 0c 00 |`.\!.;..........| -000002d0 00 a8 03 00 1d 20 c3 e3 43 9c 5d 0f 09 61 ae 18 |..... ..C.]..a..| -000002e0 66 05 b1 7d c1 9f e5 26 9c a7 97 d6 1f 9a 7c ff |f..}...&......|.| -000002f0 8c 34 a1 32 a2 35 08 04 00 80 6c 50 a1 80 d9 20 |.4.2.5....lP... | -00000300 56 08 da d9 5b 77 4d ad 43 66 71 15 ec fe db 02 |V...[wM.Cfq.....| -00000310 fb 40 d8 8d 67 22 e2 1b ec 8d b9 4e ba 65 01 8b |.@..g".....N.e..| -00000320 70 e0 83 bc 06 1b 14 8f 07 cf a6 08 58 c3 77 94 |p...........X.w.| -00000330 0f 94 53 62 54 6c 1f 92 22 9d ae f8 5a ad d5 f3 |..SbTl.."...Z...| -00000340 8a f7 e6 93 8c 0e 48 1b 23 89 d8 bd e9 5c 50 cd |......H.#....\P.| -00000350 07 3d 7e 8e b0 d6 65 44 58 62 03 a1 d9 94 72 f0 |.=~...eDXb....r.| -00000360 25 a9 e0 c1 be ac 32 05 59 f7 7f 6e 13 23 70 5a |%.....2.Y..n.#pZ| -00000370 65 ba a2 d7 da 3c a2 9e 6b 13 16 03 03 00 04 0e |e....<..k.......| +000002d0 00 a8 03 00 1d 20 7b 47 ec ef 4d 39 ec 65 b9 7c |..... {G..M9.e.|| +000002e0 08 da b5 41 0d 62 0b 52 29 24 25 3d 39 21 ed d3 |...A.b.R)$%=9!..| +000002f0 30 37 0c 15 66 49 08 04 00 80 4b 01 8e 80 78 ed |07..fI....K...x.| +00000300 d1 44 e5 98 a4 43 9a 73 b7 dc 67 72 83 29 f3 e3 |.D...C.s..gr.)..| +00000310 5b 72 ee d6 36 12 db bf ab d6 86 fd a8 54 a5 a0 |[r..6........T..| +00000320 0e 76 ca ea a7 f5 f2 e1 87 94 a7 c5 d8 69 b7 58 |.v...........i.X| +00000330 d2 f0 10 08 8c 08 ac bd aa 60 f5 45 20 15 77 71 |.........`.E .wq| +00000340 5a bb 2a 8b 0a 4b a3 08 71 88 82 01 3c bc 54 ba |Z.*..K..q...<.T.| +00000350 f4 42 7a 08 64 d7 57 5b dc ea 6a 72 e1 7d ca 96 |.Bz.d.W[..jr.}..| +00000360 d9 89 eb 60 9e d2 a4 f5 cb d5 45 d1 4d 09 4e 18 |...`......E.M.N.| +00000370 a2 4f 0f 59 97 a1 5f 7f 65 4f 16 03 03 00 04 0e |.O.Y.._.eO......| 00000380 00 00 00 |...| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 5e 91 45 7d ab 7c b7 6f 57 a6 d0 |.... ^.E}.|.oW..| -00000040 17 83 cb 40 1b 76 6b 5e 80 39 03 2f 6d 2f 10 8e |...@.vk^.9./m/..| -00000050 74 33 12 54 8d |t3.T.| +00000030 16 03 03 00 20 b9 f7 58 6f d3 29 b8 41 35 06 b7 |.... ..Xo.).A5..| +00000040 55 85 c1 f0 63 fe 4f 5f 87 01 cc 67 0b f1 4c b4 |U...c.O_...g..L.| +00000050 ca 92 bd c0 6d |....m| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 f1 3c 7a 28 eb |.......... .<z(.| -00000010 0a b1 bf 42 28 de 07 83 76 c6 2c 94 b7 d5 ef f3 |...B(...v.,.....| -00000020 0b 9c 0c 2e d3 ab 8a a9 03 d2 c0 |...........| +00000000 14 03 03 00 01 01 16 03 03 00 20 68 92 93 84 bd |.......... h....| +00000010 0e de 33 1b db ca 54 b8 a0 2f 53 c5 76 de d2 c5 |..3...T../S.v...| +00000020 7a 54 bb db 0c 08 86 79 d2 6c 58 |zT.....y.lX| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 dc f6 18 54 22 e0 9c 08 bf db a8 |........T"......| -00000010 62 2a 64 9e 06 43 0f 22 18 0e 34 15 03 03 00 12 |b*d..C."..4.....| -00000020 20 2f f4 76 cd dc 82 eb 30 f9 e0 42 6b 29 16 ed | /.v....0..Bk)..| -00000030 7c f0 ||.| +00000000 17 03 03 00 16 79 38 07 9b be 83 44 9a 3e 11 1a |.....y8....D.>..| +00000010 99 2f f2 4e 33 84 0b c7 8e ed c3 15 03 03 00 12 |./.N3...........| +00000020 ca bd 7e 59 04 8c e0 52 80 1e 56 1e af c1 5f 61 |..~Y...R..V..._a| +00000030 6c 6a |lj| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA index e40999f..e1fb8a8 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 08 a4 b1 ad 21 |....Y...U......!| -00000010 3a 60 7a d3 3b 60 67 48 5d de da ff 3f a8 55 a9 |:`z.;`gH]...?.U.| -00000020 c4 72 69 32 12 c1 d1 4e d4 78 e1 20 6e 9f ed 1e |.ri2...N.x. n...| -00000030 50 9a 31 e2 ae e2 6a f4 01 cc 94 21 25 73 f3 a5 |P.1...j....!%s..| -00000040 f6 28 b3 c6 6b c1 b3 2d fc 0c d3 66 c0 09 00 00 |.(..k..-...f....| +00000000 16 03 03 00 59 02 00 00 55 03 03 36 60 84 12 26 |....Y...U..6`..&| +00000010 51 e4 32 33 26 ef c3 31 bf ea ac 27 0f c3 fb cb |Q.23&..1...'....| +00000020 05 89 af df 56 a9 3f 14 6e 5e 2c 20 ad 6e 60 2d |....V.?.n^, .n`-| +00000030 94 aa e5 73 22 eb 68 92 77 1c 6c cb f4 5a 14 f2 |...s".h.w.l..Z..| +00000040 29 85 88 aa 2e 56 2a ad 80 e1 f0 b1 c0 09 00 00 |)....V*.........| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| 00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| @@ -55,18 +55,18 @@ 00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| 00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| 00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| -00000270 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 ec f3 |*............ ..| -00000280 2b 3b be 93 68 53 f2 ab 6c 97 5a fa 9b 8c bf eb |+;..hS..l.Z.....| -00000290 37 6f af d7 b8 02 f3 8c 0b f9 75 29 11 32 04 03 |7o........u).2..| -000002a0 00 8b 30 81 88 02 42 01 9d 90 aa b3 19 d2 9d cf |..0...B.........| -000002b0 92 c1 64 05 89 db d0 dd 80 f3 a4 7e 09 ec 36 22 |..d........~..6"| -000002c0 95 79 c4 36 0e 21 80 7d 4b 72 a5 38 a4 b0 a7 5f |.y.6.!.}Kr.8..._| -000002d0 fb ae f7 66 23 82 91 c2 f8 95 df 60 ce dc e8 1a |...f#......`....| -000002e0 3f 2b 2c fa 5e 58 67 98 78 02 42 00 fa 88 7f ae |?+,.^Xg.x.B.....| -000002f0 00 55 2c a1 c2 47 ed c8 11 74 64 e7 c6 30 63 fb |.U,..G...td..0c.| -00000300 bb 42 2a 02 9b 80 60 88 e7 3f af 17 a3 7f 1e f6 |.B*...`..?......| -00000310 31 9c 1f 8c 89 e5 a0 b1 01 2a 4e d8 d2 1e 9f 11 |1........*N.....| -00000320 f5 e3 35 38 3e b0 da 30 f1 fb ed e5 d1 16 03 03 |..58>..0........| +00000270 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 87 2c |*............ .,| +00000280 f2 fd 8e b9 3d 5f 1c c8 bb 04 f5 1e 01 a8 ba d8 |....=_..........| +00000290 b6 8e 61 78 15 9e 3b a7 da 96 8e 77 d7 70 04 03 |..ax..;....w.p..| +000002a0 00 8b 30 81 88 02 42 01 dc e2 26 f9 18 39 da 7d |..0...B...&..9.}| +000002b0 bd a1 30 c6 6f dd cd aa a0 4f 71 cf 42 76 61 ba |..0.o....Oq.Bva.| +000002c0 e7 9f 09 b5 05 f2 76 c7 db 2a 93 83 3b 0b 3a cf |......v..*..;.:.| +000002d0 60 96 24 c8 af de 2c db 5a 29 1c 62 67 28 e9 d7 |`.$...,.Z).bg(..| +000002e0 57 5f 54 18 cc bf ee d1 d9 02 42 01 04 cf 67 0b |W_T.......B...g.| +000002f0 62 2c c2 17 a3 f4 f1 32 0f c5 b9 ae 3b 52 36 2b |b,.....2....;R6+| +00000300 f0 c0 60 49 08 e0 bf f5 7c 09 13 e4 b8 ba 08 c7 |..`I....|.......| +00000310 ea 74 a0 f5 88 45 e4 35 f1 c5 4e df fe 45 bc ca |.t...E.5..N..E..| +00000320 9c 5f c8 84 66 13 8f b3 c9 7e b2 ba d6 16 03 03 |._..f....~......| 00000330 00 3a 0d 00 00 36 03 01 02 40 00 2e 04 03 05 03 |.:...6...@......| 00000340 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| 00000350 08 06 04 01 05 01 06 01 03 03 02 03 03 01 02 01 |................| @@ -108,32 +108,32 @@ 00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| 00000210 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd 62 |...%...! /.}.G.b| 00000220 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| -00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 93 0f 00 |...._X.;t.......| -00000240 00 8f 04 03 00 8b 30 81 88 02 42 01 e6 0a ff de |......0...B.....| -00000250 af a6 d2 7a 5f 4e f8 eb c8 19 74 53 5c e8 bc 2d |...z_N....tS\..-| -00000260 72 24 11 d2 11 ec ec cd a1 9c 3d 10 a2 de f8 8b |r$........=.....| -00000270 22 98 d3 33 c2 13 3b 93 89 ae ca a6 a8 94 70 fe |"..3..;.......p.| -00000280 76 2f 04 bc ac fb 66 79 3b 76 7f 6d 96 02 42 01 |v/....fy;v.m..B.| -00000290 df f6 30 14 7c 7e a1 0b f6 b8 8b d7 75 b8 bd 0e |..0.|~......u...| -000002a0 63 8a bd 8b ec 75 70 db d9 37 d7 53 f3 8b a2 ae |c....up..7.S....| -000002b0 60 96 69 74 eb bb 3d a6 9a 7d 46 51 73 ff 78 cf |`.it..=..}FQs.x.| -000002c0 7f 49 d9 27 5e 9f f9 d2 11 cc 0e e4 dc 04 fe d5 |.I.'^...........| -000002d0 d2 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 |...........@....| -000002e0 00 00 00 00 00 00 00 00 00 00 00 00 7a db 34 e9 |............z.4.| -000002f0 98 f8 c1 f0 38 c3 33 22 5c c3 45 b0 a3 10 3c 77 |....8.3"\.E...<w| -00000300 7f d2 06 c5 f8 13 b6 f4 ee 7e 53 0b 07 0b c3 c9 |.........~S.....| -00000310 89 9a a9 bb 3b af 79 09 59 ce 10 41 |....;.y.Y..A| +00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 92 0f 00 |...._X.;t.......| +00000240 00 8e 04 03 00 8a 30 81 87 02 42 01 8f ff aa 8c |......0...B.....| +00000250 bd 0c 94 39 34 e5 39 7b d2 12 26 8e 94 4a fd 68 |...94.9{..&..J.h| +00000260 f2 f5 5b 30 69 e1 42 3a 74 cd 9a 37 75 5c d2 a6 |..[0i.B:t..7u\..| +00000270 c9 7b b1 83 c1 d9 c5 55 1a af 3d 19 64 02 43 c0 |.{.....U..=.d.C.| +00000280 0a 1c 0e ff f4 42 85 fb d1 aa a2 52 1a 02 41 2f |.....B.....R..A/| +00000290 c6 23 d7 37 f1 36 75 0c 0f b4 49 14 c4 b4 d9 28 |.#.7.6u...I....(| +000002a0 c1 00 2d e4 d6 93 fd a0 f5 59 4e 45 0c a4 28 d4 |..-......YNE..(.| +000002b0 dc aa 7b 0b 28 29 12 94 f6 db 8c 23 af 81 7e ab |..{.().....#..~.| +000002c0 fd 12 ba 11 27 b2 10 87 89 61 9f 5d 6d 18 79 c5 |....'....a.]m.y.| +000002d0 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| +000002e0 00 00 00 00 00 00 00 00 00 00 00 2d 3e 6e 02 fb |...........->n..| +000002f0 50 cc 37 62 77 17 08 ef 71 e6 06 23 82 ba 97 b7 |P.7bw...q..#....| +00000300 0f 38 f9 5e 05 63 4c c9 04 6e bd e4 78 76 32 3b |.8.^.cL..n..xv2;| +00000310 3a a7 9b de 30 ca ed fb 17 dc 40 |:...0.....@| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 40 18 c0 f3 96 7b |..........@....{| -00000010 45 91 6d 5b 1c 67 4f 37 74 b7 db 72 45 57 09 25 |E.m[.gO7t..rEW.%| -00000020 4a 14 68 4d 78 6c c7 15 6a b1 57 e6 ff 53 c4 58 |J.hMxl..j.W..S.X| -00000030 41 c5 6b 08 3c 5a 8c b9 04 d0 27 62 ee a6 e3 36 |A.k.<Z....'b...6| -00000040 96 87 db 09 e3 88 d9 a2 0f 7d 9a |.........}.| +00000000 14 03 03 00 01 01 16 03 03 00 40 19 62 a8 82 26 |..........@.b..&| +00000010 0f 0c 84 b4 31 6a 5d 12 65 dc b9 bc de 5c cb 77 |....1j].e....\.w| +00000020 5d 04 7e a8 10 1a a5 05 e5 ca 04 68 a2 81 ef f5 |].~........h....| +00000030 ae 4e bd f1 f3 ba 3f 6a 81 ae 71 9a 2f 31 e2 79 |.N....?j..q./1.y| +00000040 f1 4d 6c 0e a4 be 4b f7 80 6f 97 |.Ml...K..o.| >>> Flow 5 (client to server) 00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -00000010 00 00 00 00 00 a6 c2 ef 07 bb 38 4a e4 8f 0c 12 |..........8J....| -00000020 19 1a 96 62 22 57 57 a2 b5 b3 06 70 95 28 a7 f7 |...b"WW....p.(..| -00000030 0d 42 69 37 7f 15 03 03 00 30 00 00 00 00 00 00 |.Bi7.....0......| -00000040 00 00 00 00 00 00 00 00 00 00 04 ed 3e 68 40 eb |............>h@.| -00000050 a0 7e 57 da 27 e7 f5 e8 6c e5 6d 58 c8 a5 18 47 |.~W.'...l.mX...G| -00000060 92 5a 43 90 de 07 9e 9a 3b cc |.ZC.....;.| +00000010 00 00 00 00 00 e9 f4 51 fe c1 02 35 de 6e 72 c3 |.......Q...5.nr.| +00000020 58 f3 01 4a f0 9d f2 34 df fc 0e 93 ef 46 2e 45 |X..J...4.....F.E| +00000030 5e 60 43 52 33 15 03 03 00 30 00 00 00 00 00 00 |^`CR3....0......| +00000040 00 00 00 00 00 00 00 00 00 00 ac 82 d6 47 42 40 |.............GB@| +00000050 d6 6c 6d e3 b6 c6 4a b7 83 ce 6f 3f 33 ad e7 eb |.lm...J...o?3...| +00000060 bf 59 82 50 8a 18 e3 13 46 6c |.Y.P....Fl| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA index f5fae45..7ae186d 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 be ba ac 2a 81 |....Y...U.....*.| -00000010 33 b1 6e 4d 8b 9b 29 f9 16 86 bc cd b2 03 50 72 |3.nM..).......Pr| -00000020 91 9a 93 f9 e1 d6 27 55 8b b8 6c 20 84 c2 21 9e |......'U..l ..!.| -00000030 60 aa b3 f0 ec 2f 66 0d 59 31 02 08 9e 68 68 c0 |`..../f.Y1...hh.| -00000040 58 9a 8e 6c 25 ce 4d e3 3f 9d dc 91 c0 2f 00 00 |X..l%.M.?..../..| +00000000 16 03 03 00 59 02 00 00 55 03 03 2a 52 95 57 8c |....Y...U..*R.W.| +00000010 55 3f d7 82 f0 3f af 57 a1 82 86 00 3a 6b c0 07 |U?...?.W....:k..| +00000020 4d c3 0e 80 cc 37 2d 51 f4 d3 e2 20 4a f6 c9 8a |M....7-Q... J...| +00000030 d2 98 4a ff 22 66 11 da 6f 9a a0 17 b9 96 b0 86 |..J."f..o.......| +00000040 29 e0 39 86 0a 00 42 78 30 60 61 99 c0 2f 00 00 |).9...Bx0`a../..| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,17 +60,17 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| -000002c0 ac 0c 00 00 a8 03 00 1d 20 82 89 54 65 64 97 8d |........ ..Ted..| -000002d0 e8 63 a2 5b 4f 16 56 7c cf 8b 0a 75 46 52 7e b6 |.c.[O.V|...uFR~.| -000002e0 99 2a e9 52 1f 11 46 85 36 08 04 00 80 cd a5 84 |.*.R..F.6.......| -000002f0 ff 9a 79 b5 04 85 88 fb 1e 1c d6 6b 78 e8 4d a5 |..y........kx.M.| -00000300 10 38 25 8e 8d de 71 51 b5 fd a6 2a f8 8b 5c 6d |.8%...qQ...*..\m| -00000310 1e 88 f7 d8 12 24 ff f7 7e dd 05 1c bf 71 7d 4f |.....$..~....q}O| -00000320 26 2f 2e 27 d8 e1 a8 8b d2 42 2b a6 d9 4e e6 60 |&/.'.....B+..N.`| -00000330 48 57 38 5d 3b f3 94 74 2c 8f ba e0 84 54 1c c0 |HW8];..t,....T..| -00000340 10 51 a0 31 1a d0 ec 72 01 f1 d3 65 73 c7 40 25 |.Q.1...r...es.@%| -00000350 af cd 10 18 29 2c 1a 52 e0 c9 a6 de 85 8c 96 e6 |....),.R........| -00000360 7d 85 0a 64 86 59 39 25 8f 8c 36 4c 37 16 03 03 |}..d.Y9%..6L7...| +000002c0 ac 0c 00 00 a8 03 00 1d 20 fa 3a 8f b7 50 10 38 |........ .:..P.8| +000002d0 04 9d fb c4 e4 76 6d 93 86 b2 8a d7 5b 8f 8d 45 |.....vm.....[..E| +000002e0 41 b7 ba 54 bc cc 7b 07 3c 08 04 00 80 a1 14 65 |A..T..{.<......e| +000002f0 f6 48 29 ba 08 86 52 65 dd 08 ef b8 b8 77 ef fd |.H)...Re.....w..| +00000300 8a ca dc 37 f8 69 fa 04 69 73 84 07 b2 45 f0 a2 |...7.i..is...E..| +00000310 8c 69 f7 7c 4c 5c 95 c5 66 80 ad 93 04 67 4b 3d |.i.|L\..f....gK=| +00000320 f8 53 a9 33 b3 c0 40 17 62 34 f0 f3 1e d2 23 93 |.S.3..@.b4....#.| +00000330 29 52 bc f4 f0 72 58 b9 76 9c 7b 54 b0 d5 d1 ab |)R...rX.v.{T....| +00000340 b3 1b ae f7 f3 46 6a 07 7f f4 91 ee 46 d6 85 43 |.....Fj.....F..C| +00000350 ea c6 f9 f5 47 89 85 39 72 35 af b4 03 e9 a2 ea |....G..9r5......| +00000360 a8 19 09 ea b3 d2 c2 38 59 65 d1 2c 18 16 03 03 |.......8Ye.,....| 00000370 00 3a 0d 00 00 36 03 01 02 40 00 2e 04 03 05 03 |.:...6...@......| 00000380 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| 00000390 08 06 04 01 05 01 06 01 03 03 02 03 03 01 02 01 |................| @@ -112,28 +112,28 @@ 00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| 00000210 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd 62 |...%...! /.}.G.b| 00000220 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| -00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 92 0f 00 |...._X.;t.......| -00000240 00 8e 04 03 00 8a 30 81 87 02 41 72 16 75 7d 08 |......0...Ar.u}.| -00000250 42 7b 33 e7 59 51 ef 3c 54 e7 81 e4 10 31 ab 5d |B{3.YQ.<T....1.]| -00000260 df 17 52 e0 a9 9f b5 43 e0 33 0e 52 b2 19 a2 a8 |..R....C.3.R....| -00000270 0b b9 8b e3 0b 51 1d 65 c9 7b 7c 67 66 d4 98 77 |.....Q.e.{|gf..w| -00000280 34 06 07 fc 8f 84 85 36 c3 fd f9 12 02 42 01 ad |4......6.....B..| -00000290 a7 25 ed c2 e8 2d c0 a3 12 0b 79 b2 32 e2 c3 70 |.%...-....y.2..p| -000002a0 2b 5d 99 1b 24 45 60 68 8b b3 28 5c 96 1a 26 89 |+]..$E`h..(\..&.| -000002b0 24 53 20 f5 fc 6f 98 b1 64 0b ba f5 ad ea 1e 33 |$S ..o..d......3| -000002c0 4f 64 fd 43 37 80 24 f0 7d e3 7d 63 76 7e 60 e3 |Od.C7.$.}.}cv~`.| -000002d0 14 03 03 00 01 01 16 03 03 00 28 00 00 00 00 00 |..........(.....| -000002e0 00 00 00 27 0b ff 3a 92 88 b6 86 86 0e c2 f5 94 |...'..:.........| -000002f0 d5 29 a4 6d 95 12 e1 d8 ec d9 a4 3c 1c db 52 76 |.).m.......<..Rv| -00000300 2a 72 29 |*r)| +00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 91 0f 00 |...._X.;t.......| +00000240 00 8d 04 03 00 89 30 81 86 02 41 63 34 72 b4 70 |......0...Ac4r.p| +00000250 45 46 9c 3c 06 2c f5 ab d4 dd a7 91 69 9c 65 0f |EF.<.,......i.e.| +00000260 4b d9 2d 90 3d d1 f2 4d 2a 6a 43 4f a7 fd b5 22 |K.-.=..M*jCO..."| +00000270 83 61 e2 14 33 8c bc 8a 81 52 a1 f4 69 a7 12 c9 |.a..3....R..i...| +00000280 c3 28 69 85 6d c1 b0 5d d3 5e ac 4e 02 41 35 cd |.(i.m..].^.N.A5.| +00000290 3b c3 f6 ea 9e df 2a a1 ea 80 55 40 d2 13 d3 ff |;.....*...U@....| +000002a0 b2 59 bb a0 c7 10 67 6e 9b dc 6c 3c 97 08 07 e0 |.Y....gn..l<....| +000002b0 db da 79 6b 0e 6c a0 23 13 b1 02 32 ab ee 62 69 |..yk.l.#...2..bi| +000002c0 f9 d5 7f 24 2e 26 94 36 a4 36 53 63 dd 90 20 14 |...$.&.6.6Sc.. .| +000002d0 03 03 00 01 01 16 03 03 00 28 00 00 00 00 00 00 |.........(......| +000002e0 00 00 a7 30 0e b0 f7 ba 51 35 c9 4c c2 24 90 5e |...0....Q5.L.$.^| +000002f0 b2 59 57 5d 96 9d ad d1 1e 7d b0 35 09 9c c5 49 |.YW].....}.5...I| +00000300 bd 82 |..| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 b8 e9 dd 30 75 |..........(...0u| -00000010 40 7d 71 76 db 9a 95 92 81 02 3a 9e 36 d5 15 ca |@}qv......:.6...| -00000020 5d 63 a1 0f 8c 53 c9 1c 37 56 b2 0d 54 15 a2 dc |]c...S..7V..T...| -00000030 03 d6 2e |...| +00000000 14 03 03 00 01 01 16 03 03 00 28 09 ff 53 e8 0f |..........(..S..| +00000010 ad 86 30 ca 96 54 da 72 45 13 7a cd 51 f6 b3 a5 |..0..T.rE.z.Q...| +00000020 27 4c 7c 26 81 6d 76 6f 19 8e f3 13 77 49 59 73 |'L|&.mvo....wIYs| +00000030 4e 98 3e |N.>| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 01 85 96 |................| -00000010 67 b2 4b d3 e3 27 80 9f 2d a8 f4 bf 47 91 58 6e |g.K..'..-...G.Xn| -00000020 47 d8 98 15 03 03 00 1a 00 00 00 00 00 00 00 02 |G...............| -00000030 36 54 82 d1 a2 0f 2a c3 53 f6 09 d0 5c 78 46 97 |6T....*.S...\xF.| -00000040 20 41 | A| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 99 7b 4c |..............{L| +00000010 1d 0a b1 89 0d ac fa a7 39 eb 9a ff 8f 06 60 d1 |........9.....`.| +00000020 88 e8 ef 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................| +00000030 99 42 7f c8 35 79 f3 a0 10 5c 05 25 c1 ac ab aa |.B..5y...\.%....| +00000040 d5 9e |..| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-Ed25519 b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-Ed25519 index e415b12..9ecd8e3 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-Ed25519 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-Ed25519 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 1c 50 4e 50 35 |....Y...U...PNP5| -00000010 51 02 a9 62 ba 82 a5 d3 fa 40 4e f3 28 9b 50 a6 |Q..b.....@N.(.P.| -00000020 f0 75 30 e9 fe be a3 42 1d 1c f5 20 9e 88 46 57 |.u0....B... ..FW| -00000030 c5 b4 a3 a3 fc 88 bb e0 1c 5e ea 77 a0 75 93 5a |.........^.w.u.Z| -00000040 6d 4c c7 57 6f 3a 05 af 3f 3f ac 75 cc a8 00 00 |mL.Wo:..??.u....| +00000000 16 03 03 00 59 02 00 00 55 03 03 5c 37 b1 d2 6c |....Y...U..\7..l| +00000010 bc dd 26 8c 4e f7 04 80 09 3c fd 76 23 d4 52 16 |..&.N....<.v#.R.| +00000020 df 0e 79 ab f4 cf 8c f3 61 31 c6 20 7d 7a 1d 8f |..y.....a1. }z..| +00000030 09 3e 2b 25 04 7f 0f 0a a7 0c 03 fd 9c 09 f3 5d |.>+%...........]| +00000040 96 75 f8 da 5b 6b 1b fb ca d7 ec 7a cc a8 00 00 |.u..[k.....z....| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,17 +60,17 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| -000002c0 ac 0c 00 00 a8 03 00 1d 20 82 c1 f5 7b 68 eb 7a |........ ...{h.z| -000002d0 cf 02 c9 95 28 4b 31 76 a9 84 93 a9 1f 5b f4 2a |....(K1v.....[.*| -000002e0 5c a5 31 94 5f f0 e0 ed 2e 08 04 00 80 7a 99 38 |\.1._........z.8| -000002f0 7f d0 25 4b bf a9 e0 2b db ce 17 9d 30 4b 82 9e |..%K...+....0K..| -00000300 b1 50 84 fc dd b0 a8 5c 39 20 00 40 5b 92 dc 7c |.P.....\9 .@[..|| -00000310 25 3b 53 7d 5a 4b ad 05 6f 3a 4f e5 84 b6 3a e2 |%;S}ZK..o:O...:.| -00000320 fb bf cb c8 94 39 a5 28 ad c8 5f 94 53 90 0e 61 |.....9.(.._.S..a| -00000330 af f2 92 2c 3b ec 3c bf 1d d3 8b a5 65 58 5b bf |...,;.<.....eX[.| -00000340 5a 21 3d cd 40 7c 9e 1d e9 62 3c 67 71 7c ec b4 |Z!=.@|...b<gq|..| -00000350 25 d0 4a 6a 85 1d c4 e8 44 d6 25 1a 2c 29 ae d7 |%.Jj....D.%.,)..| -00000360 d7 24 fb 5a 62 f7 50 52 12 1b c7 3e b0 16 03 03 |.$.Zb.PR...>....| +000002c0 ac 0c 00 00 a8 03 00 1d 20 aa c7 43 e7 1e 3b 2b |........ ..C..;+| +000002d0 28 c2 68 aa 83 cc 85 63 68 c4 b8 4d fb 18 fa b9 |(.h....ch..M....| +000002e0 3e 9a f2 7c 04 33 7f 48 6b 08 04 00 80 28 28 c7 |>..|.3.Hk....((.| +000002f0 84 79 65 11 07 43 7a ce f1 d6 cb 0e fe 6a 24 2c |.ye..Cz......j$,| +00000300 f3 f0 e5 9c 80 a6 c7 41 c7 51 f2 84 be 6e 58 df |.......A.Q...nX.| +00000310 f2 d2 d4 d9 62 08 c8 35 75 b9 8e 49 c2 98 b0 9d |....b..5u..I....| +00000320 32 aa db bf 03 c1 61 83 f7 20 d7 ec 07 27 5e 45 |2.....a.. ...'^E| +00000330 dc d6 92 4c a1 4f 4e 7c 53 c5 ca 42 48 40 0f 83 |...L.ON|S..BH@..| +00000340 fc 9d 60 a1 7c 43 d1 f5 f8 3f fe 50 3f d0 03 bc |..`.|C...?.P?...| +00000350 3e 8b ac 69 8f ae b6 9a c8 d4 98 84 30 f1 79 9b |>..i........0.y.| +00000360 af 5d 4e 41 2a 7c 46 22 df 46 42 74 f6 16 03 03 |.]NA*|F".FBt....| 00000370 00 3a 0d 00 00 36 03 01 02 40 00 2e 04 03 05 03 |.:...6...@......| 00000380 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| 00000390 08 06 04 01 05 01 06 01 03 03 02 03 03 01 02 01 |................| @@ -100,20 +100,20 @@ 00000140 08 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 |.....%...! /.}.G| 00000150 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af |.bC.(.._.).0....| 00000160 c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 48 |......_X.;t....H| -00000170 0f 00 00 44 08 07 00 40 af a6 03 14 53 7a 4f 75 |...D...@....SzOu| -00000180 9d cc 2f e3 e7 2a 51 16 16 b0 1d 28 e0 2a 59 f0 |../..*Q....(.*Y.| -00000190 3c df cc 18 dd b8 ef d1 9f 9d 03 8e 59 00 27 d1 |<...........Y.'.| -000001a0 39 2f 3b 33 53 1f b2 f0 22 1d 06 f6 50 0b a7 98 |9/;3S..."...P...| -000001b0 cc fa 78 53 bf 8e ff 0b 14 03 03 00 01 01 16 03 |..xS............| -000001c0 03 00 20 e5 81 3e a3 34 29 52 14 19 49 cf 04 82 |.. ..>.4)R..I...| -000001d0 8b e7 83 aa 6c db 96 ec 97 29 b4 a3 db 87 21 2e |....l....)....!.| -000001e0 a5 c0 66 |..f| +00000170 0f 00 00 44 08 07 00 40 07 e0 a5 14 ca cf 31 d7 |...D...@......1.| +00000180 99 96 c7 c7 d8 d8 a7 f7 82 e7 c6 c0 12 5d 91 5a |.............].Z| +00000190 bc eb 4a c0 59 c6 5b 7b 03 df 2a ff 48 ca 55 d8 |..J.Y.[{..*.H.U.| +000001a0 3e 10 c1 94 2c 03 b2 e7 16 83 4d e5 5a 3d 8a 48 |>...,.....M.Z=.H| +000001b0 2f e5 c4 59 de 6f 47 05 14 03 03 00 01 01 16 03 |/..Y.oG.........| +000001c0 03 00 20 ae 35 81 df 88 0e a3 2e 67 3f 33 02 3d |.. .5......g?3.=| +000001d0 b8 7e 47 db cb be 05 c7 ba 43 dc 5b 52 3b 4b ca |.~G......C.[R;K.| +000001e0 c0 dc 78 |..x| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 84 67 d4 ce cf |.......... .g...| -00000010 fb 54 2c dc f7 53 31 8a aa 03 60 37 3d 33 f2 79 |.T,..S1...`7=3.y| -00000020 d0 65 2e 3f 0e f9 1a d3 6e 6d 8e |.e.?....nm.| +00000000 14 03 03 00 01 01 16 03 03 00 20 63 23 49 7c 83 |.......... c#I|.| +00000010 1a 8b cd 48 02 e7 86 4d ab 8b 3c 4f 40 27 a6 48 |...H...M..<O@'.H| +00000020 95 d5 80 8a 7a e0 56 0b e6 34 70 |....z.V..4p| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 e5 b7 4c 92 05 fc 81 cf 11 ef cd |.......L........| -00000010 0f 4b df ef a1 54 ae 26 4e ec aa 15 03 03 00 12 |.K...T.&N.......| -00000020 0a f3 5b 06 63 84 a6 eb d4 73 94 db fe d8 e0 ae |..[.c....s......| -00000030 d6 fc |..| +00000000 17 03 03 00 16 aa b4 5b 75 04 96 c5 4a e3 2a fb |.......[u...J.*.| +00000010 be 29 32 9e c5 e4 15 bd 38 df 69 15 03 03 00 12 |.)2.....8.i.....| +00000020 50 4d b6 c0 95 e6 5a db f2 b7 ea 02 cb 3e 01 ea |PM....Z......>..| +00000030 35 0d |5.| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 index 3975b07..35ec347 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 d4 20 b3 4c 6a |....Y...U... .Lj| -00000010 69 44 3f f7 ab 15 35 85 ca 71 02 b0 70 18 8e d6 |iD?...5..q..p...| -00000020 61 d5 34 08 42 de cf a1 57 32 96 20 8c b4 72 dd |a.4.B...W2. ..r.| -00000030 63 93 e6 13 9d 4a ec 75 d9 a1 a6 9e 5e 02 f5 63 |c....J.u....^..c| -00000040 29 1a 78 9f 94 9f 6c 58 b5 91 ae 63 c0 30 00 00 |).x...lX...c.0..| +00000000 16 03 03 00 59 02 00 00 55 03 03 16 f7 21 0a 97 |....Y...U....!..| +00000010 89 11 ec c3 c4 05 41 79 72 60 40 6d ec 78 90 26 |......Ayr`@m.x.&| +00000020 0c a4 f8 5d d5 27 e9 70 bb 40 21 20 b0 bb 98 5d |...].'.p.@! ...]| +00000030 a2 27 08 1e 4a fe f9 e1 cf a5 79 d3 eb c6 40 f7 |.'..J.....y...@.| +00000040 ee 4f 0b fa a1 bb 09 62 07 24 30 b7 c0 30 00 00 |.O.....b.$0..0..| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,17 +60,17 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| -000002c0 ac 0c 00 00 a8 03 00 1d 20 a2 bd 95 3e 0c 9f ad |........ ...>...| -000002d0 11 59 e0 6a c1 21 0c 6c 86 cc f1 ce bd a0 30 5d |.Y.j.!.l......0]| -000002e0 53 1e 75 f9 55 af 49 7b 31 08 04 00 80 d4 8b 11 |S.u.U.I{1.......| -000002f0 ca 22 14 79 a3 e8 b6 c7 d0 d6 1b 17 42 93 47 30 |.".y........B.G0| -00000300 ab 50 0e c9 0c 92 88 96 b4 63 4e 4e ac 7f dd c8 |.P.......cNN....| -00000310 8f 85 07 5b 95 c5 0a c0 4e 6d 4f 51 ba d8 d7 db |...[....NmOQ....| -00000320 14 70 80 4f 68 d9 b4 39 e7 48 27 21 76 4c 79 a4 |.p.Oh..9.H'!vLy.| -00000330 60 91 d7 2f 75 69 04 1a da 71 ff b8 4d 78 d8 e7 |`../ui...q..Mx..| -00000340 ca f2 f2 1e 71 21 b3 a0 44 a7 6c 99 16 a1 c9 f8 |....q!..D.l.....| -00000350 f0 de e8 99 12 7b 3d a2 e3 15 fa 63 62 e9 1b 72 |.....{=....cb..r| -00000360 c8 bb 27 38 4a 48 66 1d dd fb ef 6f d1 16 03 03 |..'8JHf....o....| +000002c0 ac 0c 00 00 a8 03 00 1d 20 39 1f 7e 66 c8 20 24 |........ 9.~f. $| +000002d0 cf 8e 51 f6 bf 2a 01 a9 3b 51 19 f1 9d 32 b6 fa |..Q..*..;Q...2..| +000002e0 05 3b 90 c9 a3 8b 49 92 2a 08 04 00 80 da 65 ad |.;....I.*.....e.| +000002f0 fa f9 d5 f6 d7 13 34 d2 ab ac ea 57 37 69 c6 b1 |......4....W7i..| +00000300 91 ee 89 b7 04 6b 17 fb 80 23 df df ef a1 62 9b |.....k...#....b.| +00000310 e4 0a 4e ca b0 35 b2 d3 2a cf 4f c1 e3 d9 37 78 |..N..5..*.O...7x| +00000320 aa c8 59 f8 25 c7 43 51 19 6c c7 50 90 a4 2c 92 |..Y.%.CQ.l.P..,.| +00000330 01 0e 8d ff f0 88 4b af 1d 03 ee 51 8b 18 e4 ee |......K....Q....| +00000340 35 48 16 e7 4c 26 1d d8 af 91 b1 75 38 b5 65 42 |5H..L&.....u8.eB| +00000350 8e 60 c7 f9 25 a7 85 35 72 41 6f f6 c4 61 1d c0 |.`..%..5rAo..a..| +00000360 c8 cf da ae 31 5e 2e d6 9c ca f1 d6 31 16 03 03 |....1^......1...| 00000370 00 3a 0d 00 00 36 03 01 02 40 00 2e 04 03 05 03 |.:...6...@......| 00000380 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| 00000390 08 06 04 01 05 01 06 01 03 03 02 03 03 01 02 01 |................| @@ -112,26 +112,26 @@ 00000200 e5 35 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| 00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| 00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 |......._X.;t....| -00000230 88 0f 00 00 84 08 04 00 80 2e bf 05 22 82 a7 d6 |............"...| -00000240 e9 08 ff 9b 10 d3 4a 6c c4 73 5c 78 88 05 0c 15 |......Jl.s\x....| -00000250 b7 8c 78 49 64 2d 58 67 ef 8f db c0 67 fa 32 6e |..xId-Xg....g.2n| -00000260 65 45 90 a0 69 5c fb ba e0 16 1c d4 81 1d 24 89 |eE..i\........$.| -00000270 35 27 14 15 19 0b 86 ee 6a f2 b4 a5 27 61 5f 1f |5'......j...'a_.| -00000280 cc 47 7c 01 ed a9 ff ed 61 45 3f 53 1c 82 c8 cd |.G|.....aE?S....| -00000290 48 e4 89 82 12 d7 d2 ff fa 32 b3 e6 9d ce 75 75 |H........2....uu| -000002a0 d1 cd b2 a8 56 a6 a6 63 da 8d ed 27 13 01 9a 56 |....V..c...'...V| -000002b0 a2 26 b4 6c af 27 f6 4f 1b 14 03 03 00 01 01 16 |.&.l.'.O........| -000002c0 03 03 00 28 00 00 00 00 00 00 00 00 f0 e8 32 33 |...(..........23| -000002d0 50 df 73 17 3c 58 f2 c9 30 2e 5d e9 00 4f 4b 33 |P.s.<X..0.]..OK3| -000002e0 22 12 f7 f0 62 d0 62 3e ed 36 b8 58 |"...b.b>.6.X| +00000230 88 0f 00 00 84 08 04 00 80 56 1c 58 51 d8 51 bc |.........V.XQ.Q.| +00000240 8e 4b b8 24 64 85 81 d2 26 9b 38 bf 13 19 e7 0a |.K.$d...&.8.....| +00000250 f7 94 e8 b5 94 bf 6f ae f2 07 1a 46 24 38 7b 8b |......o....F$8{.| +00000260 2f a6 da 91 1a 5f 7d 3f cf c4 1b 14 9c 44 8e 6a |/...._}?.....D.j| +00000270 6b c8 c4 60 c6 15 e6 f2 c0 45 e7 46 c4 32 06 b1 |k..`.....E.F.2..| +00000280 46 5e 25 1d ba f7 d8 81 b0 6b 50 40 81 b1 93 89 |F^%......kP@....| +00000290 cb 90 ae 10 b1 db 08 99 e6 0e 8f 17 0f 4d a7 a7 |.............M..| +000002a0 f5 42 8a be ca d6 75 c4 32 44 22 ab df cf 22 f7 |.B....u.2D"...".| +000002b0 58 d9 9f 52 c2 04 c0 81 59 14 03 03 00 01 01 16 |X..R....Y.......| +000002c0 03 03 00 28 00 00 00 00 00 00 00 00 eb 5a 97 41 |...(.........Z.A| +000002d0 1d da 2b 81 da 7a b7 9a f8 5e fe 50 75 e5 a4 6a |..+..z...^.Pu..j| +000002e0 21 90 b7 3d 4e bc 44 cf 86 8f cd c3 |!..=N.D.....| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 14 ce b1 86 0e |..........(.....| -00000010 9f ce 73 25 44 b7 3e a9 25 db a8 93 d9 39 33 75 |..s%D.>.%....93u| -00000020 2f a9 7f 97 6a 76 28 fe e2 84 5f 1e 84 66 b4 c8 |/...jv(..._..f..| -00000030 45 e7 64 |E.d| +00000000 14 03 03 00 01 01 16 03 03 00 28 93 a5 d4 a8 16 |..........(.....| +00000010 4e a2 b2 c3 b9 ce dd 0e 57 49 7c eb 92 e4 e7 e3 |N.......WI|.....| +00000020 a8 55 3a 56 54 53 92 b8 ce 15 e3 c3 c2 da 52 01 |.U:VTS........R.| +00000030 6f 35 fd |o5.| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 3b 17 73 |.............;.s| -00000010 78 d6 3a b4 6d 3a 61 52 f6 a5 8c dd 18 3e ff 04 |x.:.m:aR.....>..| -00000020 d9 3f 22 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.?".............| -00000030 32 8d 5d 07 14 a9 d2 1c dd 1e 2f 3d 89 a9 8f 1d |2.]......./=....| -00000040 08 0f |..| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 5b 20 4f |.............[ O| +00000010 e9 3f 09 28 6e 88 5d 1d 57 90 2c 35 74 37 d1 df |.?.(n.].W.,5t7..| +00000020 aa 39 9b 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.9..............| +00000030 bb e3 77 62 e5 c9 78 f4 a5 09 93 b0 20 9a 1b a4 |..wb..x..... ...| +00000040 48 44 |HD| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA index 2d608a7..110f689 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 3c ba b1 d8 8d |....Y...U..<....| -00000010 f5 52 f4 a4 70 fc 12 54 20 85 eb 23 bc b8 0b e0 |.R..p..T ..#....| -00000020 80 b6 ab 9b c5 34 84 57 bc ae 95 20 e3 51 8d 40 |.....4.W... .Q.@| -00000030 93 cc 9f e4 fd 77 82 c8 12 54 6a 23 08 db ff e5 |.....w...Tj#....| -00000040 87 8d 72 41 60 51 6a 11 5f 0a 9a d2 c0 09 00 00 |..rA`Qj._.......| +00000000 16 03 03 00 59 02 00 00 55 03 03 68 dc 2e 5e 8e |....Y...U..h..^.| +00000010 80 38 0e 65 a3 b0 f6 a0 c0 8f 1e 62 ef 1d 5a 54 |.8.e.......b..ZT| +00000020 82 dc 9c 68 77 88 57 dd f3 9d c2 20 4e 56 dd 44 |...hw.W.... NV.D| +00000030 a0 46 67 4c 09 2b d5 e6 fe 15 fb b3 8e 19 ef a3 |.FgL.+..........| +00000040 8e 5c a9 70 00 cf 96 d7 3b 8b c9 64 c0 09 00 00 |.\.p....;..d....| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| 00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| @@ -55,23 +55,23 @@ 00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| 00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| 00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| -00000270 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 86 f3 |*............ ..| -00000280 1e c5 fb 1f 91 44 0e e5 e4 3e 0a cd 75 a2 fb 4c |.....D...>..u..L| -00000290 a2 b9 07 f7 33 ce cc cd 61 a5 8c ba 6a 35 04 03 |....3...a...j5..| -000002a0 00 8b 30 81 88 02 42 01 f4 8d 4f 3e c8 73 b5 b4 |..0...B...O>.s..| -000002b0 b5 2b ac 2a 27 68 56 a1 45 ce b6 1d c6 37 ce de |.+.*'hV.E....7..| -000002c0 bd 96 90 5e e2 1c c8 84 b2 84 57 25 81 d4 c3 7a |...^......W%...z| -000002d0 db b2 3d 24 2b 17 3a 4a 7e 92 1a bb 0c fb b6 05 |..=$+.:J~.......| -000002e0 cd 0e 85 4c 3d 4b 24 2a 2a 02 42 00 f6 91 d6 82 |...L=K$**.B.....| -000002f0 9e 81 98 5f 64 59 ce 16 85 fc 65 19 0c 50 ca ea |..._dY....e..P..| -00000300 8a ba 1e 61 a8 71 cf 2c eb 94 24 ac 34 75 6e 5c |...a.q.,..$.4un\| -00000310 dc 92 ba b8 bd 42 75 ef 6d 67 5f 06 5c e3 6c c2 |.....Bu.mg_.\.l.| -00000320 aa 5e 29 25 66 00 68 c8 5d 9c 6f bb e0 16 03 03 |.^)%f.h.].o.....| -00000330 00 3a 0d 00 00 36 03 01 02 40 00 2e 04 03 05 03 |.:...6...@......| -00000340 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| -00000350 08 06 04 01 05 01 06 01 03 03 02 03 03 01 02 01 |................| -00000360 03 02 02 02 04 02 05 02 06 02 00 00 16 03 03 00 |................| -00000370 04 0e 00 00 00 |.....| +00000270 2a 16 03 03 00 b6 0c 00 00 b2 03 00 1d 20 24 d0 |*............ $.| +00000280 e5 11 4c 95 2c 96 58 62 01 df 20 c8 24 ce 29 a2 |..L.,.Xb.. .$.).| +00000290 1a 3e 97 e2 df 29 49 e6 3a e8 c2 d3 72 49 04 03 |.>...)I.:...rI..| +000002a0 00 8a 30 81 87 02 41 71 15 8d 50 f6 69 40 d7 cd |..0...Aq..P.i@..| +000002b0 da c9 c3 ee 37 c2 5f c3 89 62 23 e0 ef 37 f9 9e |....7._..b#..7..| +000002c0 2a 26 85 10 56 28 08 de 49 3b fa 03 f3 14 4b 3a |*&..V(..I;....K:| +000002d0 b2 3d de 84 d2 08 8d 4e 59 3e 80 8f 6a 44 af 6f |.=.....NY>..jD.o| +000002e0 be ee 08 ae 35 40 42 bc 02 42 00 f3 e9 89 a5 7f |....5@B..B......| +000002f0 9c 50 7c 07 34 e4 cf f0 2b 0f cf f7 68 57 fa fd |.P|.4...+...hW..| +00000300 2f 52 04 f8 90 7b 97 eb c3 e0 cc 68 f7 bf 22 21 |/R...{.....h.."!| +00000310 62 b3 51 c8 a4 30 38 c5 88 46 df 55 21 21 d0 4f |b.Q..08..F.U!!.O| +00000320 6f 95 7b 5f 5a c6 98 dd 2d d1 0a 95 16 03 03 00 |o.{_Z...-.......| +00000330 3a 0d 00 00 36 03 01 02 40 00 2e 04 03 05 03 06 |:...6...@.......| +00000340 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 08 |................| +00000350 06 04 01 05 01 06 01 03 03 02 03 03 01 02 01 03 |................| +00000360 02 02 02 04 02 05 02 06 02 00 00 16 03 03 00 04 |................| +00000370 0e 00 00 00 |....| >>> Flow 3 (client to server) 00000000 16 03 03 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0| 00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.| @@ -108,31 +108,31 @@ 00000200 e5 35 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| 00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| 00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 |......._X.;t....| -00000230 88 0f 00 00 84 08 04 00 80 53 85 ea dc a6 86 2d |.........S.....-| -00000240 e7 8c 0b 68 f9 57 7f f5 77 d8 fe 35 28 91 e7 2f |...h.W..w..5(../| -00000250 8a 2c 36 cf d7 8c 9f 3d f2 e2 99 41 11 b2 3c a2 |.,6....=...A..<.| -00000260 5e f3 68 1f b5 d4 f8 90 8a e2 5e 02 48 00 2b eb |^.h.......^.H.+.| -00000270 f0 e6 8c 28 af 11 80 82 ea 35 06 fd 0a 5f d7 1a |...(.....5..._..| -00000280 e9 63 29 08 8c aa 18 1e 7c 08 81 21 c8 aa 86 b1 |.c).....|..!....| -00000290 cf 94 db f6 8d 15 dc cc ae cf 41 2c 32 b1 3f 0c |..........A,2.?.| -000002a0 96 0e 5c ed 82 74 cc fc 35 f4 38 80 29 00 c1 3a |..\..t..5.8.)..:| -000002b0 70 d4 07 07 9c 49 9e 7b 91 14 03 03 00 01 01 16 |p....I.{........| +00000230 88 0f 00 00 84 08 04 00 80 84 38 78 4d dd 9f 84 |..........8xM...| +00000240 ae cb b8 2f e9 f3 76 66 41 56 f6 ed a5 fb 8b f2 |.../..vfAV......| +00000250 43 0f 27 56 9e 7d a8 06 3e 8f ad b0 17 d5 d6 52 |C.'V.}..>......R| +00000260 f4 88 e5 af 55 5b 55 fc 26 c1 a9 d5 a9 34 2b 50 |....U[U.&....4+P| +00000270 96 09 db 59 cc f4 e8 cf 84 6f 9d b1 fd 3b a4 66 |...Y.....o...;.f| +00000280 66 43 74 6d 4f e5 52 2c 22 2d c9 4c 67 3d ff 3d |fCtmO.R,"-.Lg=.=| +00000290 c2 79 b3 b1 85 56 08 cc 02 7c 53 a7 be 39 04 21 |.y...V...|S..9.!| +000002a0 fb db fe ff 1b a6 c7 7a e9 4c 11 c3 34 a6 7c 4f |.......z.L..4.|O| +000002b0 23 61 d9 47 b0 6c ae cb 72 14 03 03 00 01 01 16 |#a.G.l..r.......| 000002c0 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 00 |...@............| -000002d0 00 00 00 00 f3 da dc d7 12 d6 f6 19 75 a8 02 68 |............u..h| -000002e0 57 0e e1 90 75 d1 fc b8 32 a3 34 16 d6 8d 2a f5 |W...u...2.4...*.| -000002f0 65 f2 a7 67 2c 2c a4 73 6a b6 f2 ad 2d 7f 8a ce |e..g,,.sj...-...| -00000300 a7 12 16 97 |....| +000002d0 00 00 00 00 d3 95 4a 65 d9 8e 3d 9c 2b 18 67 aa |......Je..=.+.g.| +000002e0 e0 d7 a6 dd fb af 42 06 0d 56 cc 3d 12 3e 7e 95 |......B..V.=.>~.| +000002f0 18 6e 97 d6 cc 84 eb 90 a1 c3 b6 6e 3c 42 d1 2e |.n.........n<B..| +00000300 7a dc 41 81 |z.A.| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 40 dc 11 a1 a2 fb |..........@.....| -00000010 55 0c 9e e0 e2 55 1a ca cd 5b df 1f 39 9e 08 51 |U....U...[..9..Q| -00000020 bd 6b 72 40 93 f8 23 7a 32 9d 85 18 20 b7 39 b0 |.kr@..#z2... .9.| -00000030 03 d3 10 6a 8e 66 6d e6 d5 38 03 c6 e5 b8 dc d7 |...j.fm..8......| -00000040 3c 27 1d d2 a9 59 f9 18 7d 15 90 |<'...Y..}..| +00000000 14 03 03 00 01 01 16 03 03 00 40 71 ee 1d 4f 55 |..........@q..OU| +00000010 b4 47 3d 26 52 5a 00 a5 ce 0e 31 6c 2d 09 95 df |.G=&RZ....1l-...| +00000020 fb 74 30 89 32 3d 47 29 58 ee 61 70 74 18 8c 01 |.t0.2=G)X.apt...| +00000030 e3 16 d7 6e 3d a1 30 75 61 b8 99 e4 c5 82 82 d5 |...n=.0ua.......| +00000040 75 f6 e1 b4 f8 97 77 92 00 64 06 |u.....w..d.| >>> Flow 5 (client to server) 00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -00000010 00 00 00 00 00 c2 92 ee 96 31 60 90 d5 ee a6 1c |.........1`.....| -00000020 ed 3c 03 40 8c e7 0c db 7f b0 11 dc 7e 58 e1 aa |.<.@........~X..| -00000030 4c d7 68 2a 91 15 03 03 00 30 00 00 00 00 00 00 |L.h*.....0......| -00000040 00 00 00 00 00 00 00 00 00 00 b6 61 51 ac 66 a5 |...........aQ.f.| -00000050 d1 ef d3 ee c8 d3 48 72 d5 e0 ef 7d ca 6a ec b2 |......Hr...}.j..| -00000060 77 ff 2d a8 32 6d be 6e a7 42 |w.-.2m.n.B| +00000010 00 00 00 00 00 e2 68 77 75 6a f8 3c 3d 2c 96 52 |......hwuj.<=,.R| +00000020 2d fc d5 3b d3 17 c0 29 df 99 f1 09 23 13 9f 89 |-..;...)....#...| +00000030 dd 21 15 23 36 15 03 03 00 30 00 00 00 00 00 00 |.!.#6....0......| +00000040 00 00 00 00 00 00 00 00 00 00 37 4e ac 91 80 02 |..........7N....| +00000050 4f 4a 9f b4 3c 0e 24 87 c8 d0 41 24 ce 01 e2 bb |OJ..<.$...A$....| +00000060 18 af bc ce 09 4b 41 f6 db 08 |.....KA...| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA index cdc7104..cbc4bcc 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 f3 28 ca c9 ac |....Y...U...(...| -00000010 29 bb 15 80 56 d2 37 09 fa 7d 23 04 d4 79 e7 1d |)...V.7..}#..y..| -00000020 bb 4e c5 60 c8 44 39 02 6a e9 e0 20 b5 ae 39 87 |.N.`.D9.j.. ..9.| -00000030 4e 24 2f 33 02 fe 72 d6 2a 4d 0c 8c da 36 7b 28 |N$/3..r.*M...6{(| -00000040 3c 06 aa b2 60 68 91 7a ae d8 7b e2 c0 2f 00 00 |<...`h.z..{../..| +00000000 16 03 03 00 59 02 00 00 55 03 03 b6 96 f2 bc ed |....Y...U.......| +00000010 1b 14 73 de 12 10 cc e9 4d f2 c7 8b 46 d8 63 55 |..s.....M...F.cU| +00000020 8f 04 33 ec 89 b5 70 93 01 1c f2 20 72 82 e1 16 |..3...p.... r...| +00000030 9c 0e 70 25 84 2c 09 a6 4f 19 c0 ed 44 d6 98 13 |..p%.,..O...D...| +00000040 97 f6 19 08 d4 b6 d3 ad 82 96 ef db c0 2f 00 00 |............./..| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,17 +60,17 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| -000002c0 ac 0c 00 00 a8 03 00 1d 20 d4 df 5d 10 ee ba a6 |........ ..]....| -000002d0 51 d7 1b fb bf ed bc d6 b9 34 44 e7 af 23 0e 9b |Q........4D..#..| -000002e0 45 af ba 7a 89 63 03 a9 4c 08 04 00 80 30 2c 0f |E..z.c..L....0,.| -000002f0 2e d9 e4 1d c2 90 01 1c cc cf d4 fe 06 6d c3 aa |.............m..| -00000300 59 d9 d9 bc 16 2f 2c b1 be 90 a3 93 a7 be bc 4d |Y..../,........M| -00000310 d8 f4 ac 21 36 59 a8 21 94 ef d3 c4 53 14 34 18 |...!6Y.!....S.4.| -00000320 c9 10 d5 77 fd 1e ad 15 0f 23 d7 73 90 7a c0 7b |...w.....#.s.z.{| -00000330 b3 b2 e2 df 15 42 35 ce 38 05 52 02 77 b7 b2 2b |.....B5.8.R.w..+| -00000340 6b 88 6a ce d4 20 99 9d e4 fe e8 38 1e 01 b7 78 |k.j.. .....8...x| -00000350 3c ea ac 8e ef 2f 7e e8 22 08 78 42 b7 db 84 80 |<..../~.".xB....| -00000360 8c 61 8a c5 cc d7 1f 6a 8d 5c 1d 2d 0d 16 03 03 |.a.....j.\.-....| +000002c0 ac 0c 00 00 a8 03 00 1d 20 21 1b d1 91 16 9c c1 |........ !......| +000002d0 51 52 39 07 6b 6d ab 07 28 f7 d0 ae 02 13 5e 73 |QR9.km..(.....^s| +000002e0 5b 51 30 96 27 57 56 e5 37 08 04 00 80 6a 13 82 |[Q0.'WV.7....j..| +000002f0 97 81 ea 32 51 cb cb 8e 3b ee e5 dd 4f 80 20 50 |...2Q...;...O. P| +00000300 c9 f0 19 9b d5 1b ae 21 f7 e6 24 4e a3 22 ec b9 |.......!..$N."..| +00000310 25 6e 77 19 12 08 16 8a c7 c1 db 29 e9 be 05 55 |%nw........)...U| +00000320 09 c1 6e 44 c3 d7 bd 18 80 c8 1f 42 53 3b e6 09 |..nD.......BS;..| +00000330 00 29 20 c4 94 04 97 6f f7 e6 f4 3b 66 77 2f e5 |.) ....o...;fw/.| +00000340 de 96 6f c3 67 c5 ce 4b 5e 4b 0e 90 02 fc 32 7f |..o.g..K^K....2.| +00000350 71 f4 63 76 37 57 75 30 fb 1b f5 99 98 5f c3 b1 |q.cv7Wu0....._..| +00000360 fb e3 76 ad 8e 2f 7a 72 86 ed 34 18 98 16 03 03 |..v../zr..4.....| 00000370 00 3a 0d 00 00 36 03 01 02 40 00 2e 04 03 05 03 |.:...6...@......| 00000380 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 05 |................| 00000390 08 06 04 01 05 01 06 01 03 03 02 03 03 01 02 01 |................| @@ -112,26 +112,26 @@ 00000200 e5 35 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| 00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| 00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 |......._X.;t....| -00000230 88 0f 00 00 84 08 04 00 80 b8 96 b3 c8 66 a9 fb |.............f..| -00000240 da 1b 82 65 9d 57 e5 e5 e5 60 c9 43 df 6e 99 53 |...e.W...`.C.n.S| -00000250 45 95 b8 58 d1 19 05 50 e1 a7 3c e8 07 ad 57 09 |E..X...P..<...W.| -00000260 9c 95 13 ea 80 24 53 56 b1 13 2d 59 9d e9 60 0f |.....$SV..-Y..`.| -00000270 75 97 d3 4f 82 3a b5 41 3e 90 75 ea 28 97 00 e7 |u..O.:.A>.u.(...| -00000280 74 c9 04 1d d0 16 ba 40 75 9c ae a0 bd 00 b1 a9 |t......@u.......| -00000290 86 d5 1a f2 30 45 72 99 ea b2 eb 61 b1 63 72 c5 |....0Er....a.cr.| -000002a0 ad b1 60 a8 fa bd 95 95 17 03 4c 8e 87 4b 44 e5 |..`.......L..KD.| -000002b0 ec f3 e0 48 33 b8 a9 74 78 14 03 03 00 01 01 16 |...H3..tx.......| -000002c0 03 03 00 28 00 00 00 00 00 00 00 00 e6 a6 db ee |...(............| -000002d0 7d fb 48 9f 81 a6 78 6a db a1 9a bb c8 da 7b b2 |}.H...xj......{.| -000002e0 6a 01 66 fb 85 a7 2f 35 40 77 b6 b2 |j.f.../5@w..| +00000230 88 0f 00 00 84 08 04 00 80 90 53 1e fc 7c 63 b0 |..........S..|c.| +00000240 98 c5 19 40 fb 4f cf c3 53 51 81 68 54 c7 49 38 |...@.O..SQ.hT.I8| +00000250 0c 41 f0 12 7d a6 e4 8a 4e 77 97 49 5a 07 7d 30 |.A..}...Nw.IZ.}0| +00000260 fa df 77 2f 51 cf 37 65 07 0b 2c 91 15 43 1d c9 |..w/Q.7e..,..C..| +00000270 69 46 e2 26 66 72 98 ec 62 1a 22 ae e8 3e 3a 28 |iF.&fr..b."..>:(| +00000280 17 83 b9 74 57 59 a2 ec 31 95 17 1f c3 ec 9a 01 |...tWY..1.......| +00000290 f2 d4 07 d5 ee d5 0e f2 f4 75 3b d6 b8 df aa ad |.........u;.....| +000002a0 0b 87 37 30 43 7e c1 b1 e1 0d 7e 90 3d 87 9d 93 |..70C~....~.=...| +000002b0 d7 06 57 18 5c 12 c2 32 0d 14 03 03 00 01 01 16 |..W.\..2........| +000002c0 03 03 00 28 00 00 00 00 00 00 00 00 ff 2a ae f8 |...(.........*..| +000002d0 c9 1c bd 3f 62 0e 68 42 e7 96 ec ee c0 fa 71 34 |...?b.hB......q4| +000002e0 f1 e2 67 76 82 cf c3 2a fb b2 5a c1 |..gv...*..Z.| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 b3 9c 30 b6 a2 |..........(..0..| -00000010 cb cf 75 38 10 e7 80 39 0e 87 39 9c d9 da 2c 53 |..u8...9..9...,S| -00000020 1a 64 2d 33 ff 21 25 e9 3c f2 ec 6d a4 59 f4 30 |.d-3.!%.<..m.Y.0| -00000030 ea 41 24 |.A$| +00000000 14 03 03 00 01 01 16 03 03 00 28 da 70 e7 aa 1b |..........(.p...| +00000010 6c 66 cb 9b 07 d9 4e 87 6f 87 60 fb 46 f5 e9 33 |lf....N.o.`.F..3| +00000020 48 59 ff 3e b5 bf 0b 0c b2 39 79 64 f6 3c 2e 95 |HY.>.....9yd.<..| +00000030 04 51 87 |.Q.| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 65 72 8f |.............er.| -00000010 4a 5f 08 c1 f9 37 5d 30 bc c6 e6 5f a8 23 35 69 |J_...7]0..._.#5i| -00000020 d3 3c 7a 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.<z.............| -00000030 b0 48 2e 2e ed 4d 9c db 3a fc ff e6 57 83 fc 90 |.H...M..:...W...| -00000040 aa 78 |.x| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 21 29 d2 |.............!).| +00000010 27 05 2d b4 a2 bf ea f2 96 8a 61 c9 91 75 9f 0f |'.-.......a..u..| +00000020 50 4a 76 15 03 03 00 1a 00 00 00 00 00 00 00 02 |PJv.............| +00000030 a9 40 eb 86 b2 f0 85 a2 75 bc 4e 09 8c c9 ca 31 |.@......u.N....1| +00000040 e5 49 |.I| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPKCS1v15 b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPKCS1v15 index 26308fc..b8ecfff 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPKCS1v15 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPKCS1v15 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 97 f2 cb de f1 |....Y...U.......| -00000010 bb cf 9a 6c 6d 7e e2 94 af 9d 0b ed 02 cf fc b2 |...lm~..........| -00000020 80 b2 7b 41 2c a6 83 e7 52 62 93 20 63 23 7f 48 |..{A,...Rb. c#.H| -00000030 be c1 7f d3 75 34 fe 3a ad 27 f5 99 b0 73 91 df |....u4.:.'...s..| -00000040 b3 e9 82 95 cd 1b f9 08 b6 3d 4f 9b c0 2f 00 00 |.........=O../..| +00000000 16 03 03 00 59 02 00 00 55 03 03 ad e1 a7 5e 0b |....Y...U.....^.| +00000010 b8 bd 9d 05 c2 8e 6c f2 ea 7d a1 c8 32 cc d1 74 |......l..}..2..t| +00000020 ba 86 75 98 33 27 39 c3 0a 6f 49 20 2b 37 9a 0f |..u.3'9..oI +7..| +00000030 9b de 1f 1d 5f 2b 45 29 6c 9b 33 c6 bc c1 15 a4 |...._+E)l.3.....| +00000040 19 9b 70 6c 15 eb 4a 92 92 5f b7 6b c0 2f 00 00 |..pl..J.._.k./..| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,17 +60,17 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| -000002c0 ac 0c 00 00 a8 03 00 1d 20 f8 3a 6c 5b 6f 88 48 |........ .:l[o.H| -000002d0 19 c5 a2 e7 4a d9 6d 21 56 23 63 1b 1f 95 aa bc |....J.m!V#c.....| -000002e0 33 ac aa 3b bb f8 35 ba 1a 04 01 00 80 98 6d 7b |3..;..5.......m{| -000002f0 7d 40 13 81 6b 70 ec ac 60 ee 1d 3e 37 36 bc f4 |}@..kp..`..>76..| -00000300 c1 9f 3c 13 b7 06 3d 38 be 4f 8c 3e e2 2e f2 b5 |..<...=8.O.>....| -00000310 de 16 ec a0 5b 64 00 5c c3 50 cc 79 a2 f7 e0 8d |....[d.\.P.y....| -00000320 68 e6 6b 1b b8 57 a4 15 d0 2c d7 4a be 97 26 26 |h.k..W...,.J..&&| -00000330 8c 5c 4e 26 36 96 48 b5 0f 88 7b 37 43 e4 d1 24 |.\N&6.H...{7C..$| -00000340 01 3c 70 38 99 c6 e2 2f 66 e7 db 57 30 f2 72 d0 |.<p8.../f..W0.r.| -00000350 17 fd ad 09 a7 bd ee de ca fd 57 15 de 25 b6 1f |..........W..%..| -00000360 ed 45 86 22 83 4e 64 54 56 17 1f 81 4f 16 03 03 |.E.".NdTV...O...| +000002c0 ac 0c 00 00 a8 03 00 1d 20 ba ad fb 1e 28 95 96 |........ ....(..| +000002d0 f3 62 9d 97 87 0f fd fc a9 91 a2 4b 8d 69 ec 8f |.b.........K.i..| +000002e0 7d 49 08 6e fe 7d b3 5b 03 04 01 00 80 86 57 23 |}I.n.}.[......W#| +000002f0 58 bb 9a 50 d8 bb 99 d9 f5 cc 66 43 38 f0 14 8a |X..P......fC8...| +00000300 cb 6d 8b c0 83 52 f8 53 75 94 07 e3 12 2c 10 bb |.m...R.Su....,..| +00000310 f3 9b 74 84 1f 11 f3 06 c3 f4 df db f0 1e 0a cd |..t.............| +00000320 1b 45 18 44 88 67 79 ca 3e 6e 2b 73 c2 10 84 d8 |.E.D.gy.>n+s....| +00000330 7b c5 2e 81 7d 53 19 46 09 35 35 8b 66 8a a8 cc |{...}S.F.55.f...| +00000340 20 ba 20 15 9f d1 27 9c 6b 3c bb 48 79 4a 7e 11 | . ...'.k<.HyJ~.| +00000350 da e3 26 5b 3a 95 da 4d bd 86 3e 8c 97 55 7c 22 |..&[:..M..>..U|"| +00000360 a1 d3 88 61 ae e1 3b 51 25 c6 01 7e 10 16 03 03 |...a..;Q%..~....| 00000370 00 0c 0d 00 00 08 01 01 00 02 04 01 00 00 16 03 |................| 00000380 03 00 04 0e 00 00 00 |.......| >>> Flow 3 (client to server) @@ -109,26 +109,26 @@ 00000200 e5 35 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.| 00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| 00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 |......._X.;t....| -00000230 88 0f 00 00 84 04 01 00 80 a8 12 9d 84 c2 17 0a |................| -00000240 03 ae bd 87 9a b6 6f 65 2f 7a 04 1f 69 2a 41 f4 |......oe/z..i*A.| -00000250 d0 9a 4d a4 5b 6e d2 d3 42 c3 77 4f 04 28 ce e6 |..M.[n..B.wO.(..| -00000260 d4 25 c5 81 1b 78 91 e9 1e 93 90 57 b2 58 6f 26 |.%...x.....W.Xo&| -00000270 ed 20 15 62 ff e9 c6 c1 52 4a 9a 05 a6 cd 17 22 |. .b....RJ....."| -00000280 75 c8 81 da a4 96 af c6 83 b5 5c 81 93 59 44 26 |u.........\..YD&| -00000290 5b 03 59 9d ab 93 ee c7 37 61 74 e7 4a 22 1c ec |[.Y.....7at.J"..| -000002a0 96 fb a2 c9 ea 2d 4b 8d d3 a7 e4 60 57 10 be b7 |.....-K....`W...| -000002b0 60 80 4f ee 8e 21 6b a2 13 14 03 03 00 01 01 16 |`.O..!k.........| -000002c0 03 03 00 28 00 00 00 00 00 00 00 00 16 82 4a c0 |...(..........J.| -000002d0 98 7b 62 3e 9b da a9 ac 31 f2 32 a9 23 13 2f e3 |.{b>....1.2.#./.| -000002e0 77 c9 1e ca 39 9f 4c 8a 10 58 33 67 |w...9.L..X3g| +00000230 88 0f 00 00 84 04 01 00 80 12 a4 42 13 85 6f 92 |...........B..o.| +00000240 6d 26 5d 05 3c b7 80 ab a9 e0 74 3d 89 67 79 a0 |m&].<.....t=.gy.| +00000250 9f e1 a9 20 d8 82 e2 22 99 38 03 fe 32 d9 1f c7 |... ...".8..2...| +00000260 39 1e 27 31 59 05 eb aa bc 2c 10 eb f0 82 65 65 |9.'1Y....,....ee| +00000270 ce b2 e9 83 67 21 43 03 19 2d 14 9f c3 db bc dc |....g!C..-......| +00000280 59 66 95 d7 4e 09 3c f0 f2 4a 39 f7 db c4 0c 4e |Yf..N.<..J9....N| +00000290 73 e2 d6 59 f1 bc 06 d8 75 df 32 b7 f1 b4 01 98 |s..Y....u.2.....| +000002a0 4f 93 43 a3 a6 09 da cd 1c ee 26 65 ab d1 2a 56 |O.C.......&e..*V| +000002b0 74 32 24 46 27 f3 d9 6a df 14 03 03 00 01 01 16 |t2$F'..j........| +000002c0 03 03 00 28 00 00 00 00 00 00 00 00 68 27 5e 44 |...(........h'^D| +000002d0 d7 73 26 f6 51 86 01 f5 f3 5d 61 a0 05 cd c3 00 |.s&.Q....]a.....| +000002e0 85 6f ea 56 85 1e 7a c3 4c d3 6d 64 |.o.V..z.L.md| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 8e 56 d0 9c 38 |..........(.V..8| -00000010 4f d9 df 12 9b dd 96 05 94 77 2f 6d 24 a8 cb 56 |O........w/m$..V| -00000020 91 f9 bc ec 00 b5 cc 71 c4 f4 36 42 be 68 37 78 |.......q..6B.h7x| -00000030 8f 6e 8c |.n.| +00000000 14 03 03 00 01 01 16 03 03 00 28 81 f3 33 d8 2a |..........(..3.*| +00000010 57 45 53 2c ee 68 8b 79 ed 07 dc 90 c3 a7 84 38 |WES,.h.y.......8| +00000020 8c 33 03 e9 c6 51 04 b2 73 8a 8b 81 12 eb 6c 5f |.3...Q..s.....l_| +00000030 a3 8f 5e |..^| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 1c 19 9e |................| -00000010 a5 40 f6 d7 8b 80 23 8a 0b fa 14 65 08 6a 3c 66 |.@....#....e.j<f| -00000020 07 c4 d2 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................| -00000030 16 7c e2 68 a5 d4 df 64 f4 1c 7d 17 b6 14 0a 4c |.|.h...d..}....L| -00000040 40 8e |@.| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 e5 c6 d7 |................| +00000010 4d e0 d1 0c ff a0 66 c4 71 53 af 7e 16 01 3d 2e |M.....f.qS.~..=.| +00000020 6c ab 90 15 03 03 00 1a 00 00 00 00 00 00 00 02 |l...............| +00000030 92 12 87 24 c8 7e 74 23 df f7 23 49 01 9a dd 3b |...$.~t#..#I...;| +00000040 2c 68 |,h| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPSS b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPSS index 3f74080..de05fec 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPSS +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSAPSS @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 29 bc e2 fe ae |....Y...U..)....| -00000010 0a db 37 e6 39 d5 48 24 3d 0f e5 d7 6b a3 69 dd |..7.9.H$=...k.i.| -00000020 ce 09 fd 28 03 c2 7e 38 db c9 ec 20 d2 5e 3f 94 |...(..~8... .^?.| -00000030 b0 2c 5e 4c 77 c2 94 c3 f2 a9 d0 91 4f 96 45 0e |.,^Lw.......O.E.| -00000040 d3 34 fc 9f e0 a5 e6 fc 1e 8a c1 00 c0 2f 00 00 |.4.........../..| +00000000 16 03 03 00 59 02 00 00 55 03 03 61 fe 1e 35 33 |....Y...U..a..53| +00000010 4b b4 dd 9b 0f 55 58 f4 0c c5 b2 73 51 7b 84 e7 |K....UX....sQ{..| +00000020 25 f7 8f 12 5a 12 11 e1 7b e6 52 20 ad 86 a9 f9 |%...Z...{.R ....| +00000030 7f 6a 30 da 79 23 c3 c4 dc 88 f6 19 1d cc 16 8b |.j0.y#..........| +00000040 96 74 84 ce 53 56 65 e2 cb 94 61 0c c0 2f 00 00 |.t..SVe...a../..| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 66 0b 00 02 62 00 02 5f 00 02 5c 30 82 02 |..f...b.._..\0..| 00000070 58 30 82 01 8d a0 03 02 01 02 02 11 00 f2 99 26 |X0.............&| @@ -61,17 +61,17 @@ 000002a0 11 89 66 79 d1 8e 88 0e 0b a0 9e 30 2a c0 67 ef |..fy.......0*.g.| 000002b0 ca 46 02 88 e9 53 81 22 69 22 97 ad 80 93 d4 f7 |.F...S."i"......| 000002c0 dd 70 14 24 d7 70 0a 46 a1 16 03 03 00 ac 0c 00 |.p.$.p.F........| -000002d0 00 a8 03 00 1d 20 9e e4 39 3a b3 d5 f9 51 16 d4 |..... ..9:...Q..| -000002e0 a8 e1 0a 6d ad 3c ca 01 97 d6 a1 ce 03 2a 67 4a |...m.<.......*gJ| -000002f0 49 06 eb ed c6 24 08 04 00 80 b3 b7 9e fd 97 9b |I....$..........| -00000300 b0 d6 35 89 21 53 ff a8 4b 59 59 26 37 ac 2f 36 |..5.!S..KYY&7./6| -00000310 27 3d 5a 04 3f 50 ed 36 e0 5f 1a d7 1b 36 47 94 |'=Z.?P.6._...6G.| -00000320 45 ec 8c 0b 8f 0f fc df ec 3c 56 f0 d0 28 45 94 |E........<V..(E.| -00000330 96 c7 35 bb 42 31 a6 6e eb 27 cf cf 7e 21 cf 2f |..5.B1.n.'..~!./| -00000340 a1 90 5d 2b 32 23 b3 de 40 a7 b6 56 c1 73 29 56 |..]+2#..@..V.s)V| -00000350 3d 73 fe 34 b2 0b 58 97 16 e6 a1 1c 47 0e 24 a7 |=s.4..X.....G.$.| -00000360 0d c9 a0 51 70 82 b1 d1 a6 a1 bc b4 49 77 c4 c4 |...Qp.......Iw..| -00000370 87 ae c8 49 e6 80 ae d0 dd ca 16 03 03 00 0c 0d |...I............| +000002d0 00 a8 03 00 1d 20 e0 90 02 58 37 69 79 d6 78 e5 |..... ...X7iy.x.| +000002e0 1d c6 7e a0 c6 38 1b ff 47 72 d6 c2 52 cb 6c 52 |..~..8..Gr..R.lR| +000002f0 36 7e 03 c3 35 1d 08 04 00 80 79 5f 23 fd b1 ee |6~..5.....y_#...| +00000300 ac 62 c8 72 09 52 1f 9a 0f ac 95 3e 4e e4 97 d2 |.b.r.R.....>N...| +00000310 a3 04 ae 19 3f 25 ad 3e b7 78 1f d9 79 5f c8 26 |....?%.>.x..y_.&| +00000320 f0 26 e5 ee 54 46 4a 05 84 15 01 4f 7a 7e 60 bd |.&..TFJ....Oz~`.| +00000330 86 74 78 d7 7c 86 91 2b 4f 76 b6 aa 78 27 c8 21 |.tx.|..+Ov..x'.!| +00000340 7e df 88 2f 26 f0 9d 3c a2 e8 95 f6 9f 5a a4 5e |~../&..<.....Z.^| +00000350 18 dc cd 0d 70 e8 85 b7 e5 57 f6 c2 f4 33 28 1c |....p....W...3(.| +00000360 58 7b 94 b0 9e ee d8 b3 42 b5 f3 63 78 a1 30 f3 |X{......B..cx.0.| +00000370 f7 e4 5e 72 64 6f 80 32 70 4e 16 03 03 00 0c 0d |..^rdo.2pN......| 00000380 00 00 08 01 01 00 02 08 04 00 00 16 03 03 00 04 |................| 00000390 0e 00 00 00 |....| >>> Flow 3 (client to server) @@ -117,26 +117,26 @@ 00000270 10 00 00 21 20 2f e5 7d a3 47 cd 62 43 15 28 da |...! /.}.G.bC.(.| 00000280 ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 |._.).0..........| 00000290 5f 58 cb 3b 74 16 03 03 00 88 0f 00 00 84 08 04 |_X.;t...........| -000002a0 00 80 a6 6b 99 15 5e 97 33 4f a8 0e 59 af 15 22 |...k..^.3O..Y.."| -000002b0 f3 6e be 02 6e e4 20 d5 81 c0 b4 74 5a e2 20 32 |.n..n. ....tZ. 2| -000002c0 2b 7f 9c e6 94 32 4d 30 bf 93 86 9b 75 4d f1 9f |+....2M0....uM..| -000002d0 e4 48 28 00 27 fa 7c 45 2e fe d7 0b dc 03 c4 6b |.H(.'.|E.......k| -000002e0 42 ad a2 32 d7 9d ea d6 52 05 3f ed 87 fd b9 9d |B..2....R.?.....| -000002f0 58 fd d6 9f 28 6d 45 07 de 5b 4a 8e f4 4d 19 0b |X...(mE..[J..M..| -00000300 cf 4e 64 75 73 ae cd e9 ae f9 af 27 d0 b9 eb 4c |.Ndus......'...L| -00000310 98 ad 66 6d 4e bf 2c 39 87 f3 72 3e 4e bc a1 8f |..fmN.,9..r>N...| -00000320 a8 1e 14 03 03 00 01 01 16 03 03 00 28 00 00 00 |............(...| -00000330 00 00 00 00 00 04 3c cc ae cd 19 52 6b 1e 0e cc |......<....Rk...| -00000340 dd a9 ac 2f 2a c6 94 4c 09 f3 ee 2f b5 5a 13 1e |.../*..L.../.Z..| -00000350 4f 54 a0 ae c2 |OT...| +000002a0 00 80 b2 c4 60 82 75 ca be 40 dc 28 ec 6d 14 6f |....`.u..@.(.m.o| +000002b0 6c 88 ca 9a d7 ae ce 94 26 a7 10 ad d8 c3 b9 a6 |l.......&.......| +000002c0 48 4e 01 7d ee 6e f8 e0 15 d9 72 c4 79 8d ac 25 |HN.}.n....r.y..%| +000002d0 37 29 83 fc e6 f1 2e 4f 76 49 6a 36 b9 1e b4 58 |7).....OvIj6...X| +000002e0 a2 3e f7 ff 96 5e d9 17 f2 40 05 1f ec bb 5b f5 |.>...^...@....[.| +000002f0 28 86 d2 fc 0e 7e 70 3a 3d 90 4c 46 a5 3e bc 57 |(....~p:=.LF.>.W| +00000300 24 4c ee 35 23 99 6f 21 12 db ba d8 3a 5f 37 1f |$L.5#.o!....:_7.| +00000310 da 3d c2 c9 bf b6 11 8b b9 b9 43 0b 52 ff 6d 2a |.=........C.R.m*| +00000320 74 a7 14 03 03 00 01 01 16 03 03 00 28 00 00 00 |t...........(...| +00000330 00 00 00 00 00 34 bd 90 a0 3f 1c 0c 11 5c 8a e4 |.....4...?...\..| +00000340 28 82 c4 57 59 73 fd a4 dc a9 91 4b df 2a c6 b5 |(..WYs.....K.*..| +00000350 f0 6e cf 41 70 |.n.Ap| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 6d 44 cb 35 8b |..........(mD.5.| -00000010 15 5c f9 f8 1e ae 4f 8c 8c d9 90 9e 6c cf 13 f6 |.\....O.....l...| -00000020 12 29 f5 f7 d6 ff da e2 48 7d 68 ec ad 1a 6c 39 |.)......H}h...l9| -00000030 c5 77 6c |.wl| +00000000 14 03 03 00 01 01 16 03 03 00 28 e2 44 81 59 e4 |..........(.D.Y.| +00000010 6c cf e2 e7 04 78 61 02 36 29 2c 5c c4 6f 13 0b |l....xa.6),\.o..| +00000020 29 ba 74 b0 13 e8 8f 67 39 b5 ea d1 9d 99 d2 f6 |).t....g9.......| +00000030 f7 32 be |.2.| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 2a ce da |.............*..| -00000010 11 1c 7d 49 0d aa 44 d4 d6 d4 7f 64 2b 49 47 20 |..}I..D....d+IG | -00000020 5a 21 bb 15 03 03 00 1a 00 00 00 00 00 00 00 02 |Z!..............| -00000030 fc 10 75 a7 22 f9 74 1c 3a d2 b2 a8 04 2d 37 5f |..u.".t.:....-7_| -00000040 c2 76 |.v| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 5c 7b 38 |.............\{8| +00000010 46 af 57 57 05 5a c5 cb 83 f3 fd 17 d4 c3 2e 93 |F.WW.Z..........| +00000020 d7 70 52 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.pR.............| +00000030 df 2b d8 62 ec 97 c6 ab be d4 7f c9 91 f4 fe 55 |.+.b...........U| +00000040 ac bd |..| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES index 95781c6..d21e9b3 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 eb a2 77 eb b6 |....Y...U....w..| -00000010 1e e4 5c 2c ed 5a dc 93 1b 7e 8a 75 a1 8c ac a6 |..\,.Z...~.u....| -00000020 69 13 f6 f6 a4 69 07 93 99 cf 12 20 37 d7 f8 26 |i....i..... 7..&| -00000030 46 ea 3a 21 03 d0 25 0f 22 84 8d 24 2f 98 3d 42 |F.:!..%."..$/.=B| -00000040 eb 47 1d de 0c 12 ab 95 7a 55 46 f7 c0 09 00 00 |.G......zUF.....| +00000000 16 03 03 00 59 02 00 00 55 03 03 ec 4a 6a f8 c5 |....Y...U...Jj..| +00000010 42 65 f9 d3 4f 65 6f 14 6b bd ae a9 82 5d 06 9b |Be..Oeo.k....]..| +00000020 9d 03 bb 67 eb ba 52 70 74 c3 01 20 f2 ef 69 54 |...g..Rpt.. ..iT| +00000030 1f 4b 79 f7 5b d5 08 b4 18 4c af 8e 55 58 45 22 |.Ky.[....L..UXE"| +00000040 c1 c9 6f cf 36 67 45 20 c7 c5 3a af c0 09 00 00 |..o.6gE ..:.....| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| 00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| @@ -55,39 +55,39 @@ 00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| 00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| 00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| -00000270 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 90 68 |*............ .h| -00000280 81 8b 1d 7f d5 69 36 d3 4e 63 40 fa 3a 21 ee a4 |.....i6.Nc@.:!..| -00000290 c7 b4 09 bc 34 51 89 df d5 d2 79 51 34 32 04 03 |....4Q....yQ42..| -000002a0 00 8b 30 81 88 02 42 01 b4 69 6b 1c e6 35 99 81 |..0...B..ik..5..| -000002b0 fb aa cb b4 2d e9 e0 48 6a 6c 5e 14 54 77 b7 9d |....-..Hjl^.Tw..| -000002c0 df a3 c2 1b 53 8c d2 46 6d 2e ae 83 3a db 7c 86 |....S..Fm...:.|.| -000002d0 4a 45 c7 51 cd 30 d6 8c f5 4f ea 37 cb 1e 27 18 |JE.Q.0...O.7..'.| -000002e0 ba df d5 5f 11 ae 0e af 75 02 42 01 2b 37 2e 6d |..._....u.B.+7.m| -000002f0 7c 11 57 b7 b7 8b 90 73 cd e0 c9 38 3c ee aa d5 ||.W....s...8<...| -00000300 f2 cd ff b9 66 6a be 62 70 74 ee a4 f4 e3 fb 4f |....fj.bpt.....O| -00000310 ed 2e d5 a7 b5 a4 53 c8 1b 17 9e e9 48 e1 dd a6 |......S.....H...| -00000320 e8 6a 05 cf 73 b2 85 11 13 37 be e0 26 16 03 03 |.j..s....7..&...| +00000270 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 7f e5 |*............ ..| +00000280 3b 03 9e 6a 77 11 1b 0f bc 4a db 44 7c 3b 81 1c |;..jw....J.D|;..| +00000290 03 8b 15 a6 f3 16 a0 58 5b 13 c5 1e d2 2c 04 03 |.......X[....,..| +000002a0 00 8b 30 81 88 02 42 00 cc 7c 76 94 81 89 8f 25 |..0...B..|v....%| +000002b0 16 e2 a0 0d 80 4f 7a 8f 8c 83 23 53 23 45 9c c1 |.....Oz...#S#E..| +000002c0 39 e3 0c c2 1b 4d f3 78 cd ea b9 c8 d4 b6 30 bb |9....M.x......0.| +000002d0 ff d7 ad 6c b2 fd 62 4d 8a 05 19 cf 58 ec 81 17 |...l..bM....X...| +000002e0 21 7c 71 a1 d7 ad 87 11 8d 02 42 01 a2 9e c8 e4 |!|q.......B.....| +000002f0 04 7c 75 22 df 14 97 94 8a 1b a1 34 95 95 dd 4c |.|u".......4...L| +00000300 9f 1a c7 c7 96 db ef 87 82 27 9a 27 3a 3d 75 26 |.........'.':=u&| +00000310 04 47 66 eb 55 60 9f 93 4e b2 09 14 fa 71 5b 3f |.Gf.U`..N....q[?| +00000320 33 37 3f 0c f2 5c 4f 1e cc fa b1 6f 70 16 03 03 |37?..\O....op...| 00000330 00 04 0e 00 00 00 |......| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| 00000030 16 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| -00000040 00 00 00 00 00 7f 83 b7 cd 14 66 fb c3 2a f9 9f |..........f..*..| -00000050 79 ec 40 e5 dd 15 46 f3 25 8d dd b2 8e d5 78 97 |y.@...F.%.....x.| -00000060 e5 d6 4e 1a 2e 35 21 b2 aa ac 28 6f 2c 36 a6 6e |..N..5!...(o,6.n| -00000070 44 92 84 1b b9 |D....| +00000040 00 00 00 00 00 d6 67 cb d5 7c 95 9b 16 e2 3b 86 |......g..|....;.| +00000050 22 bd 8c c7 40 36 9b b6 7e 0a 77 78 38 14 37 3c |"...@6..~.wx8.7<| +00000060 48 42 37 a7 07 31 bb 57 c4 e9 f5 e5 a7 58 71 f8 |HB7..1.W.....Xq.| +00000070 82 f7 12 97 72 |....r| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 40 db ee f8 c1 0e |..........@.....| -00000010 7f 23 b4 cb e6 db 03 2a fb 68 40 78 85 03 9e dc |.#.....*.h@x....| -00000020 ac f8 f0 b5 65 8d 7c 01 4a ce 86 29 a9 c5 c3 b2 |....e.|.J..)....| -00000030 12 8d d1 58 af e7 21 75 e4 be f3 c0 03 55 f8 bb |...X..!u.....U..| -00000040 71 bd 85 ee 46 87 a0 32 75 ee 4c |q...F..2u.L| +00000000 14 03 03 00 01 01 16 03 03 00 40 56 45 5c a3 b3 |..........@VE\..| +00000010 64 43 54 7f b5 90 1a 34 ab 2b 68 25 49 41 bf 78 |dCT....4.+h%IA.x| +00000020 50 b0 66 35 20 76 e1 d0 5c 8a 82 2e 03 83 cf c6 |P.f5 v..\.......| +00000030 b7 48 3d 2c c4 cf f5 31 c1 ab 9a 3b 09 3a 75 e3 |.H=,...1...;.:u.| +00000040 b2 05 fa d9 79 cc 1b 0e 30 44 e1 |....y...0D.| >>> Flow 5 (client to server) 00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -00000010 00 00 00 00 00 48 95 f8 a1 0e a7 d0 50 dd cf 8f |.....H......P...| -00000020 c4 af ec 49 89 bf 5d 8b a0 d0 60 7b 38 5a 83 e4 |...I..]...`{8Z..| -00000030 72 47 7f 81 bd 15 03 03 00 30 00 00 00 00 00 00 |rG.......0......| -00000040 00 00 00 00 00 00 00 00 00 00 48 06 f1 30 61 dd |..........H..0a.| -00000050 e2 97 aa 9c 5f a7 07 bb 44 a4 fb d6 6a 7c aa f5 |...._...D...j|..| -00000060 16 ae 38 1a 98 e5 f5 28 c2 57 |..8....(.W| +00000010 00 00 00 00 00 76 5f 1f ec 55 ec f4 87 06 91 b4 |.....v_..U......| +00000020 ba 71 4f 7f 9c ce e1 c7 e6 3d 75 05 fd ba 98 c4 |.qO......=u.....| +00000030 d0 39 24 b8 d4 15 03 03 00 30 00 00 00 00 00 00 |.9$......0......| +00000040 00 00 00 00 00 00 00 00 00 00 e8 4e 09 a1 5f db |...........N.._.| +00000050 91 d5 5b e8 6a 86 7a 6c 7d 4a e1 94 8a 7d 99 52 |..[.j.zl}J...}.R| +00000060 e6 5d d8 35 7c a0 68 8f 09 f9 |.].5|.h...| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM index 7214747..02bad39 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 c9 a1 8b 70 59 |....Y...U.....pY| -00000010 8b 88 41 56 b7 bc 9a 1f 50 57 46 7d 79 d8 ef b2 |..AV....PWF}y...| -00000020 15 3f ad ad bb 48 09 ce e1 c2 2c 20 84 43 65 e7 |.?...H...., .Ce.| -00000030 3f 2f d8 13 9a 79 ac 54 ee b9 13 a1 7c a7 05 f7 |?/...y.T....|...| -00000040 c8 b4 fc bd 20 40 17 ca 15 cd 91 1e c0 2b 00 00 |.... @.......+..| +00000000 16 03 03 00 59 02 00 00 55 03 03 d4 97 12 a8 e7 |....Y...U.......| +00000010 be a9 2d 80 f0 db 01 49 07 04 f4 d1 02 db 3d 4a |..-....I......=J| +00000020 f0 af 31 38 39 d7 4c 1a d3 74 71 20 0f a3 76 14 |..189.L..tq ..v.| +00000030 73 ff 25 1b ef 29 b3 5e 0b 8f fe ee a6 19 d3 31 |s.%..).^.......1| +00000040 5d 2e 71 ab 74 58 e9 d6 c5 9b f4 93 c0 2b 00 00 |].q.tX.......+..| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| 00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| @@ -55,34 +55,34 @@ 00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| 00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| 00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| -00000270 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 58 f9 |*............ X.| -00000280 2e 03 90 fa 3d 33 0d 3e e1 3a b1 5a 45 ec 5c ee |....=3.>.:.ZE.\.| -00000290 9f 47 51 4b 93 89 33 11 e0 63 86 fd b2 3b 04 03 |.GQK..3..c...;..| -000002a0 00 8b 30 81 88 02 42 01 c2 fa 7b f8 ed 6b a5 0f |..0...B...{..k..| -000002b0 33 87 02 35 5b 8e 5d 31 5e 92 df c2 90 ae 58 24 |3..5[.]1^.....X$| -000002c0 43 0f ba e3 b8 77 12 7a 97 c3 77 15 62 d3 f2 cc |C....w.z..w.b...| -000002d0 10 cd a9 be b6 b2 37 93 b1 ce 8b b2 6c fa 93 74 |......7.....l..t| -000002e0 5e 14 8e ba 9e d7 66 48 b8 02 42 01 8e 9a 10 1d |^.....fH..B.....| -000002f0 7d e0 d3 cf 0d d0 3c bc 34 1c 16 20 85 50 03 3f |}.....<.4.. .P.?| -00000300 e1 6d a3 a0 d4 6e d8 fd 7e df b4 c1 84 29 c3 68 |.m...n..~....).h| -00000310 c2 01 dd 77 fc 2c a5 8f 3b 74 c6 e4 32 20 b7 a0 |...w.,..;t..2 ..| -00000320 8c 1b 2d 93 6a 9c 8a ed 21 b5 9a e0 cb 16 03 03 |..-.j...!.......| +00000270 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 a8 15 |*............ ..| +00000280 13 40 df f8 dc 39 f0 af 90 53 a8 34 a9 61 68 c8 |.@...9...S.4.ah.| +00000290 ad be 4f 02 0e d2 83 fd 2e 35 bf 8c 8e 13 04 03 |..O......5......| +000002a0 00 8b 30 81 88 02 42 00 bc 69 df 5b ec 9f 17 ff |..0...B..i.[....| +000002b0 e6 e5 24 71 f6 2b a5 88 40 78 12 ef f3 dc 25 a9 |..$q.+..@x....%.| +000002c0 7c 89 24 0d c7 46 b2 db ae 72 b4 2a 87 87 fe 7e ||.$..F...r.*...~| +000002d0 22 8f e6 d4 c4 7b 61 14 c3 04 39 98 87 6f 1f 54 |"....{a...9..o.T| +000002e0 e0 50 16 0b 52 8e d6 1e 0a 02 42 00 b7 40 26 a8 |.P..R.....B..@&.| +000002f0 11 09 77 ec 36 e5 88 26 6d 83 6f e7 c3 b1 98 c3 |..w.6..&m.o.....| +00000300 4b 83 92 48 65 31 87 68 ee 49 25 ec 95 59 82 b5 |K..He1.h.I%..Y..| +00000310 93 92 c8 17 d6 d9 1c 99 60 48 1b 18 50 b4 e7 df |........`H..P...| +00000320 ed 75 1a f2 08 e8 3d 93 99 27 ef 4d e3 16 03 03 |.u....=..'.M....| 00000330 00 04 0e 00 00 00 |......| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 c2 14 2d |....(..........-| -00000040 fc d7 a2 cb 18 b9 2a ae 38 70 b7 78 7c 88 97 d3 |......*.8p.x|...| -00000050 ff 7f df 12 23 96 ab 4d 6c 5c 67 72 c4 |....#..Ml\gr.| +00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 30 f1 a9 |....(........0..| +00000040 4a 7e 86 a1 5d b7 db 2f c6 e2 ec 36 41 83 66 75 |J~..]../...6A.fu| +00000050 a3 6c 7d e7 61 36 ac f7 76 f8 8e d8 81 |.l}.a6..v....| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 2a dd b3 5b c6 |..........(*..[.| -00000010 76 e7 c0 ac 8c 70 77 d6 d8 4e 79 4a 04 3d 91 a9 |v....pw..NyJ.=..| -00000020 ad 79 ef c9 22 78 17 9e ef b0 03 c8 e6 85 b7 8c |.y.."x..........| -00000030 e5 74 95 |.t.| +00000000 14 03 03 00 01 01 16 03 03 00 28 2c 78 86 13 dc |..........(,x...| +00000010 a4 b9 bf ad 50 45 a3 d9 b3 df 33 a2 79 b1 1b 25 |....PE....3.y..%| +00000020 12 94 97 99 07 6b 52 c4 52 64 ab 89 40 8c 93 4a |.....kR.Rd..@..J| +00000030 e3 cc d9 |...| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 84 b5 0f |................| -00000010 1f ed f9 4c 0d a1 f3 7b 8e 23 87 65 b1 39 98 50 |...L...{.#.e.9.P| -00000020 3d ff 1b 15 03 03 00 1a 00 00 00 00 00 00 00 02 |=...............| -00000030 aa 34 cc f1 4a d3 de 4c 42 bc 2c 0f 3e 71 af 6b |.4..J..LB.,.>q.k| -00000040 3c fc |<.| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 fa 9e 8b |................| +00000010 92 8c f5 32 e6 d4 11 46 b4 73 62 56 f6 83 15 6f |...2...F.sbV...o| +00000020 ce de 2d 15 03 03 00 1a 00 00 00 00 00 00 00 02 |..-.............| +00000030 93 24 68 83 67 b6 f9 27 b5 26 52 78 5d f3 c9 d2 |.$h.g..'.&Rx]...| +00000040 26 a0 |&.| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA256 b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA256 index 96f6218..4946fe4 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA256 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA256 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 87 87 6f ce 44 |....Y...U....o.D| -00000010 94 5f 2f cc 94 03 50 68 a7 4f 37 70 8a d4 cf e3 |._/...Ph.O7p....| -00000020 23 7f 11 f5 93 c7 3f 96 87 49 45 20 9c d4 96 b2 |#.....?..IE ....| -00000030 dc 8c 16 c5 fb cc 2f 8e 0e a5 ef a3 ea cf 57 d0 |....../.......W.| -00000040 09 70 bd 16 c4 d9 e4 1b a0 40 f7 f3 c0 23 00 00 |.p.......@...#..| +00000000 16 03 03 00 59 02 00 00 55 03 03 d1 af 88 61 b7 |....Y...U.....a.| +00000010 b3 01 16 1a 44 26 1c a1 4f 2d 8a f6 9c f2 7e 1a |....D&..O-....~.| +00000020 1f ce cb dd 5b f0 c6 2f 16 5e 4a 20 b3 c7 ae 3f |....[../.^J ...?| +00000030 de d0 d8 9e 48 3e 87 23 f0 9d 43 10 50 3c 66 8b |....H>.#..C.P<f.| +00000040 7f d2 9b 4f f5 e4 b3 53 db d6 65 d0 c0 23 00 00 |...O...S..e..#..| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| 00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| @@ -55,43 +55,43 @@ 00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| 00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| 00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| -00000270 2a 16 03 03 00 b6 0c 00 00 b2 03 00 1d 20 3f a6 |*............ ?.| -00000280 d1 0d ae 8d c0 06 14 ca da 2c 69 1c f1 84 c4 dd |.........,i.....| -00000290 14 f4 0e a6 ce b5 d6 37 9d 9f a5 ba 7b 74 04 03 |.......7....{t..| -000002a0 00 8a 30 81 87 02 42 00 b5 2b 9a 32 9d af b9 cc |..0...B..+.2....| -000002b0 0d b6 f1 9b 87 35 af d7 dc 04 0f 1b 04 d7 fa 62 |.....5.........b| -000002c0 20 bd 2c 31 41 17 e7 c0 ea 22 78 e4 de 37 14 a8 | .,1A...."x..7..| -000002d0 f9 f3 f1 3e 0c 55 59 b3 e3 0e 31 26 ce d0 c1 19 |...>.UY...1&....| -000002e0 b8 17 07 2a 23 98 7b 17 0f 02 41 41 d5 51 80 4d |...*#.{...AA.Q.M| -000002f0 8a 14 56 b1 39 7b 8b 37 24 ef e0 ec 43 44 5a cc |..V.9{.7$...CDZ.| -00000300 9b ab dc 63 e7 cc 7b 29 c0 66 ae 9c 23 c5 1b 98 |...c..{).f..#...| -00000310 6e 35 64 97 12 43 16 73 a6 6b c8 09 2c 26 7c f5 |n5d..C.s.k..,&|.| -00000320 b1 1f 9f 55 04 9e 53 33 c1 89 7a d0 16 03 03 00 |...U..S3..z.....| +00000270 2a 16 03 03 00 b6 0c 00 00 b2 03 00 1d 20 dc 43 |*............ .C| +00000280 15 b7 95 81 41 bf e2 bd 56 82 23 46 05 29 05 95 |....A...V.#F.)..| +00000290 ae 67 08 38 9f 10 70 25 21 92 b4 a0 82 4e 04 03 |.g.8..p%!....N..| +000002a0 00 8a 30 81 87 02 41 5d ca d6 a2 fd e3 e2 be 2f |..0...A]......./| +000002b0 69 b5 7d 5c a3 2b 36 4c 8b 81 05 89 12 e1 30 26 |i.}\.+6L......0&| +000002c0 fa ae 82 b9 4f 8e ba ac ee 7b 62 d5 60 f8 df a4 |....O....{b.`...| +000002d0 c1 a1 15 73 f8 fb 0b 47 64 b3 34 4a 44 02 a6 32 |...s...Gd.4JD..2| +000002e0 bc 0d 7b a5 c1 84 cf 77 02 42 01 f3 e5 7f d1 47 |..{....w.B.....G| +000002f0 bc be 0a ec cd d6 4f 2c 26 5a 95 d3 0f 9b c3 c6 |......O,&Z......| +00000300 05 b5 5e d7 f6 ca 64 17 94 aa a5 e6 b1 88 57 21 |..^...d.......W!| +00000310 f8 da 02 de 32 8c ea 5b 7c 36 c9 93 e1 96 38 93 |....2..[|6....8.| +00000320 9b f9 e5 44 47 a6 74 fa 0e 5f 8f 22 16 03 03 00 |...DG.t.._."....| 00000330 04 0e 00 00 00 |.....| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| 00000030 16 03 03 00 50 00 00 00 00 00 00 00 00 00 00 00 |....P...........| -00000040 00 00 00 00 00 d3 72 3f 9d 37 ba 97 55 83 b4 f0 |......r?.7..U...| -00000050 ad 0b f0 48 98 16 05 f1 b5 6e da a4 79 e4 d9 8e |...H.....n..y...| -00000060 62 af b9 a1 d1 a4 5c 04 d2 b1 86 32 af 64 ac 89 |b.....\....2.d..| -00000070 d3 47 5f 61 ae f4 21 5b 8d 4b ff 74 c1 b8 9c de |.G_a..![.K.t....| -00000080 fd 74 a0 99 c1 |.t...| +00000040 00 00 00 00 00 85 db ae c1 37 85 25 3d ee 5f f5 |.........7.%=._.| +00000050 12 95 df ee 29 4a f7 3a 80 ca bd c2 b3 d8 f3 8c |....)J.:........| +00000060 56 62 d2 68 13 1d 73 51 09 93 a3 b9 43 4a 2c 0f |Vb.h..sQ....CJ,.| +00000070 bf 3c 96 76 08 a9 17 68 e2 9a 3f 39 e7 04 76 f8 |.<.v...h..?9..v.| +00000080 8f fe e8 f5 ce |.....| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 50 09 3b 3e 7e 2e |..........P.;>~.| -00000010 d8 46 04 ac b0 3d c9 7e ec 28 8c bd 6c 0f a8 b5 |.F...=.~.(..l...| -00000020 af 8c 86 ed 64 81 6c d4 98 9e 56 2a 48 0d 03 40 |....d.l...V*H..@| -00000030 64 3e 25 58 6f 03 6a 4e be a2 11 6f 6f e7 2f c2 |d>%Xo.jN...oo./.| -00000040 8f 78 c4 11 a1 07 21 91 9d 34 01 08 39 0d 07 d2 |.x....!..4..9...| -00000050 d4 a2 cc 2f 25 ea ee 8d 8b 91 f9 |.../%......| +00000000 14 03 03 00 01 01 16 03 03 00 50 fa 85 cc bc dd |..........P.....| +00000010 0e 16 86 b1 5c 51 8a b9 cc 78 cd cd 64 5d 23 ca |....\Q...x..d]#.| +00000020 59 84 b3 42 dd ae a7 98 43 05 21 4f 35 43 75 5c |Y..B....C.!O5Cu\| +00000030 13 c8 e0 b6 66 0f 55 32 69 7a 8b 8f cd c2 37 38 |....f.U2iz....78| +00000040 f6 fa 0b 66 cf 46 91 3e 9f f5 43 44 f5 c7 2b e1 |...f.F.>..CD..+.| +00000050 39 3a f7 3c f2 03 c4 85 dc 58 66 |9:.<.....Xf| >>> Flow 5 (client to server) 00000000 17 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| -00000010 00 00 00 00 00 1d 76 4c fb 46 f8 02 9a bc 07 8d |......vL.F......| -00000020 b0 52 40 44 58 da ad be 3c a6 d7 44 0f 59 98 f3 |.R@DX...<..D.Y..| -00000030 ae 5c d2 04 bb 07 ee f6 99 9d 2c 14 44 3b 90 bc |.\........,.D;..| -00000040 2b e9 bc 37 59 15 03 03 00 40 00 00 00 00 00 00 |+..7Y....@......| -00000050 00 00 00 00 00 00 00 00 00 00 c4 ef 97 87 35 a2 |..............5.| -00000060 2f cc c2 6f 3d d5 f5 6f fd 74 56 50 37 f8 10 e8 |/..o=..o.tVP7...| -00000070 36 f5 fb 6f 7b 5d 20 07 0d 2f 72 46 a7 3a e0 de |6..o{] ../rF.:..| -00000080 39 b3 76 0e 4f c0 e7 85 4b bb |9.v.O...K.| +00000010 00 00 00 00 00 44 e6 99 40 ae 12 bc d9 92 c5 ae |.....D..@.......| +00000020 fb 4d 5f 64 7a 77 0f 80 8e a4 be d0 ba ba 41 b1 |.M_dzw........A.| +00000030 0d 40 e9 0e 50 32 dc 35 2d 5e 5c 8a ef 20 75 80 |.@..P2.5-^\.. u.| +00000040 a0 e5 9c 61 49 15 03 03 00 40 00 00 00 00 00 00 |...aI....@......| +00000050 00 00 00 00 00 00 00 00 00 00 57 91 40 2a a5 f7 |..........W.@*..| +00000060 9f 29 0f 02 8e 50 ac 4b 2e 55 9a 78 72 f0 d7 c5 |.)...P.K.U.xr...| +00000070 3b f2 cd 28 4d 8b 49 d8 50 a6 22 96 de df 16 d6 |;..(M.I.P.".....| +00000080 61 4b 23 5c 5d de a1 0a 5b 16 |aK#\]...[.| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384 b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384 index 90a1639..14af5ae 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 b8 16 bd ae 15 |....Y...U.......| -00000010 a3 33 52 cc 60 dc 6c fe 7c f3 82 b9 1e 13 ab 87 |.3R.`.l.|.......| -00000020 22 d8 c3 38 dc 8a 76 bb a0 a3 fd 20 8a d1 92 d1 |"..8..v.... ....| -00000030 d6 f3 76 e0 e2 76 32 95 32 a0 eb 5b dc e4 42 81 |..v..v2.2..[..B.| -00000040 14 bb 58 ab b8 e8 9d ee fa 32 58 05 c0 2c 00 00 |..X......2X..,..| +00000000 16 03 03 00 59 02 00 00 55 03 03 bb 8a 66 ee 44 |....Y...U....f.D| +00000010 42 dc 59 c7 a7 7b a8 57 8e 63 21 f0 4e 31 f4 5c |B.Y..{.W.c!.N1.\| +00000020 1d d3 42 e5 de eb 8c 78 3a 01 01 20 9b 89 05 d6 |..B....x:.. ....| +00000030 d2 07 38 8b 4c 5f 6d 62 9f 43 a0 cd d3 40 0f 77 |..8.L_mb.C...@.w| +00000040 17 ff 43 4a 5c b3 8c 83 b7 4b c7 e7 c0 2c 00 00 |..CJ\....K...,..| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| 00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| @@ -55,34 +55,34 @@ 00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| 00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| 00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| -00000270 2a 16 03 03 00 b6 0c 00 00 b2 03 00 1d 20 5c 9b |*............ \.| -00000280 9b 29 5c 83 36 b8 20 47 2b 04 0d 1b ab f5 f7 81 |.)\.6. G+.......| -00000290 aa 89 b4 93 37 aa 28 4e 44 e1 22 26 b6 46 04 03 |....7.(ND."&.F..| -000002a0 00 8a 30 81 87 02 42 01 2c 87 df 1f 07 86 36 c8 |..0...B.,.....6.| -000002b0 f6 aa 41 c1 8e 99 6e 12 08 5f e2 62 4b 3a 9b ad |..A...n.._.bK:..| -000002c0 e8 26 1c 95 f9 62 c6 f6 c7 e4 f7 db 3b 23 e5 4f |.&...b......;#.O| -000002d0 03 a1 c6 89 74 cb bd 2a 4e 47 3f 0f bf 28 bb 6d |....t..*NG?..(.m| -000002e0 c0 c6 53 4c 02 0b 9a 30 2d 02 41 0c 6f 26 a5 4c |..SL...0-.A.o&.L| -000002f0 b6 6c 8c ab 82 32 19 a0 f0 1b 41 2d 9d 1d 12 1b |.l...2....A-....| -00000300 91 62 6a 3d 17 92 79 f6 59 45 21 2f 6b d0 cb 7b |.bj=..y.YE!/k..{| -00000310 22 b3 79 80 90 90 81 97 06 c8 59 fd 8b 40 f9 ec |".y.......Y..@..| -00000320 80 58 db fc 5e a2 67 9a 96 01 53 d4 16 03 03 00 |.X..^.g...S.....| -00000330 04 0e 00 00 00 |.....| +00000270 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 fd 71 |*............ .q| +00000280 c1 3a 6a a3 69 6a 34 f3 02 c5 1d e5 db 63 f4 eb |.:j.ij4......c..| +00000290 97 4c 70 bc b3 4e 9d 2c 2f b2 b9 9d ac 3f 04 03 |.Lp..N.,/....?..| +000002a0 00 8b 30 81 88 02 42 01 bd 9d ad 24 37 b9 60 55 |..0...B....$7.`U| +000002b0 e4 cc bc 49 c3 88 3b ed ac e4 42 8e fa 81 01 d9 |...I..;...B.....| +000002c0 39 4c f0 1c 7d 39 a2 81 8a e1 17 0e 8d 37 76 96 |9L..}9.......7v.| +000002d0 37 13 3a 1e 2e fd 0d 0a 3c 90 9d 43 3d 06 c0 b1 |7.:.....<..C=...| +000002e0 4e 07 3e c3 9f f2 43 40 0b 02 42 01 d6 d0 20 ad |N.>...C@..B... .| +000002f0 48 09 c0 9b 5d c8 84 46 3b 98 37 9b 5a 91 4a 07 |H...]..F;.7.Z.J.| +00000300 79 68 71 92 76 dc 70 0f 5c 44 7e 81 c3 c6 3f 19 |yhq.v.p.\D~...?.| +00000310 f4 0f 6a 0b aa cc bb 65 e7 34 b5 e9 67 2d 32 98 |..j....e.4..g-2.| +00000320 1c f6 76 4c 96 73 df 21 d6 e1 ea 34 86 16 03 03 |..vL.s.!...4....| +00000330 00 04 0e 00 00 00 |......| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 17 be e6 |....(...........| -00000040 ba 39 2d 82 38 6e 09 2c 1c ef d5 1f ad 8e e0 47 |.9-.8n.,.......G| -00000050 2d bc 74 f8 3b ed 86 89 9e e9 a5 01 40 |-.t.;.......@| +00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 27 fd 98 |....(........'..| +00000040 47 79 56 f9 e8 0e fd 18 c2 8f 2d 32 51 f7 19 b5 |GyV.......-2Q...| +00000050 ab 2f 81 ed b6 cf 6f b5 65 81 81 f1 44 |./....o.e...D| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 42 3b b0 5e 66 |..........(B;.^f| -00000010 3e ef a5 3d 49 64 42 34 b1 21 d6 43 d3 f6 f5 84 |>..=IdB4.!.C....| -00000020 21 96 b4 7b ed 73 b5 23 b6 40 cf 86 ab 71 59 58 |!..{.s.#.@...qYX| -00000030 3a bf 79 |:.y| +00000000 14 03 03 00 01 01 16 03 03 00 28 a9 b7 63 61 57 |..........(..caW| +00000010 54 57 f0 b2 60 58 e3 dc 6e e1 40 3e 67 b4 99 8f |TW..`X..n.@>g...| +00000020 e9 6b 11 f1 1a 54 bd c1 d3 b9 5b 01 12 27 a4 0b |.k...T....[..'..| +00000030 e9 ec 01 |...| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 8d 3c f7 |..............<.| -00000010 9e da 91 15 35 10 5f a4 29 32 3f 6a 8c 1d bc 13 |....5._.)2?j....| -00000020 8a 35 2b 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.5+.............| -00000030 1f b3 e3 e3 24 ac 7a a6 ee 81 e7 cc 9e 70 34 2c |....$.z......p4,| -00000040 d2 28 |.(| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 e0 8a 6e |...............n| +00000010 62 5d e3 db 99 10 d2 53 b6 21 2e 79 31 cf 71 1d |b].....S.!.y1.q.| +00000020 34 71 2a 15 03 03 00 1a 00 00 00 00 00 00 00 02 |4q*.............| +00000030 e7 4a 8d b9 2f 1b b1 70 72 da 7f d8 fa 4f 9f d6 |.J../..pr....O..| +00000040 ca f3 |..| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305 b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305 index 1b3c37b..3113b3c 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305 @@ -4,7 +4,7 @@ 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 08 cc a9 |................| -00000050 13 01 13 03 13 02 01 00 00 7b 00 05 00 05 01 00 |.........{......| +00000050 13 03 13 01 13 02 01 00 00 7b 00 05 00 05 01 00 |.........{......| 00000060 00 00 00 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 |................| 00000070 19 00 0b 00 02 01 00 00 0d 00 1a 00 18 08 04 04 |................| 00000080 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 06 |................| @@ -14,11 +14,11 @@ 000000c0 ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 |._.).0..........| 000000d0 5f 58 cb 3b 74 |_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 ea 73 50 31 e4 |....Y...U...sP1.| -00000010 7a c7 e2 05 23 a0 22 e3 1a cd 6d b5 0f e7 f2 5e |z...#."...m....^| -00000020 d6 cb 6c 70 05 04 a9 63 4a a3 fc 20 a2 c5 68 f2 |..lp...cJ.. ..h.| -00000030 9b 56 6e 83 66 c1 7f 85 02 b6 6d 37 12 0f 12 5a |.Vn.f.....m7...Z| -00000040 41 7e c3 c9 44 85 3c 00 50 6f c7 f9 cc a9 00 00 |A~..D.<.Po......| +00000000 16 03 03 00 59 02 00 00 55 03 03 e1 cc 3c 49 04 |....Y...U....<I.| +00000010 bb 5b 18 c7 44 8f 52 62 d9 74 84 94 fa 61 3f 12 |.[..D.Rb.t...a?.| +00000020 c8 23 50 0b 8a 5c 81 23 c2 9d 3d 20 1f b2 67 b0 |.#P..\.#..= ..g.| +00000030 e9 2d a9 ed 35 4e ab b9 73 59 32 2f 49 ed 1e 60 |.-..5N..sY2/I..`| +00000040 4c 31 11 6e 27 79 e0 62 e0 e4 ca 16 cc a9 00 00 |L1.n'y.b........| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..| 00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....| @@ -53,32 +53,32 @@ 00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....| 00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.| 00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....| -00000270 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 a4 6a |*............ .j| -00000280 0d ab f2 7c 1a 31 2a 7d 51 b7 fe 69 cd 59 f5 c1 |...|.1*}Q..i.Y..| -00000290 10 94 a0 b2 6f 6f c4 48 48 9b 20 1e 46 2a 04 03 |....oo.HH. .F*..| -000002a0 00 8b 30 81 88 02 42 00 84 2a 96 88 a4 7a 86 7f |..0...B..*...z..| -000002b0 cf 86 20 37 17 de 54 0c c2 89 5e 27 f4 3b a4 ec |.. 7..T...^'.;..| -000002c0 ce 25 34 4e c7 a8 7d f5 56 6d 96 2c d0 53 ae 42 |.%4N..}.Vm.,.S.B| -000002d0 b5 87 a9 20 9c 4f c9 67 7e ca f6 fc 2f 61 72 35 |... .O.g~.../ar5| -000002e0 78 fe 54 32 1e a1 90 88 c2 02 42 01 a6 7b 98 de |x.T2......B..{..| -000002f0 fd 01 4b 4a 8f 1a e8 18 dd 07 bb 0b 38 41 7f 22 |..KJ........8A."| -00000300 62 3b 7e 37 67 b7 18 46 a7 32 43 1b c9 a9 8a a6 |b;~7g..F.2C.....| -00000310 d7 8a 2f 7b c5 14 f3 33 96 fe 0a fc 22 d0 a5 02 |../{...3...."...| -00000320 37 a5 31 5f b9 6b d2 3b f6 d0 d1 7b a1 16 03 03 |7.1_.k.;...{....| -00000330 00 04 0e 00 00 00 |......| +00000270 2a 16 03 03 00 b6 0c 00 00 b2 03 00 1d 20 cc a1 |*............ ..| +00000280 4d a4 b1 22 86 e5 91 9b e2 1a 28 c6 66 06 1a 89 |M.."......(.f...| +00000290 a9 62 23 93 09 54 ae 67 a8 ab 18 ac 67 37 04 03 |.b#..T.g....g7..| +000002a0 00 8a 30 81 87 02 42 01 f0 46 f3 3f 13 a7 1d 84 |..0...B..F.?....| +000002b0 73 65 9e 91 16 6c 3d 8f 21 ab 17 db 24 34 21 8c |se...l=.!...$4!.| +000002c0 a9 e1 9b a6 17 c8 0d 7a b4 8e f0 46 cd c5 b9 b2 |.......z...F....| +000002d0 5e 64 7f 9f 9d 03 14 7a 23 5d 55 70 ae d1 ff 08 |^d.....z#]Up....| +000002e0 e8 70 f5 5d 55 90 74 04 0d 02 41 09 ca 7d 60 ea |.p.]U.t...A..}`.| +000002f0 13 17 42 e8 53 e7 c5 31 15 4a 58 14 d6 54 f5 40 |..B.S..1.JX..T.@| +00000300 a1 aa fe 4b 13 f5 29 04 05 cc 12 26 e2 b7 e5 a6 |...K..)....&....| +00000310 90 7c 5e 66 2f ed 41 7c 97 a1 72 87 5e 46 5a 5b |.|^f/.A|..r.^FZ[| +00000320 1b d1 7b 3c 34 ba 3f 47 7d a9 84 33 16 03 03 00 |..{<4.?G}..3....| +00000330 04 0e 00 00 00 |.....| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 f5 a0 28 0a 7e d4 8b a2 b6 e1 af |.... ..(.~......| -00000040 83 e2 50 e8 fc 7e f0 59 21 ed 3d 0d a8 ef a9 b1 |..P..~.Y!.=.....| -00000050 5a 13 2a 1b 2c |Z.*.,| +00000030 16 03 03 00 20 7f ab 78 f0 a6 b6 57 bd c3 b9 32 |.... ..x...W...2| +00000040 96 3f 7c 9d a0 4d dc 74 c9 e8 1a 88 c4 b2 10 27 |.?|..M.t.......'| +00000050 e3 9c 1e 9b e1 |.....| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 44 15 68 4d e0 |.......... D.hM.| -00000010 3b 34 c5 77 b2 25 f2 e9 35 75 08 f5 a9 53 c9 65 |;4.w.%..5u...S.e| -00000020 19 36 49 fe 43 e4 f5 48 ac 7c d7 |.6I.C..H.|.| +00000000 14 03 03 00 01 01 16 03 03 00 20 0c b7 0c 47 8e |.......... ...G.| +00000010 40 6b 9f 9c d2 cd 24 25 db 12 e8 0c 50 be f3 98 |@k....$%....P...| +00000020 4a 6f f9 42 58 07 b9 64 d0 00 91 |Jo.BX..d...| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 f7 fd 2a 83 90 01 f3 d2 82 dc bd |.......*........| -00000010 6c 33 31 a3 92 0f a4 f5 9c fa f4 15 03 03 00 12 |l31.............| -00000020 9e 60 18 02 f1 0d 2f f5 5f 68 69 ae 62 93 04 6a |.`..../._hi.b..j| -00000030 41 f0 |A.| +00000000 17 03 03 00 16 1d 32 1c ef 0b 1f a4 ba 39 a3 63 |......2......9.c| +00000010 04 29 e5 67 1e bb 5a 6e c7 3c c1 15 03 03 00 12 |.).g..Zn.<......| +00000020 0e 0b 0f 49 30 fe d4 c3 35 85 e3 db 6e 65 e3 2d |...I0...5...ne.-| +00000030 d1 1d |..| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES index eff5b97..ea6c787 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 f1 07 97 47 f7 |....Y...U.....G.| -00000010 b8 42 f5 ce 2b b5 ec 5a d3 74 f1 fa 1f ea ec 6d |.B..+..Z.t.....m| -00000020 49 4e cf 2e 47 8b 2e 80 9b 8a ed 20 89 ca 35 4a |IN..G...... ..5J| -00000030 f4 35 5e b7 ed b2 96 ad e1 66 1d 43 9d 07 ba ed |.5^......f.C....| -00000040 ff 9d 47 65 c8 7d 91 32 4b 88 4d 83 c0 13 00 00 |..Ge.}.2K.M.....| +00000000 16 03 03 00 59 02 00 00 55 03 03 1e 2f 6f fa 02 |....Y...U.../o..| +00000010 44 3e 0d d0 3e b5 e6 0c a2 d6 aa 04 5b ba 93 39 |D>..>.......[..9| +00000020 29 dd e7 7e b8 11 f9 85 97 a5 e4 20 9c 64 e9 47 |)..~....... .d.G| +00000030 cb 7c 0c 77 9d 83 5a c4 e8 05 62 40 95 8e 8e aa |.|.w..Z...b@....| +00000040 39 bb 24 8f b7 29 75 77 18 66 60 29 c0 13 00 00 |9.$..)uw.f`)....| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,38 +60,38 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| -000002c0 ac 0c 00 00 a8 03 00 1d 20 78 22 92 20 a9 be 78 |........ x". ..x| -000002d0 12 0f e6 83 13 3d 13 91 16 11 ca 26 9f b7 37 d5 |.....=.....&..7.| -000002e0 f0 97 f9 f2 01 fd 08 4f 42 08 04 00 80 2c f1 4e |.......OB....,.N| -000002f0 79 63 f2 d9 54 1c 0c 56 fd 56 4d e0 37 ee 5d bb |yc..T..V.VM.7.].| -00000300 22 90 fd ee d9 0f e6 d9 85 41 b9 8d d6 76 5f 05 |"........A...v_.| -00000310 1b 8c d7 4e c5 e8 4e 69 b9 5d de 73 c0 ed 4f 3e |...N..Ni.].s..O>| -00000320 09 9d b0 10 d6 61 87 d8 f9 c2 5b 48 f9 ef dd 65 |.....a....[H...e| -00000330 e6 f8 b0 d2 71 f6 e9 ae b1 c0 ea 90 dc 33 c6 72 |....q........3.r| -00000340 3e 9f 31 d4 ae 78 23 54 7a 4f 02 69 72 c1 06 2f |>.1..x#TzO.ir../| -00000350 3f 3c 7b f2 d8 17 40 a6 95 6d 46 62 6b 54 f1 cf |?<{...@..mFbkT..| -00000360 60 08 63 89 f7 a5 2a 52 3b 0e 0c d6 34 16 03 03 |`.c...*R;...4...| +000002c0 ac 0c 00 00 a8 03 00 1d 20 92 ed 81 60 d9 51 c2 |........ ...`.Q.| +000002d0 00 3d 99 84 82 c5 83 67 60 b3 11 59 0c c5 5d ff |.=.....g`..Y..].| +000002e0 d6 28 79 68 2d 73 7f 84 40 08 04 00 80 b6 a0 4b |.(yh-s..@......K| +000002f0 3d fb e1 e6 76 cc ae e3 59 d0 1c 50 5c 09 5d 80 |=...v...Y..P\.].| +00000300 c2 58 0d 36 d7 1a 78 e3 c2 66 73 3a 14 06 37 6f |.X.6..x..fs:..7o| +00000310 3a 95 2e 2a eb cc e5 e3 f7 30 eb 0d 33 04 51 6e |:..*.....0..3.Qn| +00000320 06 86 8f 53 6d fd 97 75 b3 13 2e 4e ee 8f 03 68 |...Sm..u...N...h| +00000330 23 32 83 96 af 01 ed b0 21 a7 13 06 47 f4 08 b9 |#2......!...G...| +00000340 8a 47 cc 12 99 20 c6 31 77 28 2c 2e d6 a0 20 8c |.G... .1w(,... .| +00000350 e6 67 c7 70 23 ed 98 9c c9 47 1c e0 37 95 42 aa |.g.p#....G..7.B.| +00000360 c2 19 1b 55 09 5c 58 fb ef 67 a9 b5 65 16 03 03 |...U.\X..g..e...| 00000370 00 04 0e 00 00 00 |......| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| 00000030 16 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| -00000040 00 00 00 00 00 96 55 d3 bd a1 b6 de 93 68 19 ed |......U......h..| -00000050 4a 3a cc 42 7c c4 41 1e b5 37 65 d5 84 10 60 3d |J:.B|.A..7e...`=| -00000060 e9 57 29 28 79 54 da 6c 1b 36 6b b1 75 f4 bb 32 |.W)(yT.l.6k.u..2| -00000070 47 8d de c8 7d |G...}| +00000040 00 00 00 00 00 dd 81 23 e0 a3 01 33 bb 87 0d 93 |.......#...3....| +00000050 b2 61 16 01 e3 87 e0 05 cc b0 ec 15 56 df ff 9c |.a..........V...| +00000060 e6 9c 6a 57 79 8a 0b 86 f9 fb 60 3f ca 0d ef f2 |..jWy.....`?....| +00000070 81 c0 5e 22 bf |..^".| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 40 db ed ec 54 4a |..........@...TJ| -00000010 20 d8 a7 ee 12 04 e2 e4 95 b4 a4 a7 e1 80 c8 40 | ..............@| -00000020 81 00 6d 3e 58 26 7c d4 26 84 86 ee b4 fc c5 50 |..m>X&|.&......P| -00000030 46 31 e7 4c 1e fd ed 10 7e 72 45 18 43 db 4c 0d |F1.L....~rE.C.L.| -00000040 b5 49 6c 31 04 f0 85 a7 f8 02 e1 |.Il1.......| +00000000 14 03 03 00 01 01 16 03 03 00 40 d4 d3 ba 7f 4c |..........@....L| +00000010 1a ee d9 ca 66 a0 5b d7 08 78 5d 5c fd 17 32 71 |....f.[..x]\..2q| +00000020 7f 8c 2e eb 80 bc 82 0f 0c ed 71 ac 34 59 71 d1 |..........q.4Yq.| +00000030 aa d3 fd 0c 50 7d 4b 1b 01 5d 4c 03 9f 6c 16 8f |....P}K..]L..l..| +00000040 5d f7 8d c0 4b 3f 01 96 23 40 22 |]...K?..#@"| >>> Flow 5 (client to server) 00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -00000010 00 00 00 00 00 90 f7 06 a7 05 8d de 51 21 88 95 |............Q!..| -00000020 47 61 fb 8d a9 c9 6d 59 ca 92 8d 07 8b 9d 82 4e |Ga....mY.......N| -00000030 fd e9 ae 3d b0 15 03 03 00 30 00 00 00 00 00 00 |...=.....0......| -00000040 00 00 00 00 00 00 00 00 00 00 12 77 0c 5f 12 4b |...........w._.K| -00000050 96 ab 64 58 6e f5 82 09 6c 18 ae 1f a2 fb 0a 3b |..dXn...l......;| -00000060 71 17 25 8b c8 72 d0 13 fb e8 |q.%..r....| +00000010 00 00 00 00 00 36 49 0e f6 26 13 f7 69 15 54 27 |.....6I..&..i.T'| +00000020 5a e6 f2 fb 7d ad e0 30 d3 cd ed 08 24 74 5f 77 |Z...}..0....$t_w| +00000030 f7 8b 3f bf 94 15 03 03 00 30 00 00 00 00 00 00 |..?......0......| +00000040 00 00 00 00 00 00 00 00 00 00 28 09 ed 2f d8 6f |..........(../.o| +00000050 95 fc db 9e ec d8 81 7e a4 d4 8e c5 ec d3 24 bc |.......~......$.| +00000060 ab 52 e6 01 75 98 b9 e5 9f d9 |.R..u.....| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256 b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256 index 4f8f49e..88d0d01 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 9e d4 c1 3e c6 |....Y...U.....>.| -00000010 3d 44 eb a7 b8 c5 c8 e0 ab 16 06 83 67 5e b2 d6 |=D..........g^..| -00000020 67 50 4b f3 24 17 97 19 76 7e 71 20 5a 2b dc 15 |gPK.$...v~q Z+..| -00000030 87 37 be bb c7 9c 38 cd 3e 55 4e 33 32 a0 01 1b |.7....8.>UN32...| -00000040 79 13 87 6a 19 09 42 4c fb 59 97 a8 c0 27 00 00 |y..j..BL.Y...'..| +00000000 16 03 03 00 59 02 00 00 55 03 03 e6 04 5e a9 bb |....Y...U....^..| +00000010 23 56 bd cc e7 72 9f 10 b1 fc 23 48 22 19 cb 27 |#V...r....#H"..'| +00000020 3e c4 22 ec b9 7a 9c 81 60 c5 55 20 b9 7f 8a 0e |>."..z..`.U ....| +00000030 6b d6 cf cb 35 85 52 f3 9f 28 00 87 22 88 6d 7c |k...5.R..(..".m|| +00000040 35 0e f6 af 7c 28 b4 71 cc 46 c1 b5 c0 27 00 00 |5...|(.q.F...'..| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,42 +60,42 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| -000002c0 ac 0c 00 00 a8 03 00 1d 20 57 62 97 e9 c8 c6 17 |........ Wb.....| -000002d0 73 d2 9e 31 a6 f8 be 03 65 86 af 6b e2 64 bf 7c |s..1....e..k.d.|| -000002e0 4a f1 b9 fb 84 21 10 76 66 08 04 00 80 2d 08 24 |J....!.vf....-.$| -000002f0 06 2a a3 c5 28 c4 22 5b fe 79 4f 91 56 9e 40 6f |.*..(."[.yO.V.@o| -00000300 e6 0c e8 70 e0 35 9e 55 91 51 86 ec ad ff 6b 3f |...p.5.U.Q....k?| -00000310 a7 19 fa 6f 74 47 8a 86 04 b5 8a f0 0a d5 e5 5f |...otG........._| -00000320 ea 30 cc 79 77 3d ac 99 da 41 7f 25 3b da cd da |.0.yw=...A.%;...| -00000330 aa 4e 2a 54 b5 d3 13 4f e4 e9 cb 76 86 fb 0b b5 |.N*T...O...v....| -00000340 0d a3 be ab d2 e6 6e f6 77 7c 60 a7 50 56 43 60 |......n.w|`.PVC`| -00000350 95 ba 95 c4 b5 1a 8d 6a f7 a5 9f 03 27 93 9f 23 |.......j....'..#| -00000360 44 27 88 f0 d5 51 0f ba 43 84 5c 02 14 16 03 03 |D'...Q..C.\.....| +000002c0 ac 0c 00 00 a8 03 00 1d 20 55 af 53 a0 54 77 df |........ U.S.Tw.| +000002d0 ca 8f 49 1a 4d d0 9b 24 a6 a9 2b b2 2a 33 46 b8 |..I.M..$..+.*3F.| +000002e0 01 d6 4e fd fb c1 e4 e6 64 08 04 00 80 5c da 2f |..N.....d....\./| +000002f0 01 2b 10 b9 e9 35 f2 b1 2a 28 4f 78 58 7b 3d 9a |.+...5..*(OxX{=.| +00000300 13 e4 7c 77 41 95 fa 7a 90 1f eb f5 20 55 7c 76 |..|wA..z.... U|v| +00000310 dd c5 66 08 88 eb ba 17 f0 de f3 0c a5 a6 3c 21 |..f...........<!| +00000320 52 89 25 b1 4d 86 e3 0b 8a 14 dc 8b a6 76 41 25 |R.%.M........vA%| +00000330 9e d3 20 b6 61 8a 26 8b 0d b7 cb 98 ac 45 e0 3b |.. .a.&......E.;| +00000340 6f d6 b2 52 8b a2 31 63 c8 44 1d 2a 3a c1 35 87 |o..R..1c.D.*:.5.| +00000350 7a 7b 2a fa dd ab d3 48 9b e2 fa e1 93 7c 09 f7 |z{*....H.....|..| +00000360 e1 72 83 f8 23 07 30 3a 4a 4f 56 97 1b 16 03 03 |.r..#.0:JOV.....| 00000370 00 04 0e 00 00 00 |......| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| 00000030 16 03 03 00 50 00 00 00 00 00 00 00 00 00 00 00 |....P...........| -00000040 00 00 00 00 00 02 19 fd 3e 06 0d 12 0d 03 42 da |........>.....B.| -00000050 76 6f e2 e3 96 eb 42 d9 96 b7 0b ae d6 a0 06 fa |vo....B.........| -00000060 57 4e ff 62 85 dd 3f ab 63 f9 73 87 8d 71 6a c6 |WN.b..?.c.s..qj.| -00000070 f4 ef ce f5 55 5b d2 1f b5 33 fd 12 32 bd 5e 1e |....U[...3..2.^.| -00000080 d5 32 91 9a ae |.2...| +00000040 00 00 00 00 00 91 c1 82 23 f0 03 79 83 38 ef d0 |........#..y.8..| +00000050 73 71 9b 7d 55 5e 53 3b d3 cf 86 48 60 2f 42 97 |sq.}U^S;...H`/B.| +00000060 63 e8 4b 20 4c 92 3e 2f aa b3 32 46 8a 96 69 42 |c.K L.>/..2F..iB| +00000070 96 9a 4b bd 04 f2 3d b6 5f f9 37 4f a4 3d f1 cb |..K...=._.7O.=..| +00000080 d5 57 fc 5e 8e |.W.^.| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 50 77 80 95 42 a3 |..........Pw..B.| -00000010 2b 1c 16 0f 3b f4 78 2a bd ab 6e d1 33 1e 0e a5 |+...;.x*..n.3...| -00000020 c7 f4 e9 92 82 00 da 44 0f b6 4e f9 1f ef 67 3b |.......D..N...g;| -00000030 de 5c dc 93 07 68 99 1a 70 7f 92 a7 d7 da f3 60 |.\...h..p......`| -00000040 cf d5 f1 f0 5e 75 68 a1 0b 32 eb d2 96 de e6 34 |....^uh..2.....4| -00000050 c3 e3 26 43 1f a2 8d e7 1b fc 76 |..&C......v| +00000000 14 03 03 00 01 01 16 03 03 00 50 e1 91 69 dc 7b |..........P..i.{| +00000010 5f a4 c7 7a 8f ba bb 8d 98 c3 0e 3f 10 f1 3e 3f |_..z.......?..>?| +00000020 37 6f 11 81 3f c5 7c 22 6f 22 a3 94 ae 3a 77 17 |7o..?.|"o"...:w.| +00000030 a2 7b cc 8e 5e 6e 9b 4b 98 fd 16 f8 46 9e 78 19 |.{..^n.K....F.x.| +00000040 43 e6 da e3 05 9a 0a 49 b0 09 c7 e5 4b 41 dc b4 |C......I....KA..| +00000050 c0 81 9b 46 7e dd c3 64 2e f8 6e |...F~..d..n| >>> Flow 5 (client to server) 00000000 17 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........| -00000010 00 00 00 00 00 f8 35 11 b8 23 cf d9 ec a7 d3 b9 |......5..#......| -00000020 60 1e 34 01 20 49 73 ec 72 78 58 24 3b fc a8 42 |`.4. Is.rxX$;..B| -00000030 b2 a9 69 69 40 65 5a c2 8b 9f 0b 0e 70 ab ac 22 |..ii@eZ.....p.."| -00000040 1a ac d6 04 06 15 03 03 00 40 00 00 00 00 00 00 |.........@......| -00000050 00 00 00 00 00 00 00 00 00 00 fe ed 19 a0 84 06 |................| -00000060 8b f0 e8 4e 30 7a 3c 89 a0 a8 59 74 a5 92 73 f3 |...N0z<...Yt..s.| -00000070 df 1b f0 c6 5a 95 d5 1c b6 57 4a 1b 8f 24 59 87 |....Z....WJ..$Y.| -00000080 b4 2b 7f 6f 89 03 e8 6d e5 d9 |.+.o...m..| +00000010 00 00 00 00 00 65 4c 71 31 d4 47 4d 0b 81 1f 75 |.....eLq1.GM...u| +00000020 b6 71 64 4a e6 a8 80 a1 f1 e2 0a 14 77 af a4 c6 |.qdJ........w...| +00000030 1d 6a 7d 79 6a 15 a1 0e 86 6c 8e e1 32 64 0b 5d |.j}yj....l..2d.]| +00000040 af e0 f5 05 91 15 03 03 00 40 00 00 00 00 00 00 |.........@......| +00000050 00 00 00 00 00 00 00 00 00 00 ca 46 1b 95 2a 41 |...........F..*A| +00000060 ce dc 30 d6 e0 cf 2f 2b 1f 61 81 33 a4 58 e7 af |..0.../+.a.3.X..| +00000070 90 9c 15 42 9b ab 26 64 d1 39 46 45 6b 74 b9 c4 |...B..&d.9FEkt..| +00000080 21 d9 ef 2d 69 51 dc e7 8a 6b |!..-iQ...k| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305 b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305 index 38fb4a0..2c2cb45 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305 @@ -4,7 +4,7 @@ 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 08 cc a8 |................| -00000050 13 01 13 03 13 02 01 00 00 7b 00 05 00 05 01 00 |.........{......| +00000050 13 03 13 01 13 02 01 00 00 7b 00 05 00 05 01 00 |.........{......| 00000060 00 00 00 00 0a 00 0a 00 08 00 1d 00 17 00 18 00 |................| 00000070 19 00 0b 00 02 01 00 00 0d 00 1a 00 18 08 04 04 |................| 00000080 03 08 07 08 05 08 06 04 01 05 01 06 01 05 03 06 |................| @@ -14,11 +14,11 @@ 000000c0 ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 |._.).0..........| 000000d0 5f 58 cb 3b 74 |_X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 4e fb dc 04 6f |....Y...U..N...o| -00000010 5a 52 37 a3 55 58 26 e5 cd a0 67 4c 0f 87 1a 3a |ZR7.UX&...gL...:| -00000020 f6 84 33 2f 2e 52 d0 48 7c 5b 64 20 6e d0 bc ca |..3/.R.H|[d n...| -00000030 c9 a5 87 8d 99 c5 ec 85 84 89 f0 22 ab 63 55 f4 |...........".cU.| -00000040 70 d7 02 93 b5 fe d7 38 fb c1 b2 da cc a8 00 00 |p......8........| +00000000 16 03 03 00 59 02 00 00 55 03 03 2a 76 db 4b d5 |....Y...U..*v.K.| +00000010 10 f3 21 f2 4b 29 a2 2e 7a 7d 0b 86 c4 af 60 95 |..!.K)..z}....`.| +00000020 5b 11 84 27 8a 59 7f af a0 27 de 20 02 f7 dc 9b |[..'.Y...'. ....| +00000030 63 8e 2e da 48 b5 73 81 8e 76 13 da dd 2e 17 2b |c...H.s..v.....+| +00000040 ff 18 ad d7 9d f3 44 ed b6 60 0e 42 cc a8 00 00 |......D..`.B....| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -58,31 +58,31 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| -000002c0 ac 0c 00 00 a8 03 00 1d 20 fc 4b 92 ab d2 cb 4f |........ .K....O| -000002d0 61 aa 86 12 1a 1d 75 be 31 dd b8 ee 6c a6 db bd |a.....u.1...l...| -000002e0 0b ea b2 d5 27 49 42 eb 5a 08 04 00 80 02 ad 71 |....'IB.Z......q| -000002f0 e2 e8 f6 44 3c a6 18 6f 76 ee 9a eb 0e d9 ff cb |...D<..ov.......| -00000300 6d 1e 64 dd 29 1d 8c c8 f6 14 40 c0 12 46 74 4c |m.d.).....@..FtL| -00000310 41 2d 71 5f 9c b7 86 0b fc 66 1e 14 cb 26 d0 d7 |A-q_.....f...&..| -00000320 21 b4 bd c2 04 38 77 90 6a f0 01 18 bd 1c 17 45 |!....8w.j......E| -00000330 7e 38 46 4c 2e 97 ba 11 01 1f 20 cc df f2 6b 5b |~8FL...... ...k[| -00000340 a7 29 c0 52 52 9c 2f 23 bd 1c 72 c2 f2 99 d1 dc |.).RR./#..r.....| -00000350 6a 6c ac 8e 87 8a 00 74 47 2e 99 8d 3f 79 04 60 |jl.....tG...?y.`| -00000360 5e dc ba 86 1c f4 f9 03 22 38 96 a7 b3 16 03 03 |^......."8......| +000002c0 ac 0c 00 00 a8 03 00 1d 20 0d c3 c2 b5 73 da 39 |........ ....s.9| +000002d0 82 e5 8c 18 0d 8d 16 c2 a5 e7 3e 39 fd 25 00 18 |..........>9.%..| +000002e0 25 16 c0 a7 6e c6 dd bb 01 08 04 00 80 b3 bd 01 |%...n...........| +000002f0 ae dd b1 c8 2a 5d 0e 66 6d 1e b3 92 f4 01 63 59 |....*].fm.....cY| +00000300 0c c1 62 df 75 8f 4f 19 5a cf 2f 63 79 d0 06 31 |..b.u.O.Z./cy..1| +00000310 c0 60 6a 4f db 70 18 bd 80 8b 30 94 40 dd 13 39 |.`jO.p....0.@..9| +00000320 4f db 2b 54 a4 97 f7 ef a5 a3 ff f5 14 3d e2 2d |O.+T.........=.-| +00000330 0c 0e 71 4a bd a8 59 48 ab 06 55 53 45 2a ee 3e |..qJ..YH..USE*.>| +00000340 65 1f 47 ee 8d e3 f6 4e 2e b1 4c d0 af 50 15 02 |e.G....N..L..P..| +00000350 5e 84 fe 76 d5 f3 c5 fb 2a 91 44 f0 92 32 ee ea |^..v....*.D..2..| +00000360 a0 26 77 5c 94 88 24 e3 2f 75 e3 fd b7 16 03 03 |.&w\..$./u......| 00000370 00 04 0e 00 00 00 |......| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 0a 17 ee 70 8c 50 24 7c 00 b9 6f |.... ...p.P$|..o| -00000040 82 71 ed 2b 8c 0b 4b ff bb 38 bc 12 7e 0c a5 3e |.q.+..K..8..~..>| -00000050 71 a2 ad f8 52 |q...R| +00000030 16 03 03 00 20 0b 58 fe b5 63 ac 28 f8 34 d6 72 |.... .X..c.(.4.r| +00000040 1a a3 ec 26 91 70 07 8d 6a 3a 3b 3a 94 5e a3 fa |...&.p..j:;:.^..| +00000050 6e 92 3a 15 65 |n.:.e| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 e9 87 55 12 a8 |.......... ..U..| -00000010 ad 68 42 0c 60 12 be 2f 2c e5 00 2d 01 cf 86 a2 |.hB.`../,..-....| -00000020 1b 06 b3 86 bf 88 48 73 7a d3 cc |......Hsz..| +00000000 14 03 03 00 01 01 16 03 03 00 20 01 fa e1 2f 29 |.......... .../)| +00000010 ee f6 d4 e8 22 b6 e0 8f 82 37 81 83 1b 03 4d 5f |...."....7....M_| +00000020 00 80 cb eb 9a 3a 01 c7 aa e9 9a |.....:.....| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 96 75 4c c6 ba b1 ad ae 2f 44 9d |......uL...../D.| -00000010 10 c3 ef e5 dc fb 0a 3e af 6b 6a 15 03 03 00 12 |.......>.kj.....| -00000020 30 13 8f e5 a1 0f 38 67 b9 53 4e 6a 66 ec ee 45 |0.....8g.SNjf..E| -00000030 c2 b2 |..| +00000000 17 03 03 00 16 43 6a e8 f2 ca f9 4f 3c 6d ff 5e |.....Cj....O<m.^| +00000010 f3 19 eb ee 96 1c d8 68 c5 53 86 15 03 03 00 12 |.......h.S......| +00000020 c2 72 4e 3c 33 93 fa f3 21 32 bb fd e3 c4 ef 1a |.rN<3...!2......| +00000030 46 df |F.| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-Ed25519 b/libgo/go/crypto/tls/testdata/Client-TLSv12-Ed25519 index 35513ad..72d564f 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-Ed25519 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-Ed25519 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 66 49 2a a6 a4 |....Y...U..fI*..| -00000010 75 60 58 bb 5f 5e 82 cd e5 c0 9f 6d a4 fd 39 3b |u`X._^.....m..9;| -00000020 d9 17 80 14 89 ea 51 c1 b0 43 d6 20 b2 6b 72 81 |......Q..C. .kr.| -00000030 f6 63 20 22 e2 b6 d2 61 aa 87 b6 67 ae 56 78 44 |.c "...a...g.VxD| -00000040 5d 10 8c cf ea 32 cf 9e 92 e5 59 70 cc a9 00 00 |]....2....Yp....| +00000000 16 03 03 00 59 02 00 00 55 03 03 6c 5f 04 9e a6 |....Y...U..l_...| +00000010 c6 41 0c ee a2 2c af 45 f0 bc de 67 2d 20 1c 9c |.A...,.E...g- ..| +00000020 82 33 fd 86 86 b3 50 04 77 ec da 20 f3 09 fb 8c |.3....P.w.. ....| +00000030 79 83 f9 82 58 b9 76 bb d3 58 44 3d 52 0c 37 ae |y...X.v..XD=R.7.| +00000040 18 98 84 9a 56 af 5d 2b 68 68 c7 30 cc a9 00 00 |....V.]+hh.0....| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 01 3c 0b 00 01 38 00 01 35 00 01 32 30 82 01 |..<...8..5..20..| 00000070 2e 30 81 e1 a0 03 02 01 02 02 10 0f 43 1c 42 57 |.0..........C.BW| @@ -42,27 +42,27 @@ 00000170 90 95 39 e5 0d c1 55 ff 2c 16 b7 1d fc ab 7d 4d |..9...U.,.....}M| 00000180 d4 e0 93 13 d0 a9 42 e0 b6 6b fe 5d 67 48 d7 9f |......B..k.]gH..| 00000190 50 bc 6c cd 4b 03 83 7c f2 08 58 cd ac cf 0c 16 |P.l.K..|..X.....| -000001a0 03 03 00 6c 0c 00 00 68 03 00 1d 20 c4 8c b8 a2 |...l...h... ....| -000001b0 32 92 b8 22 1f 4c f1 96 00 64 35 47 4e f8 3d 08 |2..".L...d5GN.=.| -000001c0 83 12 fe 95 a8 e4 8e c9 30 27 5c 39 08 07 00 40 |........0'\9...@| -000001d0 7f 90 cf e0 87 69 e3 50 e6 fa 5e 28 a1 0f 79 0a |.....i.P..^(..y.| -000001e0 6e cf f4 87 e8 2f 55 b2 dd cb 5e 8f 9a 14 bd c2 |n..../U...^.....| -000001f0 2b 2b 2d ed 72 40 23 5d 6d f4 89 3a ff 09 82 ec |++-.r@#]m..:....| -00000200 b6 4b 27 9a 08 ea e9 73 94 b4 31 1f e1 39 86 0e |.K'....s..1..9..| +000001a0 03 03 00 6c 0c 00 00 68 03 00 1d 20 a7 28 ef 3e |...l...h... .(.>| +000001b0 1c 65 9f 8e 9a 80 0b 7d ac 9c ce d6 1e 97 54 30 |.e.....}......T0| +000001c0 53 9b e6 0c 61 e0 ea 9c ae 70 f2 78 08 07 00 40 |S...a....p.x...@| +000001d0 0c 49 38 23 a0 75 28 fb ec 71 a4 89 79 45 d1 ca |.I8#.u(..q..yE..| +000001e0 83 6f 5d dd 01 d4 c6 63 53 5d 6e 8f 06 09 80 a1 |.o]....cS]n.....| +000001f0 f7 ef af 2d 29 af aa 10 86 1c 18 19 3f be bb 90 |...-).......?...| +00000200 0e c3 9d 1e 6e 60 49 7f fc c8 42 61 89 c2 e3 04 |....n`I...Ba....| 00000210 16 03 03 00 04 0e 00 00 00 |.........| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 8f 97 36 bd 59 ef 8e 2f 11 28 b0 |.... ..6.Y../.(.| -00000040 d7 20 79 bf 04 07 45 f9 89 de b0 c7 55 1a ad 80 |. y...E.....U...| -00000050 0f 8c ef 1d c6 |.....| +00000030 16 03 03 00 20 b2 7f b6 1b 9c ec bf 2e ae a5 70 |.... ..........p| +00000040 d5 33 9b 63 02 66 77 7d 00 ec 86 e4 bb d4 57 68 |.3.c.fw}......Wh| +00000050 49 2a d3 be e7 |I*...| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 47 6c 1f 86 47 |.......... Gl..G| -00000010 72 03 94 e0 43 f8 e5 ca 03 7d f5 d5 dd 70 05 f5 |r...C....}...p..| -00000020 98 5d 51 b4 11 49 71 7a fd 37 9a |.]Q..Iqz.7.| +00000000 14 03 03 00 01 01 16 03 03 00 20 4c 7d ef ed ea |.......... L}...| +00000010 ab 8d 4f 38 46 6e 8f 56 b4 1d f2 1f 2c df 57 c0 |..O8Fn.V....,.W.| +00000020 f9 8a c2 71 f8 6d df b7 c7 1e 23 |...q.m....#| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 b7 a2 f5 8e 7c d3 7d 61 af 29 1c |.........|.}a.).| -00000010 77 0c 8d b4 5b d3 be 77 a6 a5 99 15 03 03 00 12 |w...[..w........| -00000020 d8 23 dc a8 99 fe 1c 6e f2 2f 41 8e df 40 11 4f |.#.....n./A..@.O| -00000030 6b 92 |k.| +00000000 17 03 03 00 16 26 f1 7c ee c8 3a 61 b0 f7 5a bd |.....&.|..:a..Z.| +00000010 b7 61 61 60 69 db cd ea 10 ee 63 15 03 03 00 12 |.aa`i.....c.....| +00000020 22 c0 65 a4 5d 0e 48 9c 56 f8 54 17 82 5f 29 97 |".e.].H.V.T.._).| +00000030 be 6b |.k| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ExportKeyingMaterial b/libgo/go/crypto/tls/testdata/Client-TLSv12-ExportKeyingMaterial index c900aa6..adf1f72 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ExportKeyingMaterial +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ExportKeyingMaterial @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 7c c1 7b 30 03 |....Y...U..|.{0.| -00000010 3c d7 63 5f 47 1c b1 13 56 56 b4 fd 55 e2 27 3e |<.c_G...VV..U.'>| -00000020 39 bb ce 9b 5b 2c 1e 17 33 e1 da 20 65 8b 26 42 |9...[,..3.. e.&B| -00000030 a4 38 29 c7 9a 25 13 fc 1d 69 cb 10 63 c6 26 fc |.8)..%...i..c.&.| -00000040 f4 46 64 31 28 06 b3 a5 a4 c2 f6 5a cc a8 00 00 |.Fd1(......Z....| +00000000 16 03 03 00 59 02 00 00 55 03 03 79 92 2e 86 bc |....Y...U..y....| +00000010 c0 b7 56 2a 25 58 75 b3 25 ac 58 1d 8d 8e d5 87 |..V*%Xu.%.X.....| +00000020 2d 67 8e 6e d4 d4 b6 67 b1 42 96 20 91 75 0b fa |-g.n...g.B. .u..| +00000030 d0 6f ab 91 4a c3 15 07 1d 6c 8e e5 55 f2 26 aa |.o..J....l..U.&.| +00000040 4d 5c 57 3b 93 a6 fc 46 c9 f6 80 1e cc a8 00 00 |M\W;...F........| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,31 +60,31 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| -000002c0 ac 0c 00 00 a8 03 00 1d 20 f7 a2 97 2f 50 e4 e2 |........ .../P..| -000002d0 fa ef 80 67 78 1c aa 6c 03 aa 05 3b 6f 98 97 11 |...gx..l...;o...| -000002e0 7e 55 3d 50 f3 a9 9b 21 65 08 04 00 80 34 4a 4b |~U=P...!e....4JK| -000002f0 4b 6e 86 01 1b 6b 8e 3e 84 01 75 b8 05 c3 b2 52 |Kn...k.>..u....R| -00000300 16 ee ac 61 83 dd 09 32 d5 55 6a 5d d6 6b 4a 1a |...a...2.Uj].kJ.| -00000310 2b f7 09 33 6f 3d 4f c1 e3 aa 03 27 fe af cd 6d |+..3o=O....'...m| -00000320 b8 76 00 02 42 98 e6 f6 b7 ed fb 35 35 29 23 b1 |.v..B......55)#.| -00000330 4d 48 0a ba a1 1b e3 8e a2 cb 80 11 ec 92 20 df |MH............ .| -00000340 1f a4 5e 5d 70 85 8e 5d 85 62 81 1f b3 3a 0d 8d |..^]p..].b...:..| -00000350 9a 07 d3 99 a5 3c 6c c2 52 08 f0 be 50 ed d2 4d |.....<l.R...P..M| -00000360 44 ed e7 40 06 64 4e 17 fe 4a 0e 1b d6 16 03 03 |D..@.dN..J......| +000002c0 ac 0c 00 00 a8 03 00 1d 20 5f 3c a6 bb 4e 32 85 |........ _<..N2.| +000002d0 69 4b 23 df 18 9c 07 ac 0b a8 dd 9b 59 33 00 02 |iK#.........Y3..| +000002e0 99 de 4e 66 1e 04 3b ce 4b 08 04 00 80 82 41 7c |..Nf..;.K.....A|| +000002f0 7b b8 ee d4 23 08 c3 23 8d b1 ea 27 43 e7 8e f1 |{...#..#...'C...| +00000300 7b 87 b0 88 ab f7 b1 15 2e 45 c5 50 e7 cd 05 31 |{........E.P...1| +00000310 bf 99 30 c8 ff 6a 23 ec 9d e5 c8 09 fa ec 50 a8 |..0..j#.......P.| +00000320 fa b3 54 b7 c5 61 99 f6 94 12 e6 34 4a 59 e3 dd |..T..a.....4JY..| +00000330 e5 7f f4 88 c9 2a 4c 09 65 d9 75 a6 ce 12 96 82 |.....*L.e.u.....| +00000340 a2 36 f2 5e 93 f2 4e 1c 05 91 a7 5a 67 36 e9 3d |.6.^..N....Zg6.=| +00000350 33 cd 6a 77 9c 8d 14 95 80 41 61 bd 80 ed 7b 51 |3.jw.....Aa...{Q| +00000360 cf 76 87 4d ac dc 5f c1 5d 52 a7 f9 51 16 03 03 |.v.M.._.]R..Q...| 00000370 00 04 0e 00 00 00 |......| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 30 8b ea ef 6c 35 97 5b 26 5f ef |.... 0...l5.[&_.| -00000040 bc 28 fd e9 23 73 bb b3 ae 41 0c be 5f 83 a5 f7 |.(..#s...A.._...| -00000050 96 07 8d 81 67 |....g| +00000030 16 03 03 00 20 bc c3 7c c2 cc a4 4e 8f d0 79 7a |.... ..|...N..yz| +00000040 a4 7d 4c 3d 17 8c 19 93 4f 49 03 50 f6 71 4d 16 |.}L=....OI.P.qM.| +00000050 97 bb 18 88 67 |....g| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 29 fa a8 de f2 |.......... )....| -00000010 8f 94 16 fc be 84 93 e9 34 98 c2 44 08 9b 2e 37 |........4..D...7| -00000020 1f 41 61 53 fa 9c 23 ff d8 6d c3 |.AaS..#..m.| +00000000 14 03 03 00 01 01 16 03 03 00 20 00 c4 8a f9 1e |.......... .....| +00000010 c0 66 ab ef 39 ae 41 7a 05 9c e3 06 e4 4d 00 bb |.f..9.Az.....M..| +00000020 d4 ef 21 71 a3 54 23 fe db 4a 86 |..!q.T#..J.| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 ab 6d 32 1c 16 cc 29 b1 21 4c b1 |......m2...).!L.| -00000010 74 4c 50 e3 1f c5 f1 05 6a 8a 92 15 03 03 00 12 |tLP.....j.......| -00000020 18 88 3d 23 81 d7 ba c5 1e 9a c4 3a 1b c8 cd 5b |..=#.......:...[| -00000030 c5 fa |..| +00000000 17 03 03 00 16 0c d3 9a f5 1d f4 5f b2 45 c7 7c |..........._.E.|| +00000010 38 59 6e df 6e 59 d5 94 8b a9 bb 15 03 03 00 12 |8Yn.nY..........| +00000020 9e 74 a5 0e c1 7f 33 52 be 17 f6 f5 4d 9f 3d d1 |.t....3R....M.=.| +00000030 b5 65 |.e| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-P256-ECDHE b/libgo/go/crypto/tls/testdata/Client-TLSv12-P256-ECDHE index d75b670..3331435 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-P256-ECDHE +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-P256-ECDHE @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 96 00 05 00 05 01 00 00 00 00 00 0a 00 |................| 00000090 04 00 02 00 17 00 0b 00 02 01 00 00 0d 00 1a 00 |................| 000000a0 18 08 04 04 03 08 07 08 05 08 06 04 01 05 01 06 |................| @@ -18,11 +18,11 @@ 00000100 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 |..lK[.V.2B.X..I.| 00000110 b5 68 1a 41 03 56 6b dc 5a 89 |.h.A.Vk.Z.| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 b8 7d f5 69 c3 |....Y...U...}.i.| -00000010 6a ca 8b df f3 30 2c 39 47 2e 74 2e 4f 89 4c 1e |j....0,9G.t.O.L.| -00000020 f0 eb 10 0e 06 1d 2c 4e de 2e 8f 20 6c a0 5b 66 |......,N... l.[f| -00000030 fc a6 05 df 29 6b ce 72 92 e7 d7 78 f5 46 38 f9 |....)k.r...x.F8.| -00000040 91 1c 9a 08 4c b1 9a 41 e5 0c d2 cd c0 2f 00 00 |....L..A...../..| +00000000 16 03 03 00 59 02 00 00 55 03 03 0b f0 3e a1 66 |....Y...U....>.f| +00000010 13 35 53 83 59 3c 9e 2a 0f 0b b0 9a 42 de e4 f1 |.5S.Y<.*....B...| +00000020 8a 2d 34 ef 15 fe 28 55 42 d8 bf 20 aa 27 5c 5f |.-4...(UB.. .'\_| +00000030 24 59 17 ef 43 f3 18 f8 40 97 8f 1a 6a f4 e4 4a |$Y..C...@...j..J| +00000040 a3 b7 11 39 01 bd 98 8c 61 08 d9 50 c0 2f 00 00 |...9....a..P./..| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -62,19 +62,19 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| -000002c0 cd 0c 00 00 c9 03 00 17 41 04 3e 87 67 8b 87 08 |........A.>.g...| -000002d0 fe 4e 4c c3 6b 42 4b 97 ad f4 1c 83 35 72 db 4f |.NL.kBK.....5r.O| -000002e0 39 83 ea 14 69 bb 8c 87 58 c5 a4 a8 8c d7 9d af |9...i...X.......| -000002f0 7a 5e 58 59 31 4d f2 01 4a 23 51 24 1b 04 0c e3 |z^XY1M..J#Q$....| -00000300 94 9e 1b 6c ad aa 83 fd 2d 36 08 04 00 80 ab e9 |...l....-6......| -00000310 ff 6d 7a cd 3b a7 da ff d5 bd 27 49 68 53 f5 45 |.mz.;.....'IhS.E| -00000320 c3 dd 5b a2 99 fb 8f 24 37 49 d3 08 87 d1 06 98 |..[....$7I......| -00000330 39 72 25 78 b3 05 fb a2 c9 ac f9 c8 f7 fc ea 8a |9r%x............| -00000340 98 ce 78 83 64 f6 e0 c7 44 62 af a7 d5 26 df f1 |..x.d...Db...&..| -00000350 2c cc ce 11 8b 03 4a e1 81 54 3f e1 6e 52 c9 1a |,.....J..T?.nR..| -00000360 d8 95 52 e0 3f a5 e3 c8 12 9a c7 57 5d 46 7a ce |..R.?......W]Fz.| -00000370 56 8a 90 0f 0d 1b ba 58 cf 1c a3 4b 39 5a 08 ee |V......X...K9Z..| -00000380 8a 61 bb 0f 7d f7 0e f2 1f 73 e0 c8 6f 54 16 03 |.a..}....s..oT..| +000002c0 cd 0c 00 00 c9 03 00 17 41 04 79 6a df 70 26 49 |........A.yj.p&I| +000002d0 c0 5a 39 fc 7c 80 d1 2c cd 76 d0 4c 6f a7 7d bc |.Z9.|..,.v.Lo.}.| +000002e0 32 c6 54 c6 76 58 e2 0f 3f 33 ad 92 61 33 11 16 |2.T.vX..?3..a3..| +000002f0 d7 42 a8 ba 2a 8f 22 2a eb 88 3e 74 78 2a 67 de |.B..*."*..>tx*g.| +00000300 39 75 63 2c 1d 2e da 33 77 a5 08 04 00 80 61 f5 |9uc,...3w.....a.| +00000310 ed 56 5b f1 dd 78 a0 c4 8a 9b ac 28 c5 91 0c bd |.V[..x.....(....| +00000320 f1 d5 c1 f6 31 2e 8c c3 d5 84 3a 15 e8 6d f1 bc |....1.....:..m..| +00000330 9e a6 04 fd 95 2f 51 60 2f c6 ff 99 cf 38 24 bf |...../Q`/....8$.| +00000340 a4 32 a2 1f a1 6b bd 27 98 00 14 23 0d 12 66 67 |.2...k.'...#..fg| +00000350 48 33 92 51 e7 e7 3c f5 ef 13 ca 46 3c 39 53 70 |H3.Q..<....F<9Sp| +00000360 41 78 4a 02 70 87 48 ce b0 31 02 33 0b 06 78 b9 |AxJ.p.H..1.3..x.| +00000370 87 0b 07 e0 f7 15 c8 3e 27 a1 a3 20 24 9e 20 93 |.......>'.. $. .| +00000380 7f b5 53 7b 18 88 96 87 2b df 02 ba 0c d8 16 03 |..S{....+.......| 00000390 03 00 04 0e 00 00 00 |.......| >>> Flow 3 (client to server) 00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..| @@ -82,17 +82,17 @@ 00000020 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.| 00000030 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I| 00000040 a6 b5 68 1a 41 03 56 6b dc 5a 89 14 03 03 00 01 |..h.A.Vk.Z......| -00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 b8 16 |.....(..........| -00000060 ce 7d df 64 13 07 9e d8 37 bb 3f 9c 9e 2b 3c 0e |.}.d....7.?..+<.| -00000070 26 a7 9d 32 e5 44 b8 d6 66 bc 05 7b 27 7a |&..2.D..f..{'z| +00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 c1 90 |.....(..........| +00000060 a0 8b 53 87 a8 e3 56 4c 5c ad 5f dc 00 af 29 5f |..S...VL\._...)_| +00000070 11 53 7d 49 25 f8 74 16 dc 84 5f 3b c6 24 |.S}I%.t..._;.$| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 c0 73 5c 27 1b |..........(.s\'.| -00000010 19 d0 66 68 ea c5 ad 7d a8 03 37 d2 9a ff 00 c4 |..fh...}..7.....| -00000020 70 65 98 3b 88 59 c0 ca e3 c0 d6 32 0e 8d 15 3c |pe.;.Y.....2...<| -00000030 e2 c3 f3 |...| +00000000 14 03 03 00 01 01 16 03 03 00 28 00 f9 b2 51 85 |..........(...Q.| +00000010 72 7e ec 79 72 59 90 ae 69 51 79 61 10 3b 4e 4b |r~.yrY..iQya.;NK| +00000020 45 d6 a5 9a c0 1a 69 c9 9f 1c ee cd ad 6a e8 ea |E.....i......j..| +00000030 c4 9e f1 |...| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 28 ef 47 |.............(.G| -00000010 ad 7f 40 4b 34 78 f3 1e 01 a7 f4 20 0a d5 c1 41 |..@K4x..... ...A| -00000020 f7 be 41 15 03 03 00 1a 00 00 00 00 00 00 00 02 |..A.............| -00000030 fb fc eb 14 f2 a6 e7 2e 80 d6 93 31 25 01 e9 d2 |...........1%...| -00000040 c3 ae |..| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 86 5a 45 |..............ZE| +00000010 24 60 90 dc bc b3 f6 61 6f db 60 02 99 f9 e2 93 |$`.....ao.`.....| +00000020 07 85 0d 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................| +00000030 36 86 b0 60 b5 5d dd 28 64 c6 5b c7 ed 01 07 b1 |6..`.].(d.[.....| +00000040 12 39 |.9| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4 b/libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4 index ab2c4eb..12fb594 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 51 02 00 00 4d 03 03 34 50 1f 52 15 |....Q...M..4P.R.| -00000010 85 c7 85 2c 4d a9 b2 0c 49 e5 a3 ea 57 21 96 39 |...,M...I...W!.9| -00000020 db c9 97 b6 c4 d0 81 9a 39 a3 e8 20 59 f5 b9 db |........9.. Y...| -00000030 58 2e ef 1c b3 85 96 27 6a 23 71 3f 5c 72 ce cf |X......'j#q?\r..| -00000040 c5 b7 fe 05 00 f4 65 06 54 c1 2e 7c 00 05 00 00 |......e.T..|....| +00000000 16 03 03 00 51 02 00 00 4d 03 03 b0 e7 ee 09 45 |....Q...M......E| +00000010 36 f1 7a 92 be 9e d8 9d ae cd c1 4e b2 12 94 3e |6.z........N...>| +00000020 6c 34 71 ed 5f e0 97 7f 25 e4 dd 20 f4 43 01 03 |l4q._...%.. .C..| +00000030 88 33 26 7f 48 c1 f2 d1 4d d3 f8 1a bd 86 4c 50 |.3&.H...M.....LP| +00000040 18 89 dc 08 99 f1 51 c5 84 be b9 fd 00 05 00 00 |......Q.........| 00000050 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.| 00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......| 00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..| @@ -70,15 +70,15 @@ 00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..| 00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..| 00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 03 00 01 |.Y(.....ia5.....| -00000090 01 16 03 03 00 24 ab 48 84 ae 77 f9 8b 82 44 52 |.....$.H..w...DR| -000000a0 3e 65 94 27 cc f2 08 a7 f2 e5 21 0c 02 d0 89 ac |>e.'......!.....| -000000b0 50 be 69 57 c9 7c a0 f2 7f 6d |P.iW.|...m| +00000090 01 16 03 03 00 24 08 65 01 80 0d 59 b8 ac 0f 09 |.....$.e...Y....| +000000a0 bf 61 31 32 e0 74 e9 f4 72 e3 2c 79 11 4d b2 a2 |.a12.t..r.,y.M..| +000000b0 55 65 94 c8 cd 0a 61 99 07 b8 |Ue....a...| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 24 61 94 21 65 0f |..........$a.!e.| -00000010 10 ba 0c a6 d9 e3 08 54 86 ae f9 64 c7 e7 f4 4b |.......T...d...K| -00000020 aa f5 19 ca 2a 0d 50 88 85 42 32 14 04 29 d9 |....*.P..B2..).| +00000000 14 03 03 00 01 01 16 03 03 00 24 04 20 46 cd fb |..........$. F..| +00000010 6c 46 9c 47 21 03 fe 9b a4 c6 da 2c 71 2f db 92 |lF.G!......,q/..| +00000020 40 da 7d 46 2e e4 9c 81 86 89 7f 53 46 91 28 |@.}F.......SF.(| >>> Flow 5 (client to server) -00000000 17 03 03 00 1a cb 1d 43 67 de 7a 20 c7 ed 46 99 |.......Cg.z ..F.| -00000010 86 1f b9 61 9f c6 34 9a 07 37 3c 94 45 b4 40 15 |...a..4..7<.E.@.| -00000020 03 03 00 16 4e ac d3 12 23 b4 33 bc 5b 03 91 7e |....N...#.3.[..~| -00000030 d9 d0 7f d7 48 3e 8c 16 16 ec |....H>....| +00000000 17 03 03 00 1a 89 2b 2e 49 21 19 b7 d0 df 85 da |......+.I!......| +00000010 b8 a7 f3 73 5f fe 44 e5 0c a1 af 16 74 93 bc 15 |...s_.D.....t...| +00000020 03 03 00 16 5f 9e 64 d0 91 50 34 44 cf f6 1f e0 |...._.d..P4D....| +00000030 e0 13 b9 67 da 5c 99 16 f1 b3 |...g.\....| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce index 48a99ed..06752de 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 f1 d8 72 0c 79 |....Y...U....r.y| -00000010 e2 ca 92 11 1c 30 cc 45 00 9b ea 3d a3 ed 23 d5 |.....0.E...=..#.| -00000020 22 f0 da 9c 03 32 7b c3 13 d3 df 20 8f 7a 61 43 |"....2{.... .zaC| -00000030 cb 72 46 5e c1 39 78 42 32 97 cc 2b 90 2e 53 59 |.rF^.9xB2..+..SY| -00000040 31 38 ec 7b 2b 8a f3 80 e0 03 f0 0e cc a8 00 00 |18.{+...........| +00000000 16 03 03 00 59 02 00 00 55 03 03 5b 4b bb c4 39 |....Y...U..[K..9| +00000010 fb 45 5c 54 03 30 0f 71 c3 2e 48 25 33 fd 6d 40 |.E\T.0.q..H%3.m@| +00000020 18 6e 75 43 66 9e 08 fb 6a a1 f8 20 34 3c c4 2a |.nuCf...j.. 4<.*| +00000030 b5 9b 65 b0 cd b9 fc ce cf 51 f8 cc a1 5d 00 ed |..e......Q...]..| +00000040 49 5b 43 9a ff c4 cf 6b d8 2a ea e5 cc a8 00 00 |I[C....k.*......| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,185 +60,185 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| -000002c0 ac 0c 00 00 a8 03 00 1d 20 96 cb 1d cd f6 2f ff |........ ...../.| -000002d0 fe 32 ef d6 18 a2 6b 57 66 cd 3d 50 42 56 dc a4 |.2....kWf.=PBV..| -000002e0 5f fe e4 91 ce d1 17 34 3c 08 04 00 80 b1 47 de |_......4<.....G.| -000002f0 b3 19 b0 fd 02 35 eb 3c a1 04 d3 6b 53 84 20 c7 |.....5.<...kS. .| -00000300 08 4b 96 12 23 ae bf ca a8 83 1d 90 16 ae d3 7c |.K..#..........|| -00000310 fa 1b b4 f0 bb bb 4e 3f 70 13 2f 40 6c d4 76 61 |......N?p./@l.va| -00000320 5b 23 85 3f e7 37 ef e1 55 47 8d 01 e1 24 22 7f |[#.?.7..UG...$".| -00000330 a4 2c 6f 97 47 5f d6 69 bf b4 db 4b b8 a1 ad 66 |.,o.G_.i...K...f| -00000340 5f d5 5d b6 06 ac 93 ed d7 06 cb b5 a4 d4 4b a7 |_.]...........K.| -00000350 7b de f7 73 60 af ad 23 f4 6a f1 bf 2a ee 5b 4e |{..s`..#.j..*.[N| -00000360 83 94 d7 95 3b e5 5e a5 3d 1a 0a 7a 9e 16 03 03 |....;.^.=..z....| +000002c0 ac 0c 00 00 a8 03 00 1d 20 76 c4 f4 ec a2 d6 c1 |........ v......| +000002d0 b1 d8 b0 41 71 8a ee e9 8a 17 06 90 6b 0c 05 66 |...Aq.......k..f| +000002e0 54 d8 a6 ad 50 95 11 f0 03 08 04 00 80 46 0b da |T...P........F..| +000002f0 0b 0c 6c 1a 2e a2 7e 28 40 1b 40 9a b4 5c 36 88 |..l...~(@.@..\6.| +00000300 c1 ad cd 45 be 23 17 a6 98 e5 11 fe a8 78 c6 21 |...E.#.......x.!| +00000310 17 a6 a8 7d ce 28 c4 ef 51 76 f8 b1 b1 75 31 04 |...}.(..Qv...u1.| +00000320 b9 14 bc 3b bf 59 50 b8 e1 ad c6 86 45 3c e1 70 |...;.YP.....E<.p| +00000330 fb cd 69 8c 0a 5f f6 2d bd 10 95 30 ed 4c 9a 47 |..i.._.-...0.L.G| +00000340 73 8b 39 72 00 0a 7e 8f a9 42 27 01 6f 3d 37 f9 |s.9r..~..B'.o=7.| +00000350 7d d4 1b a2 6a 07 37 dc 5e 6c 8b b1 d5 75 3a 9b |}...j.7.^l...u:.| +00000360 d1 45 c5 d8 e0 90 f0 62 3d d5 01 00 9e 16 03 03 |.E.....b=.......| 00000370 00 04 0e 00 00 00 |......| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 f2 6f 2e 79 5c db 90 b8 2e cf 59 |.... .o.y\.....Y| -00000040 0a 56 69 86 f1 71 0c ff a9 7c 0b a0 e7 c9 8d 17 |.Vi..q...|......| -00000050 65 ad a5 6c 82 |e..l.| +00000030 16 03 03 00 20 bb f4 78 64 23 f7 31 50 42 3d 97 |.... ..xd#.1PB=.| +00000040 8f 73 89 b9 90 8f 74 b6 e4 7d 58 27 65 25 59 8a |.s....t..}X'e%Y.| +00000050 5a 8d 8f fa bd |Z....| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 d5 90 08 84 71 |.......... ....q| -00000010 bc 09 48 be ad 59 11 76 c6 39 bb 94 8c 60 80 29 |..H..Y.v.9...`.)| -00000020 44 1a 0d fe 5c 00 4c bc 47 3c 1e |D...\.L.G<.| +00000000 14 03 03 00 01 01 16 03 03 00 20 0a 43 74 53 47 |.......... .CtSG| +00000010 41 4b 0a f1 f7 75 51 a9 22 c9 e0 5c 53 90 6b d7 |AK...uQ."..\S.k.| +00000020 97 18 c6 ef c3 85 32 f5 7c 26 97 |......2.|&.| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 42 cd 1c e5 91 35 b0 c1 4d df e4 |.....B....5..M..| -00000010 b0 ca f3 8a 7a 41 85 31 7a 7d 59 |....zA.1z}Y| +00000000 17 03 03 00 16 8e 83 1a 32 53 02 1c fa 84 89 4f |........2S.....O| +00000010 25 fb 5f 85 4f bd ee ae 9f 0f ea |%._.O......| >>> Flow 6 (server to client) -00000000 16 03 03 00 14 3b 0f 40 64 9f ff 8f b9 85 18 af |.....;.@d.......| -00000010 b4 bc e7 33 8a 9b 03 de ed |...3.....| +00000000 16 03 03 00 14 96 76 32 c4 6d e6 23 bf 21 a8 09 |......v2.m.#.!..| +00000010 a3 8b 69 98 cd c3 c9 ce 73 |..i.....s| >>> Flow 7 (client to server) -00000000 16 03 03 01 16 17 a7 61 5b 22 97 6e eb dd 43 84 |.......a[".n..C.| -00000010 b9 ac 15 c2 76 7d 1f c0 e3 46 11 af c0 59 7d cc |....v}...F...Y}.| -00000020 d4 5d 02 90 28 bb b3 7c 85 76 46 34 7c bf 2b bf |.]..(..|.vF4|.+.| -00000030 c4 e9 e1 46 b0 15 7e af c1 03 4a 17 b3 7a 03 cd |...F..~...J..z..| -00000040 e0 90 b1 1b 59 ac 1f 33 b0 41 c3 47 ee 58 af 5b |....Y..3.A.G.X.[| -00000050 5b c4 7a 92 02 e2 34 8d cd 70 20 c4 59 5e 25 f2 |[.z...4..p .Y^%.| -00000060 28 b1 f2 a5 e0 c4 f9 d0 ae cc 2b 1e ea d4 5a fe |(.........+...Z.| -00000070 62 97 bc d7 57 94 5c b8 ce 4c 62 1a e5 29 02 1e |b...W.\..Lb..)..| -00000080 0e 68 1d 8a 17 f9 47 55 ac 65 cf 13 88 d3 95 0d |.h....GU.e......| -00000090 d7 e0 d8 03 f8 f6 6f 9c 5b de 5c 80 c3 34 7e 82 |......o.[.\..4~.| -000000a0 5c 8b c4 a3 99 c8 1e f0 f2 e5 6e 73 40 62 31 8e |\.........ns@b1.| -000000b0 3b 08 62 ba a8 b9 18 c4 84 a0 b4 9f 68 81 2f ae |;.b.........h./.| -000000c0 8d 7c cc 54 ba 4a ec 26 a5 8a 9b a7 bd 36 17 2c |.|.T.J.&.....6.,| -000000d0 52 69 4c 57 81 64 e6 34 88 27 81 d2 32 eb d2 8d |RiLW.d.4.'..2...| -000000e0 4d 8d c1 8b 14 b3 07 19 63 f8 d6 4a 9a 7d 3f c1 |M.......c..J.}?.| -000000f0 af 18 72 f7 2d c8 7e 82 52 28 51 80 59 0c 9b 9f |..r.-.~.R(Q.Y...| -00000100 ac 40 69 25 0e 6d d7 4a 72 b5 18 f8 78 b9 52 c3 |.@i%.m.Jr...x.R.| -00000110 d6 32 6c 7d 29 70 a8 33 18 d0 4b |.2l})p.3..K| +00000000 16 03 03 01 16 72 5b d9 30 b2 b0 91 e2 3d 2b 12 |.....r[.0....=+.| +00000010 2c c9 43 f1 67 ae 54 ee ce a1 15 12 12 9a 27 46 |,.C.g.T.......'F| +00000020 7e 47 90 d4 f2 7d b9 98 ec f8 61 b8 84 52 9f 21 |~G...}....a..R.!| +00000030 c1 83 6a ce 1a 68 fc 5b 25 42 f3 8f 55 ee 92 45 |..j..h.[%B..U..E| +00000040 af a4 d1 c4 a6 b5 0e 58 3d 70 76 98 ec 47 af 6f |.......X=pv..G.o| +00000050 e3 4f 9f ef 52 a3 aa 33 75 83 f6 57 33 a8 dc f5 |.O..R..3u..W3...| +00000060 36 49 09 1c 72 31 c1 43 52 64 4a b5 ca ce 06 f5 |6I..r1.CRdJ.....| +00000070 91 18 90 85 f0 c9 96 4f bf 4c de 9e 50 a2 1c de |.......O.L..P...| +00000080 86 51 1f 0b 73 e1 df 1d 2d 90 6d 7f a2 f1 28 e8 |.Q..s...-.m...(.| +00000090 5f 2a 78 2d 8e ab f2 05 19 85 4e 92 a8 cf cd 16 |_*x-......N.....| +000000a0 1e df 1d 51 ee 8b ba 72 cd ac d2 01 4b 84 46 62 |...Q...r....K.Fb| +000000b0 1c 28 4d 3f 44 c1 62 12 13 4f f8 73 f4 da c0 98 |.(M?D.b..O.s....| +000000c0 14 da 31 6a 48 0d 1d bb 24 6c ef 0f 98 c0 3c 86 |..1jH...$l....<.| +000000d0 c6 d6 8e ab bd 20 bd 06 e9 ba aa ce 3a 88 25 95 |..... ......:.%.| +000000e0 54 15 fb c6 49 c7 98 ff 27 92 c0 60 6a 3c f8 26 |T...I...'..`j<.&| +000000f0 fd 28 ac c4 8f 5c 4f 15 24 10 45 3c 07 3d 3f 50 |.(...\O.$.E<.=?P| +00000100 e5 db cf 78 bd b0 d2 24 a2 4b 3e a6 9c 2d 3b 0d |...x...$.K>..-;.| +00000110 d8 1b 86 88 dc 0c 3c 9c 16 cf ea |......<....| >>> Flow 8 (server to client) -00000000 16 03 03 00 81 8b e2 a1 f5 15 55 13 f6 f2 fa 95 |..........U.....| -00000010 3b bb 0f 3d 3e 9b 3c b1 60 cb 69 7f 63 62 2d 9b |;..=>.<.`.i.cb-.| -00000020 20 47 3a 7d 5e d0 98 38 49 c3 94 f8 1d 56 1d 69 | G:}^..8I....V.i| -00000030 27 65 bc ca 63 22 65 61 60 67 49 35 f0 eb 83 1b |'e..c"ea`gI5....| -00000040 44 c4 f0 91 64 5a 81 b5 06 4b 3e 3a ef 3b 5c b0 |D...dZ...K>:.;\.| -00000050 81 b4 36 df f3 0d a3 0a 1c 40 03 fa 81 48 42 70 |..6......@...HBp| -00000060 bf 4c b3 6b 67 19 7b 83 05 a1 31 a3 1c 79 49 2c |.L.kg.{...1..yI,| -00000070 1f 58 bc 7d 98 4e 5b 64 44 3d 3c 43 fb 77 c7 7c |.X.}.N[dD=<C.w.|| -00000080 65 aa 0a 3d 49 a1 16 03 03 02 69 de 2a 3b 96 9f |e..=I.....i.*;..| -00000090 21 b4 5d de 2b b6 c5 03 ec ab 79 35 eb da 8b 1f |!.].+.....y5....| -000000a0 f8 c4 58 7c d1 af 3d 6e f9 73 63 2b dc 2e a5 4f |..X|..=n.sc+...O| -000000b0 88 93 24 5e d7 2a ab 0a a5 0f bf 5d 2d 74 9c 19 |..$^.*.....]-t..| -000000c0 3a 97 88 f7 17 25 ad 6a 81 3a f1 e3 bb 4c 7a b6 |:....%.j.:...Lz.| -000000d0 4c b0 f3 25 e5 66 06 14 b0 a3 3d 3a 25 36 4c e1 |L..%.f....=:%6L.| -000000e0 62 25 fc ac 22 7b 25 0d f9 5f 5b a6 1b 7f b9 14 |b%.."{%.._[.....| -000000f0 4d 71 81 6b de 9d 6a 40 80 ba 88 20 60 c6 e2 50 |Mq.k..j@... `..P| -00000100 c6 a6 3d 01 ee 04 dc ad 3c 95 a7 ef a7 dd 3a 6c |..=.....<.....:l| -00000110 0f f2 c2 c2 e0 fc 3c d2 75 88 ad 1a 23 94 2a 69 |......<.u...#.*i| -00000120 28 66 c2 8a 5c 34 69 da cc 5d 13 dd 86 fc 66 13 |(f..\4i..]....f.| -00000130 de c2 c6 86 6d 4a b4 ea b0 99 61 38 72 1e 7f 36 |....mJ....a8r..6| -00000140 df 32 4b a7 12 23 8f f3 d1 8d d7 2f d1 65 67 4f |.2K..#...../.egO| -00000150 10 07 03 6a b2 87 aa a4 b0 41 c9 20 f4 84 5e b7 |...j.....A. ..^.| -00000160 5e 4d 47 d4 7f 6c 8d 2e a5 bb 7d 07 1b 5b e5 50 |^MG..l....}..[.P| -00000170 5d 27 c0 8b f8 5e a7 a8 ef d7 f3 b0 6d 07 7a 9b |]'...^......m.z.| -00000180 1d 54 5a 18 c7 4f 6f b8 92 44 16 ec 92 43 1a 1a |.TZ..Oo..D...C..| -00000190 a8 d0 a3 40 25 b0 ff 35 9c b7 4c f9 cd 06 59 a6 |...@%..5..L...Y.| -000001a0 25 ca 4a b7 34 31 0a 23 29 3a 09 8b 7b 05 15 b0 |%.J.41.#):..{...| -000001b0 67 ae 1b 8b f4 67 16 e0 c1 67 a1 58 09 c9 10 f0 |g....g...g.X....| -000001c0 f0 62 02 52 14 6d 02 3d e6 ab 16 fb 7f 38 69 7c |.b.R.m.=.....8i|| -000001d0 d1 f3 db 69 3c cd 78 28 b2 fa 94 1c a0 2f b7 bb |...i<.x(...../..| -000001e0 31 4f f6 56 2a 98 5a d1 bf 5d e4 0d ec 8f 47 42 |1O.V*.Z..]....GB| -000001f0 62 a6 59 39 77 d8 bd 11 71 64 b4 2b 65 2a 10 5d |b.Y9w...qd.+e*.]| -00000200 46 51 bf 8d b6 13 df 61 b8 1e 37 ad fc c0 86 a9 |FQ.....a..7.....| -00000210 b4 09 2f 33 8e 93 4a 5b 32 f4 f9 7d 01 a8 b8 09 |../3..J[2..}....| -00000220 8e da 90 8f a7 fb 82 76 fd 6b 7e 93 57 13 e1 99 |.......v.k~.W...| -00000230 cb b8 12 0a da c2 62 0e 0c 65 53 d4 5b 75 c2 22 |......b..eS.[u."| -00000240 3f 91 5c e6 c4 12 48 78 c4 6d 2c 1f 45 dc a2 a1 |?.\...Hx.m,.E...| -00000250 73 cf 69 97 8b 64 42 d5 22 06 de 04 4b 8c f5 5f |s.i..dB."...K.._| -00000260 d6 97 1a 73 4f 4e d2 55 e1 8d 8c 21 fd 7f 26 1c |...sON.U...!..&.| -00000270 53 9f 69 c9 01 11 be 4e d0 ab 78 56 af bb 0a 0f |S.i....N..xV....| -00000280 73 cb c5 d2 07 4a 16 a0 71 9f dd 46 17 0e 86 5e |s....J..q..F...^| -00000290 e2 90 34 7d af b1 86 6c e3 33 cf ff 2f bf ea 8e |..4}...l.3../...| -000002a0 62 7e 7f b9 f7 c4 1b 4c 61 b6 8d 6f a9 b4 56 27 |b~.....La..o..V'| -000002b0 0a 0d fa d7 d9 ce 6a 1a e3 4e 4d f8 04 c8 74 75 |......j..NM...tu| -000002c0 07 6f 38 96 c7 04 df a4 e0 6a 08 c5 5b 93 b7 c1 |.o8......j..[...| -000002d0 fb 4d 4f 01 67 3c 8b 03 93 f7 46 c2 db 2f 41 2d |.MO.g<....F../A-| -000002e0 e1 d6 dd 39 d5 0c dc 6a 10 c2 50 fe 34 64 79 9a |...9...j..P.4dy.| -000002f0 5e 88 35 89 16 03 03 00 bc d1 42 6c 11 23 45 dd |^.5.......Bl.#E.| -00000300 41 9e 81 0a 3d d1 c1 99 6f 91 b5 16 96 e6 d3 eb |A...=...o.......| -00000310 9b 8f c3 30 14 7f 19 d5 9a fa ea 9c de 53 23 7c |...0.........S#|| -00000320 d8 49 d2 c5 e7 7c ff 96 22 0a 57 fc 11 ed b9 ca |.I...|..".W.....| -00000330 2e 18 a5 30 7e 3a d2 86 70 de 48 28 83 a1 3b 65 |...0~:..p.H(..;e| -00000340 67 b9 2e 89 87 92 0e eb b5 70 1d 36 7b 98 4b 8e |g........p.6{.K.| -00000350 12 49 db 85 18 dc e1 f4 51 a9 bb e4 5c ae 56 31 |.I......Q...\.V1| -00000360 c1 56 84 bb e5 42 ec d1 41 e7 a7 4e 08 d7 5f 1d |.V...B..A..N.._.| -00000370 67 9a ed 10 b6 80 ff ea 36 70 ac a0 a9 ec 4a e3 |g.......6p....J.| -00000380 37 ae bf f3 bd a9 aa 3f b0 14 f6 0b 05 18 09 dd |7......?........| -00000390 29 b4 97 55 88 24 59 ce 5b 42 e2 b5 1f 04 76 f3 |)..U.$Y.[B....v.| -000003a0 f1 c0 49 7d 47 ef 5e 6c c3 ed 30 2c a0 a1 df c6 |..I}G.^l..0,....| -000003b0 12 13 22 8b 65 16 03 03 00 4a 3e 6c f8 63 5b 93 |..".e....J>l.c[.| -000003c0 f0 c6 3a 58 e0 6c 6b 70 46 d0 be 6f 13 34 7a 30 |..:X.lkpF..o.4z0| -000003d0 e6 e4 b2 fd 39 ee 79 b1 7e 73 5e 9b 2d d9 3f 4f |....9.y.~s^.-.?O| -000003e0 61 d5 53 37 79 57 15 a3 3a 7c b7 02 cc 76 25 1d |a.S7yW..:|...v%.| -000003f0 96 8b dd 9e 32 8b 1a 9e 37 b1 1a b8 f2 4f ef 3c |....2...7....O.<| -00000400 78 e1 b9 07 16 03 03 00 14 bf da c1 d4 16 fd 48 |x..............H| -00000410 a9 ad 59 6d 8c dc e1 6c fd 73 ca 9c 1b |..Ym...l.s...| +00000000 16 03 03 00 81 2e c9 cd ad df 75 cf b6 8d 7f 8c |..........u.....| +00000010 c6 bb 5b e6 2b 40 a0 36 45 13 ae 93 f1 04 bf f3 |..[.+@.6E.......| +00000020 62 bd c8 62 d9 cf 05 a3 4c e9 37 af 35 a6 83 8e |b..b....L.7.5...| +00000030 71 46 b8 2a 5b 02 3b 81 d5 15 b8 17 72 c4 1e 00 |qF.*[.;.....r...| +00000040 78 d9 4a 04 a7 b3 5b 80 bd 1f 88 ba fa 22 b5 0e |x.J...[......"..| +00000050 ca 44 55 27 c0 67 ce 37 4c 9a 9a d7 77 da 58 35 |.DU'.g.7L...w.X5| +00000060 83 b3 39 90 8d e2 7f 08 2e cc 5a 8e 5e a8 c3 bb |..9.......Z.^...| +00000070 db e5 a2 56 56 04 37 13 f3 b1 71 2d ea 0a 56 00 |...VV.7...q-..V.| +00000080 6e 8d 8b 20 79 30 16 03 03 02 69 76 4b a4 c6 5e |n.. y0....ivK..^| +00000090 0a a2 3c 89 24 f6 93 94 25 4e 0b 8a d2 33 2f 03 |..<.$...%N...3/.| +000000a0 ab 20 22 33 ad 84 6d aa 31 6b 5a 10 0e 42 1b dd |. "3..m.1kZ..B..| +000000b0 35 9b a0 dc 31 f8 65 91 c4 14 78 2e 74 2e 1d 46 |5...1.e...x.t..F| +000000c0 3a 66 41 f0 a3 9a 4e ae bc 9b 55 f9 d1 9c c5 6e |:fA...N...U....n| +000000d0 38 24 19 15 fb e6 c3 85 de ef f0 97 a2 a1 db ed |8$..............| +000000e0 b8 d0 05 ae 93 77 d7 45 50 a5 4e 8a 83 84 07 fb |.....w.EP.N.....| +000000f0 3a 80 c6 69 3c 6e b2 e3 e0 97 f7 03 93 76 dd 32 |:..i<n.......v.2| +00000100 0c 5d a2 e6 1f 82 90 8b dd 93 06 ef eb b7 e0 74 |.].............t| +00000110 1a 7d 8f 37 c2 c1 41 9c 30 74 ca 37 17 5e 71 a0 |.}.7..A.0t.7.^q.| +00000120 cb d6 00 47 9d 14 93 aa fe 57 56 10 ae 88 13 65 |...G.....WV....e| +00000130 f4 6c 20 4e f9 14 87 73 36 5e d5 20 93 34 db 87 |.l N...s6^. .4..| +00000140 e7 f8 84 6e 36 9d 60 20 b5 8f 47 33 84 94 22 e1 |...n6.` ..G3..".| +00000150 5d c6 1c 35 39 61 71 47 90 a9 b4 c6 5e 31 58 d1 |]..59aqG....^1X.| +00000160 40 d8 22 22 23 c2 53 e3 75 1f 98 1c cc 7f 2d 11 |@.""#.S.u.....-.| +00000170 31 5e 49 a1 2c d9 c8 db 6e 4e 9d da 57 e1 c9 32 |1^I.,...nN..W..2| +00000180 03 6c f0 9b df c2 03 d5 b7 e2 04 77 e8 87 bc 14 |.l.........w....| +00000190 73 66 b0 fb d1 d6 26 0c 36 90 2c 20 43 16 c6 68 |sf....&.6., C..h| +000001a0 6c c0 ee be 2c da 6f 4f 95 1e cf a0 31 e8 40 48 |l...,.oO....1.@H| +000001b0 88 61 26 7b 53 5b 42 14 2a 89 a3 1e 03 01 16 9d |.a&{S[B.*.......| +000001c0 41 6d de 60 75 1d 36 12 cd 16 8b 1c 93 da 17 79 |Am.`u.6........y| +000001d0 4b d2 1d 78 64 da 6c cc 5c 7c e3 f9 4d 70 a2 07 |K..xd.l.\|..Mp..| +000001e0 b4 24 33 de 19 bc d2 1a 43 42 f4 26 8b c0 81 e4 |.$3.....CB.&....| +000001f0 a3 32 97 09 ec 6f 39 d7 ca c9 c5 ee 38 fd 91 dd |.2...o9.....8...| +00000200 c4 dc 3c 53 38 60 c7 b6 60 c6 a9 ff ae 81 e9 8c |..<S8`..`.......| +00000210 ea 49 19 3f fe 0e 8e b8 e6 7c ec 4b 63 66 d8 7a |.I.?.....|.Kcf.z| +00000220 82 51 7f 24 51 ae ad 91 5d 0e 2c aa ee fa 9f d3 |.Q.$Q...].,.....| +00000230 22 1a 8b 8d 12 48 bb 3a 7c ea f0 09 af 1a 7e 7e |"....H.:|.....~~| +00000240 47 74 b9 b9 1f 97 8e 64 62 52 ae 08 d5 f1 13 cb |Gt.....dbR......| +00000250 51 64 b0 6a 33 1f 48 78 c1 91 91 91 a7 75 29 cb |Qd.j3.Hx.....u).| +00000260 32 60 96 d4 27 3f a4 8f 12 e9 5d 79 4d fd f9 19 |2`..'?....]yM...| +00000270 b8 f7 39 d8 53 e5 45 96 0f c6 4f f2 27 c6 e6 07 |..9.S.E...O.'...| +00000280 40 47 29 94 b9 6a 38 9e 24 bf 9e 92 f6 67 3f e3 |@G)..j8.$....g?.| +00000290 48 0f 3b 3a d7 7b 14 4e 34 a3 8a 25 b4 a2 d6 15 |H.;:.{.N4..%....| +000002a0 3f 38 9e ba fa 7e 33 fd a4 4c ed e7 58 93 65 7d |?8...~3..L..X.e}| +000002b0 90 48 fc 70 7e 10 a5 d0 0a ec 96 c4 cf 26 ae 94 |.H.p~........&..| +000002c0 d7 3f 92 40 2f ad ed c8 bb 69 b1 3e 0b ab 4f 4e |.?.@/....i.>..ON| +000002d0 73 91 a6 05 2b a7 89 e8 63 28 39 51 53 8d 2c 5e |s...+...c(9QS.,^| +000002e0 c8 64 90 c3 b7 2d ee 00 aa 7f 38 ca 57 ab b8 aa |.d...-....8.W...| +000002f0 93 12 af c5 16 03 03 00 bc 0e 58 31 64 e6 68 e6 |..........X1d.h.| +00000300 10 81 2f 79 e3 49 3a d9 cc 70 09 7e b6 b5 61 c4 |../y.I:..p.~..a.| +00000310 92 16 22 d0 e5 af b8 b8 91 2e 72 7c cf 95 cb ef |..".......r|....| +00000320 14 81 73 33 34 98 65 1b 69 db 2c 9d eb 1c ce be |..s34.e.i.,.....| +00000330 1f ce 48 b4 22 8d f0 6e 48 21 8e aa af 83 43 d2 |..H."..nH!....C.| +00000340 65 54 0f 57 6b ce b1 24 ef 09 bf 7f 23 92 35 07 |eT.Wk..$....#.5.| +00000350 55 2f 2f e7 b7 d7 72 d2 7c 5f 71 d6 20 9a 68 e8 |U//...r.|_q. .h.| +00000360 1b 90 0b 13 f7 37 e2 35 0d fc 04 ea 32 50 2d 04 |.....7.5....2P-.| +00000370 72 1a db d9 71 e1 4e d1 76 7c c3 f5 22 97 92 c5 |r...q.N.v|.."...| +00000380 61 19 e0 40 b1 14 de 37 9d 8e e7 fd fe 2b 28 97 |a..@...7.....+(.| +00000390 91 77 8f a7 d4 b1 db bc a2 78 65 5c a8 8d 41 21 |.w.......xe\..A!| +000003a0 0e 56 6b ac 0b da a9 dd b1 51 84 19 20 ab e5 eb |.Vk......Q.. ...| +000003b0 f2 52 8d 48 a2 16 03 03 00 4a 69 44 32 65 c2 09 |.R.H.....JiD2e..| +000003c0 9c c1 d6 66 06 29 c3 a6 c3 10 2e d9 9e d6 0a d3 |...f.)..........| +000003d0 06 a3 d2 d2 67 52 bd 19 26 a8 ef 08 ed 9f 2b e8 |....gR..&.....+.| +000003e0 96 ea 08 b7 46 a2 36 e3 c1 84 4b c2 a2 b5 34 9c |....F.6...K...4.| +000003f0 83 ea 94 51 e6 ca 9c 0b e1 e3 86 13 b7 1b 1f 4e |...Q...........N| +00000400 ee a1 10 70 16 03 03 00 14 5a 1c c1 14 fd d9 ff |...p.....Z......| +00000410 e3 46 ac 89 3b b3 e1 8e 6b 90 41 44 1f |.F..;...k.AD.| >>> Flow 9 (client to server) -00000000 16 03 03 02 69 11 1e 53 9b b7 57 6d ea 89 bb 37 |....i..S..Wm...7| -00000010 1b c6 01 bd 27 db fa 17 cc 5d 20 be ee 5b a9 64 |....'....] ..[.d| -00000020 48 4e 4a 4c 82 65 8e 3d 42 d6 ce 5c a8 50 d4 fa |HNJL.e.=B..\.P..| -00000030 0f 02 b2 19 90 b5 4e ae 6c e9 d6 b7 b8 64 ca 0e |......N.l....d..| -00000040 09 2d a9 7b ab 0f b8 83 97 b6 e0 eb bf 03 5a 1c |.-.{..........Z.| -00000050 e7 16 31 67 30 46 60 26 df 19 cf 5f fa 40 36 43 |..1g0F`&..._.@6C| -00000060 91 d5 7c 2f 5f 29 74 03 e0 90 cd 55 25 e5 1e fe |..|/_)t....U%...| -00000070 6b 13 ec 58 29 b0 f4 a3 b2 8d ba 4e 3b f1 11 d8 |k..X)......N;...| -00000080 85 49 50 b9 e0 03 89 a1 0f da ce 57 83 aa 4a 8c |.IP........W..J.| -00000090 3b 15 d5 10 47 01 22 32 4f 78 87 69 4c bf a6 6e |;...G."2Ox.iL..n| -000000a0 d4 e6 a5 1e fa 5b ff b0 38 a5 fa 83 1d 45 c5 18 |.....[..8....E..| -000000b0 72 65 91 6c 41 d2 21 be 5b 1d e9 f5 19 eb d0 5a |re.lA.!.[......Z| -000000c0 7e 0d 81 c9 ca f0 97 9e cc 9b 5c 77 6b 9c 15 d3 |~.........\wk...| -000000d0 bd 43 4d 42 e5 f9 82 a9 d6 f2 44 93 ae 74 a3 fd |.CMB......D..t..| -000000e0 c5 1f 15 13 a0 ea d2 f3 4c 4c ea 2d fe 3b 6e 7b |........LL.-.;n{| -000000f0 f4 11 f7 2e 7d 45 26 a0 d9 29 4e 4d ec 90 e2 3e |....}E&..)NM...>| -00000100 51 52 dd 6e e1 b5 77 b1 a2 f5 17 b5 34 7f e8 8f |QR.n..w.....4...| -00000110 38 9c d6 1c b5 6c 2d 99 00 a1 41 95 15 c5 e5 bf |8....l-...A.....| -00000120 c1 67 fb ea 53 6c a8 85 8c c4 a6 74 e3 dc f7 90 |.g..Sl.....t....| -00000130 b8 cc 99 39 1a a1 c6 51 db 65 e9 b8 ad 2b 1f 35 |...9...Q.e...+.5| -00000140 b5 90 ae f7 af c2 d0 a9 92 eb 63 21 24 4f 5e 62 |..........c!$O^b| -00000150 ba 69 ce 1a c8 41 79 db c0 6c ef bc cf 19 4a 2c |.i...Ay..l....J,| -00000160 e0 66 6e 72 97 2d 75 e5 ee 14 82 e8 26 98 fe c4 |.fnr.-u.....&...| -00000170 8a 17 c4 fb 48 2a d7 7e d9 3e 5b f9 d4 7d 0e da |....H*.~.>[..}..| -00000180 56 44 5e 33 9d 5f 97 ab d1 60 a8 ee 3d 16 6a 2a |VD^3._...`..=.j*| -00000190 33 b1 7d e2 e6 86 cd 88 ac e1 48 49 4e 19 a2 b0 |3.}.......HIN...| -000001a0 16 53 ec ff b8 a4 f7 35 2d a7 7a 04 86 66 42 52 |.S.....5-.z..fBR| -000001b0 51 3d 21 62 c5 35 9c e5 cb f9 bf 7b d1 12 b0 18 |Q=!b.5.....{....| -000001c0 7b 6f 88 d9 ef d2 1a 45 3e 51 ac 3e c8 87 8c 47 |{o.....E>Q.>...G| -000001d0 08 d0 90 b5 66 f6 4e c3 75 74 68 c8 7d 14 3a 2b |....f.N.uth.}.:+| -000001e0 83 7d 12 78 37 9e 11 02 3d 63 ba 78 b6 ba 6d 26 |.}.x7...=c.x..m&| -000001f0 30 b0 bf a9 23 1e 83 aa 3d a8 02 5b 77 5f 2a 95 |0...#...=..[w_*.| -00000200 d0 b9 c8 22 a3 a9 fe b0 32 99 8a 46 67 10 b3 d9 |..."....2..Fg...| -00000210 3e 84 02 ec a2 68 7e 69 db 51 99 37 ee 49 66 0b |>....h~i.Q.7.If.| -00000220 af e1 cd b0 25 74 dc ce 29 ed 70 1c 3a bb f2 99 |....%t..).p.:...| -00000230 03 86 6d af 3f 78 4a 86 70 b8 85 15 02 91 be f6 |..m.?xJ.p.......| -00000240 4f f2 73 98 00 c6 76 20 c2 19 c6 e9 6c d0 e5 09 |O.s...v ....l...| -00000250 5c 12 c8 1c a1 3d b7 41 18 26 cb ea d0 92 61 53 |\....=.A.&....aS| -00000260 06 7c f8 5e a8 27 de 76 4e 83 49 2a ab 82 16 03 |.|.^.'.vN.I*....| -00000270 03 00 35 4f b7 51 7c c8 51 25 a4 58 de 8b 4a e2 |..5O.Q|.Q%.X..J.| -00000280 97 cc 48 d0 4d be 9b 8a 44 3b 22 43 b9 82 a4 a5 |..H.M...D;"C....| -00000290 76 38 0b ae 91 d3 20 75 18 50 f3 1b eb 11 fd 86 |v8.... u.P......| -000002a0 4a 1a f1 e8 2a f8 e0 60 16 03 03 00 98 ae e6 1b |J...*..`........| -000002b0 b1 00 f9 14 93 55 be 63 ea 5b 5e d4 18 37 6b 14 |.....U.c.[^..7k.| -000002c0 5c 8e fb 82 51 e1 57 24 b7 4a 8b 55 74 79 70 55 |\...Q.W$.J.UtypU| -000002d0 de 33 82 14 0a 39 0d 91 92 9a 11 c0 4a dd 12 49 |.3...9......J..I| -000002e0 ea 1a 41 df fd f2 4a 79 c3 0a d5 93 5c ea 82 ff |..A...Jy....\...| -000002f0 16 4a 20 91 25 34 5d 72 9d ea 0e 40 dd 6d 86 fd |.J .%4]r...@.m..| -00000300 e9 d1 d9 db 61 e6 62 17 6b 09 47 c4 a7 32 1c 22 |....a.b.k.G..2."| -00000310 f6 e4 41 2a 3e 2b d0 c3 92 56 c5 b8 5f 6d 25 44 |..A*>+...V.._m%D| -00000320 81 e7 1a ed 70 6a a6 94 89 d1 ad 8d d1 c0 df a2 |....pj..........| -00000330 26 6f 20 0b 0e 51 15 dd 05 86 36 88 72 3f e1 5d |&o ..Q....6.r?.]| -00000340 da 9d d3 76 e4 14 03 03 00 11 52 70 cd 84 39 32 |...v......Rp..92| -00000350 7c c0 58 53 9b 32 00 96 14 b6 57 16 03 03 00 20 ||.XS.2....W.... | -00000360 98 94 aa 9f 77 71 42 3e 48 e8 74 8e 27 60 54 c2 |....wqB>H.t.'`T.| -00000370 55 ac 52 99 37 21 f3 1e 30 93 5f 71 06 19 e5 1c |U.R.7!..0._q....| +00000000 16 03 03 02 69 c8 db 54 92 d3 ea 2f 24 47 f9 24 |....i..T.../$G.$| +00000010 53 c1 d4 6a e8 dd 1d 71 d6 fb 2c 7e 3a 41 75 f6 |S..j...q..,~:Au.| +00000020 0c 08 70 b6 f9 0a 12 4b 0d 3d 34 03 a9 36 9e f1 |..p....K.=4..6..| +00000030 c7 93 dc 51 e4 15 3d fd a7 67 28 24 32 fe ff d3 |...Q..=..g($2...| +00000040 cd 69 d6 4a 5d 11 78 3b aa 07 8d 1e c4 97 22 34 |.i.J].x;......"4| +00000050 df 03 f2 37 fd 4f 76 c3 04 a6 a6 0f 35 1c 0f 13 |...7.Ov.....5...| +00000060 7e 0a b9 5e 47 d2 9a 8c d8 a3 f4 7a e4 92 5f 12 |~..^G......z.._.| +00000070 a6 20 fb 51 16 af eb 55 d0 23 4e b5 f9 e8 cc 33 |. .Q...U.#N....3| +00000080 bd d1 52 27 21 96 06 05 67 fa 68 0e ab 2c 84 05 |..R'!...g.h..,..| +00000090 c9 97 6a db 69 57 a8 5c 55 a9 e1 cf 33 01 28 9a |..j.iW.\U...3.(.| +000000a0 76 09 64 a4 a3 31 36 13 72 27 0c 85 e9 59 47 27 |v.d..16.r'...YG'| +000000b0 89 07 ee e2 e0 68 a6 f0 fa d5 c3 8b 2f 75 68 d0 |.....h....../uh.| +000000c0 8e d8 fe ae 1d 0d af 0b 40 3d 9f ec 85 03 24 20 |........@=....$ | +000000d0 c5 11 30 aa 25 ee 2c 86 42 ae 4f 0d 6b 18 70 1d |..0.%.,.B.O.k.p.| +000000e0 5f ae 1e cf 99 a7 0e c8 9b b3 63 58 cd b6 7d be |_.........cX..}.| +000000f0 01 43 96 37 87 45 5f 2f aa 9c 12 48 ef 3b c8 d9 |.C.7.E_/...H.;..| +00000100 60 20 26 69 68 56 48 aa 64 59 9e 41 ed 7e 8d c3 |` &ihVH.dY.A.~..| +00000110 0f cd 0e 19 7a 76 89 95 f8 20 68 cd f9 81 e9 a0 |....zv... h.....| +00000120 21 ff 60 e5 0f 6d dd 73 d2 19 1e 2a 76 f7 9a 46 |!.`..m.s...*v..F| +00000130 5d d5 6b b2 19 28 c2 ac 9c e0 35 c8 d2 2a 53 fa |].k..(....5..*S.| +00000140 3e 58 9e f2 05 7e 6b ce 51 6d 3d 2a ce 2e 9b 59 |>X...~k.Qm=*...Y| +00000150 aa d4 8d cc ad 1f 82 e7 ca 5a ef a6 87 d5 41 0b |.........Z....A.| +00000160 8d 27 6d 09 4d 40 c3 26 a3 a9 91 dd 1b 37 5d ff |.'m.M@.&.....7].| +00000170 8f c3 c7 b1 bf be f5 d1 19 4d 93 86 a7 5f 5e 8f |.........M..._^.| +00000180 14 34 82 50 76 25 42 04 b8 4b d3 da 15 ee 60 d1 |.4.Pv%B..K....`.| +00000190 35 56 4c 63 0d ba 64 13 4f 3d 12 87 84 5a 45 41 |5VLc..d.O=...ZEA| +000001a0 14 b6 6f 91 c4 b9 4f 97 c1 10 d6 3e b3 99 21 18 |..o...O....>..!.| +000001b0 c3 91 82 e4 b6 91 3e bb 01 89 9a f0 60 ac 8e 7d |......>.....`..}| +000001c0 cf c2 f9 b4 4f da 40 e3 5e 83 a1 8f b4 fa 28 aa |....O.@.^.....(.| +000001d0 c9 ae 7b 8f 7d c9 d1 f8 7b b2 b5 3f 0a 9b 00 9e |..{.}...{..?....| +000001e0 1d fa 59 ff 39 b7 85 4d 2a b9 b8 67 03 df a0 f9 |..Y.9..M*..g....| +000001f0 f1 7e 9d 27 1c 55 a9 76 44 9e f1 13 78 7d 34 4d |.~.'.U.vD...x}4M| +00000200 c9 23 07 e6 db 93 d7 70 3c 1b 5d 89 ed 8d 3d 43 |.#.....p<.]...=C| +00000210 2e 89 f6 14 83 ff 87 db 26 a5 9a cd 98 5d 32 24 |........&....]2$| +00000220 70 d2 e0 72 a7 6f a4 b4 2b 37 db 7e 39 4f d7 37 |p..r.o..+7.~9O.7| +00000230 ea 68 b5 98 33 0e 23 21 3f 43 b3 ff 18 8e df 85 |.h..3.#!?C......| +00000240 ba 15 48 3a fe 09 9b b6 27 40 d4 60 a8 3e 55 a3 |..H:....'@.`.>U.| +00000250 75 c9 32 38 b5 21 46 ab 41 99 24 e6 09 3f 64 e6 |u.28.!F.A.$..?d.| +00000260 09 40 cb 93 25 ab 1a 90 c7 d5 a6 40 36 a0 16 03 |.@..%......@6...| +00000270 03 00 35 0f c7 e4 c3 16 c0 4f 7f 25 04 06 63 e7 |..5......O.%..c.| +00000280 79 79 f9 4f c9 66 ca cd ba e3 af 4a 50 a3 3d c3 |yy.O.f.....JP.=.| +00000290 79 0c 71 d9 2f df 93 79 30 8f 6b 0f 54 f9 be 07 |y.q./..y0.k.T...| +000002a0 f3 d6 9b c0 2a 3a 0a a1 16 03 03 00 98 b8 f1 fc |....*:..........| +000002b0 87 62 e9 6b 40 fd 50 ac b7 fa 52 69 51 66 ae 9b |.b.k@.P...RiQf..| +000002c0 05 7e f2 38 73 27 d8 0c 2a 53 37 30 62 76 5d e9 |.~.8s'..*S70bv].| +000002d0 fd 95 c6 14 d2 9d 34 13 e9 4c a5 7c c0 b6 e0 c4 |......4..L.|....| +000002e0 97 ef 01 c0 f9 38 39 ee 17 c0 20 01 76 4f a7 10 |.....89... .vO..| +000002f0 b0 45 9d c7 c3 cd a9 47 14 4a ed 00 1f 06 70 5b |.E.....G.J....p[| +00000300 f5 04 8b 77 ad af 1e 77 7a 9d cc fc a4 1f d2 8d |...w...wz.......| +00000310 8f e3 31 d3 3c de e6 85 f3 3d c0 ae 78 f7 22 c6 |..1.<....=..x.".| +00000320 ec 2e a2 f0 5f ed 95 33 54 8c 89 35 c9 e4 25 4b |...._..3T..5..%K| +00000330 84 5e 31 83 04 d0 f1 67 69 73 8b 7f 24 ae e0 87 |.^1....gis..$...| +00000340 6b f7 ba f0 23 14 03 03 00 11 7a c7 6a 32 2b 9b |k...#.....z.j2+.| +00000350 25 c2 d2 ee 37 b2 8d 7b f2 90 6d 16 03 03 00 20 |%...7..{..m.... | +00000360 c1 1c 9d 18 a9 41 92 fc 05 19 93 7c 7e 2f b2 39 |.....A.....|~/.9| +00000370 8c 76 4b 29 5a 67 cc f5 55 9f c0 e3 8f ad ee 3c |.vK)Zg..U......<| >>> Flow 10 (server to client) -00000000 14 03 03 00 11 45 8e f9 74 04 d0 44 c6 94 80 60 |.....E..t..D...`| -00000010 c1 50 7d b2 64 76 16 03 03 00 20 d5 65 8a b9 26 |.P}.dv.... .e..&| -00000020 54 70 26 de c6 8a 8f 61 a3 b1 9e 8b 49 40 f7 24 |Tp&....a....I@.$| -00000030 4f 75 e0 94 e6 e7 68 51 38 8a 37 17 03 03 00 19 |Ou....hQ8.7.....| -00000040 42 7e 5a e2 46 7b ba 7d 0d 07 20 2a c0 56 fe aa |B~Z.F{.}.. *.V..| -00000050 01 eb ca d2 29 1d ff 85 10 |....)....| +00000000 14 03 03 00 11 49 66 13 ec 09 83 0d 47 82 45 61 |.....If.....G.Ea| +00000010 06 14 cc f5 da 41 16 03 03 00 20 34 d4 0c bd 86 |.....A.... 4....| +00000020 6d ef a9 b6 97 68 e6 88 84 ed 1c 9d a1 8d 2b c9 |m....h........+.| +00000030 2f 45 75 5b e5 6a 08 72 71 a9 c6 17 03 03 00 19 |/Eu[.j.rq.......| +00000040 e8 83 4c f5 19 ea d1 ef e3 27 25 f9 af d2 f0 a6 |..L......'%.....| +00000050 b3 62 15 66 ec 72 ce 4e e2 |.b.f.r.N.| >>> Flow 11 (client to server) -00000000 15 03 03 00 12 1d 01 c7 d5 d5 d1 ce 8c 52 15 8f |.............R..| -00000010 75 1e 97 fa 38 5c 65 |u...8\e| +00000000 15 03 03 00 12 2e 39 ba ca ad 7c a9 ae 3f 6a 78 |......9...|..?jx| +00000010 b6 31 d2 d0 4e 1f dc |.1..N..| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice index 006e2d7..20aa6c9 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 47 d0 f5 d9 f0 |....Y...U..G....| -00000010 59 d1 bf 28 d0 39 36 c0 bc d1 25 fd 5a 63 18 06 |Y..(.96...%.Zc..| -00000020 1e 8a 5c a6 6f d0 f9 b4 02 23 e1 20 df a0 2a 74 |..\.o....#. ..*t| -00000030 1a 52 8b d9 90 01 c2 86 69 12 b8 13 58 aa 59 b0 |.R......i...X.Y.| -00000040 66 79 ff 01 9b 9a 72 1c a6 83 e6 91 cc a8 00 00 |fy....r.........| +00000000 16 03 03 00 59 02 00 00 55 03 03 68 39 1d 0e 5a |....Y...U..h9..Z| +00000010 22 ba 13 5f b6 c1 52 5d 13 e5 07 18 aa ec 24 0f |".._..R]......$.| +00000020 c9 56 3a 83 a1 32 a1 7f 02 e8 7b 20 31 e2 f8 c4 |.V:..2....{ 1...| +00000030 5b c2 57 9a 1d a4 6f a7 9c 1c 93 b1 9f 19 c3 cb |[.W...o.........| +00000040 e1 73 87 1b a8 88 d9 4c 67 2f 44 aa cc a8 00 00 |.s.....Lg/D.....| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,284 +60,284 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| -000002c0 ac 0c 00 00 a8 03 00 1d 20 20 97 bd 85 2f cb 85 |........ .../..| -000002d0 be a8 9c e3 ae 6b 23 a5 5b 18 65 5c f5 cc 24 2b |.....k#.[.e\..$+| -000002e0 34 2c 5f c8 4d e9 86 35 0b 08 04 00 80 d2 b6 ee |4,_.M..5........| -000002f0 86 76 aa 1d 9c 1c ee ef 0e 59 63 1d ec f1 cf a1 |.v.......Yc.....| -00000300 f3 5b 6d da 99 9c 40 07 bf 28 ad 72 cd 80 6c 9d |.[m...@..(.r..l.| -00000310 bf a2 20 33 2d d0 67 ef 90 28 88 2b d0 8e c6 9d |.. 3-.g..(.+....| -00000320 87 7a 18 8f 80 ce 25 92 13 8d ef 38 0a 14 f9 67 |.z....%....8...g| -00000330 88 94 ef af 97 d2 21 90 9e 24 2f af 1e bb fa 10 |......!..$/.....| -00000340 4c a7 9f f5 27 63 e6 d8 1a 86 53 c6 3c 15 a8 6c |L...'c....S.<..l| -00000350 b9 bc 8f c4 38 1a 4b 34 36 ec af b2 1e d0 bf 58 |....8.K46......X| -00000360 74 36 ad fb e4 f0 fd 9d 6d 01 cf 51 6c 16 03 03 |t6......m..Ql...| +000002c0 ac 0c 00 00 a8 03 00 1d 20 57 22 18 98 ed 7f 12 |........ W".....| +000002d0 e7 e3 83 6b 42 82 ff 49 54 f8 0b 7d 93 3d 11 42 |...kB..IT..}.=.B| +000002e0 67 cf 89 47 77 31 c5 59 4a 08 04 00 80 69 d4 13 |g..Gw1.YJ....i..| +000002f0 f8 1c 68 9d 40 10 c8 aa e6 44 0e 14 b9 38 6e ca |..h.@....D...8n.| +00000300 a9 50 05 4a ce a0 03 ea 02 92 e4 5a ed 42 6f 70 |.P.J.......Z.Bop| +00000310 e1 c1 99 49 a4 34 20 6b 5e 14 e8 a1 d3 27 ff 0d |...I.4 k^....'..| +00000320 0c d7 47 49 1e 8f 8a 3a 62 1d c9 81 3c 5f a3 16 |..GI...:b...<_..| +00000330 16 34 a0 53 a7 01 1d 09 f7 d9 d4 62 b2 0a 1c 1f |.4.S.......b....| +00000340 b2 e5 24 1b 7e 78 35 43 ed 47 f8 62 53 2d 04 ec |..$.~x5C.G.bS-..| +00000350 81 b5 68 11 3a 2d ee 88 ef 86 eb 71 d0 5e 31 42 |..h.:-.....q.^1B| +00000360 57 6d b6 f2 be 32 4c 38 f8 2a 93 2f db 16 03 03 |Wm...2L8.*./....| 00000370 00 04 0e 00 00 00 |......| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 e8 d5 df da 49 9a 94 10 30 90 81 |.... ....I...0..| -00000040 c6 19 54 d4 0d e2 0d e0 d9 a3 c0 21 7f a6 d1 cc |..T........!....| -00000050 ea 75 2e 17 01 |.u...| +00000030 16 03 03 00 20 2a 03 0a 58 36 31 ec 26 df e5 7c |.... *..X61.&..|| +00000040 88 b5 d1 f7 6d fc 4b 0a 91 54 4a e7 8c 83 a3 54 |....m.K..TJ....T| +00000050 0a 10 5b ff 69 |..[.i| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 f3 92 03 fb 7b |.......... ....{| -00000010 0f 32 0b 5b dd 9e eb c3 26 2c 92 4d 58 35 a8 96 |.2.[....&,.MX5..| -00000020 74 d6 d8 0f 61 b2 7d b6 8d ec e6 |t...a.}....| +00000000 14 03 03 00 01 01 16 03 03 00 20 27 b0 69 0c 67 |.......... '.i.g| +00000010 c7 3a ec c1 aa 02 20 cf f9 e8 22 86 3b d3 e1 4f |.:.... ...".;..O| +00000020 bc fd 04 40 19 77 bf bd 38 28 56 |...@.w..8(V| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 ab 69 44 d0 fe 95 93 ae f9 1b d7 |......iD........| -00000010 33 6c 59 a5 41 cc d2 1b ca 2c 63 |3lY.A....,c| +00000000 17 03 03 00 16 8a 2c 24 1b b8 53 01 54 c8 bd f3 |......,$..S.T...| +00000010 e1 ec a9 ab 83 a0 66 a9 29 1c 4e |......f.).N| >>> Flow 6 (server to client) -00000000 16 03 03 00 14 99 96 92 c4 82 c8 27 77 a6 f4 ca |...........'w...| -00000010 e5 5b ff 78 bc 54 b6 d7 cd |.[.x.T...| +00000000 16 03 03 00 14 c5 e3 03 06 89 d8 47 1a 66 18 0e |...........G.f..| +00000010 8d 36 c5 f4 30 80 7e 72 a2 |.6..0.~r.| >>> Flow 7 (client to server) -00000000 16 03 03 01 16 d9 6a 26 33 e5 d8 df 32 d1 f5 84 |......j&3...2...| -00000010 1f 37 7f 07 6a ae be 20 84 20 dc 28 31 8e 46 32 |.7..j.. . .(1.F2| -00000020 0b 96 c8 22 28 fb 98 d9 8e 6f 6d 97 66 55 e2 1e |..."(....om.fU..| -00000030 b5 b8 e4 9b 52 25 28 c2 72 cb 9e 14 4c ba 58 6c |....R%(.r...L.Xl| -00000040 3b 33 da 56 db fe 14 d3 4c b4 ce a9 57 64 ae 4e |;3.V....L...Wd.N| -00000050 5f c5 a7 e6 f4 01 51 d7 81 f4 1d ca fa 3f 86 e7 |_.....Q......?..| -00000060 9f 64 28 6e 3f e4 ef 79 77 20 64 45 ed a2 16 e1 |.d(n?..yw dE....| -00000070 b4 63 99 9f 62 6d b7 6d f4 ad 1f fe d9 de 00 84 |.c..bm.m........| -00000080 4b bb 0c bc c8 82 a8 1d 8a ac f6 10 2d 5d d4 c7 |K...........-]..| -00000090 37 f8 fc 89 24 ea c4 b8 87 f4 f4 f0 4b cd db e2 |7...$.......K...| -000000a0 15 03 95 1e c1 10 7c e8 6d 99 6c e0 bc e1 0a a5 |......|.m.l.....| -000000b0 d8 36 eb 59 93 6d 1c 96 1c 61 1b 11 36 04 58 6b |.6.Y.m...a..6.Xk| -000000c0 c5 b0 fb 8e 9f 21 4a 25 a1 59 ee 5d 1b e3 e3 98 |.....!J%.Y.]....| -000000d0 71 0a d8 3f 18 f2 b2 1c 6f ec 6d 87 13 b9 d3 25 |q..?....o.m....%| -000000e0 53 c1 00 78 be 99 82 f6 27 05 24 01 10 1c 59 19 |S..x....'.$...Y.| -000000f0 94 6a af 7e e5 ae c5 03 14 04 e2 fe 5e 59 e8 e0 |.j.~........^Y..| -00000100 45 3d af c0 40 ea 84 0a 13 9c d3 0f d4 69 3f 3e |E=..@........i?>| -00000110 97 83 ac b5 b9 07 56 9a 19 44 ca |......V..D.| +00000000 16 03 03 01 16 7e eb a3 b5 ea 58 e3 4a 26 35 7d |.....~....X.J&5}| +00000010 54 15 93 74 e8 e4 63 34 38 d9 e0 02 3d 28 f8 98 |T..t..c48...=(..| +00000020 0f 24 6b ca 08 7f b6 77 68 ec 85 c3 4a 6b 69 c3 |.$k....wh...Jki.| +00000030 8d 8e 1b 8b 41 11 9b 0d d1 c8 99 2b c9 d2 4c f1 |....A......+..L.| +00000040 fd 82 e5 35 ba a3 3b f3 6d 47 82 45 08 e7 02 bb |...5..;.mG.E....| +00000050 10 a6 7b 76 83 78 e0 aa 5a 78 24 59 1c db ae a3 |..{v.x..Zx$Y....| +00000060 37 20 b3 12 98 48 68 d3 b3 72 9f 4f d4 de 50 b4 |7 ...Hh..r.O..P.| +00000070 4a c1 37 93 e0 55 ae e8 37 2a 40 de ac 30 e1 1d |J.7..U..7*@..0..| +00000080 f0 03 19 8c af 77 f5 26 98 af a8 a8 d2 72 6c 68 |.....w.&.....rlh| +00000090 75 00 32 10 e6 3f 91 a8 24 a7 d8 05 23 04 52 23 |u.2..?..$...#.R#| +000000a0 e7 e6 83 ac 37 1b 36 a7 ca d4 7e d5 21 4c ab 38 |....7.6...~.!L.8| +000000b0 23 cb 7c a9 f4 66 26 5e 7f 3e d6 ab 7a ac 34 38 |#.|..f&^.>..z.48| +000000c0 95 16 df e2 e4 cf 3a 62 82 78 cb 71 32 06 6d 07 |......:b.x.q2.m.| +000000d0 84 91 0c e9 d0 63 88 9e d1 b5 f0 fb 43 2b 07 0b |.....c......C+..| +000000e0 32 d7 20 af b8 76 17 da ee cc e6 03 bb 7a 0b f2 |2. ..v.......z..| +000000f0 61 4f db 7f a3 66 b0 05 a8 88 b8 0b b3 6e 9c df |aO...f.......n..| +00000100 48 8b 7e eb 42 cd ea eb 1d bb 63 a0 e4 ee df 21 |H.~.B.....c....!| +00000110 20 67 11 26 dd f1 47 1b 15 2b a0 | g.&..G..+.| >>> Flow 8 (server to client) -00000000 16 03 03 00 81 4b d8 09 ef 6a 5b a2 c2 e0 2c b3 |.....K...j[...,.| -00000010 fa e9 21 b3 64 c7 51 8d d4 14 14 ba 7b 2f f8 1a |..!.d.Q.....{/..| -00000020 e9 f8 7a 69 8b 0b b4 5f 26 c5 b6 2e dd c9 90 04 |..zi..._&.......| -00000030 7d af fd 56 f7 9a 0d 56 09 6c 74 48 49 74 90 71 |}..V...V.ltHIt.q| -00000040 e1 ee 66 4c 1a da 66 43 50 fa 94 2c 84 21 10 f0 |..fL..fCP..,.!..| -00000050 00 85 a7 c2 ea 73 19 52 b7 f2 2a e8 17 17 23 67 |.....s.R..*...#g| -00000060 b6 80 d6 3f e0 a1 ed 81 66 89 0a 0d 48 9f 7f dc |...?....f...H...| -00000070 79 c4 27 9b c0 b8 68 ef 2a 5b ab df 8f 82 d6 ff |y.'...h.*[......| -00000080 84 38 f8 a4 f2 98 16 03 03 02 69 1f c6 1c dc 85 |.8........i.....| -00000090 f1 66 8d 7f 7f aa 36 cd c6 d4 cc 38 c8 8d 98 75 |.f....6....8...u| -000000a0 92 d2 db b4 49 0c 09 cc af e6 5b 07 64 76 34 c8 |....I.....[.dv4.| -000000b0 41 49 85 5e b4 68 ac 35 04 72 00 70 33 f7 5f a7 |AI.^.h.5.r.p3._.| -000000c0 84 40 34 03 2f 89 25 06 a1 50 dc ea d7 c4 29 57 |.@4./.%..P....)W| -000000d0 f9 5b 57 63 14 02 1e 74 db 5d 02 cf c4 f1 89 f6 |.[Wc...t.]......| -000000e0 6a 77 ce 87 5c 3a 61 b8 7d 02 f0 0e 6e 85 2a 51 |jw..\:a.}...n.*Q| -000000f0 d8 ad 4a 9f 65 04 4c 00 d0 35 76 01 dc 03 cf ca |..J.e.L..5v.....| -00000100 6b 11 83 9e 70 33 82 f6 cb eb 4c da 44 76 89 ab |k...p3....L.Dv..| -00000110 d4 65 01 e6 08 7b 2a 3d 49 02 39 85 e8 ff 53 fd |.e...{*=I.9...S.| -00000120 d0 ce 2a f0 11 3c 02 8f bd b8 2f ea 81 a1 64 10 |..*..<..../...d.| -00000130 7b c2 8b 72 f3 32 7b 36 80 13 17 8b 83 dc ce 3a |{..r.2{6.......:| -00000140 29 44 06 66 c9 c3 83 cc 28 38 c5 02 7c 3d b6 30 |)D.f....(8..|=.0| -00000150 55 07 a0 08 bb b3 e1 1e a8 a5 74 60 51 be ee dd |U.........t`Q...| -00000160 aa 83 09 e9 f3 c7 a5 1e 20 fc 6d d5 82 af f5 b6 |........ .m.....| -00000170 5b 23 dd 81 ce 78 5a 3c 92 c3 96 e1 aa e5 ad 24 |[#...xZ<.......$| -00000180 da 89 41 44 8b 0b 42 df e5 28 11 8e 9a e0 06 51 |..AD..B..(.....Q| -00000190 80 93 15 31 ec 8c 3e 60 92 ab a5 ec 25 5c c5 10 |...1..>`....%\..| -000001a0 ac 0f 01 1b c4 36 d5 f0 52 c7 0b f7 9b 40 9b c0 |.....6..R....@..| -000001b0 18 ad 1c eb 49 ed 8e 27 b6 35 b4 20 e0 e6 df 04 |....I..'.5. ....| -000001c0 69 d6 b5 56 04 30 d4 3d b0 9f e6 21 66 e7 97 cb |i..V.0.=...!f...| -000001d0 2f bd b2 b2 c1 be 4b 4f 6e 88 60 a1 cb eb b4 86 |/.....KOn.`.....| -000001e0 92 07 da 3c fa 8b 1a de 1c e7 6b c0 53 70 e7 ee |...<......k.Sp..| -000001f0 2f 70 4f e0 2a a3 b4 dc af 64 4f 5a 44 f9 ff fc |/pO.*....dOZD...| -00000200 7f 2f 7e 22 13 47 ed f4 ec 0c fa 01 21 e3 c1 d6 |./~".G......!...| -00000210 c7 53 f4 de 6c 91 c5 85 bd 3c a7 f3 d6 e7 f3 31 |.S..l....<.....1| -00000220 13 59 b7 ee 0b f7 6a 88 76 94 ab 45 41 9e ab d7 |.Y....j.v..EA...| -00000230 71 59 7e 45 ed 4d a0 12 4a 81 6a 15 05 a9 21 94 |qY~E.M..J.j...!.| -00000240 40 f0 1d aa 7e b3 d4 6d a6 ff 46 94 e6 d0 16 46 |@...~..m..F....F| -00000250 60 ac c5 15 94 d5 f7 76 1e 8b 90 e6 17 ff 5c 21 |`......v......\!| -00000260 d0 f9 98 25 0f 98 8b 6c 0f 2c 2a 92 0a f0 90 3d |...%...l.,*....=| -00000270 ef 9a 40 67 21 83 f7 5c 95 24 97 f6 45 51 81 4c |..@g!..\.$..EQ.L| -00000280 4b e1 64 0a f5 dd 02 fd 8d 21 d1 ef f8 96 70 4b |K.d......!....pK| -00000290 58 aa 3c f9 b1 f1 e9 fd 31 ea fc 68 4b c9 fa 79 |X.<.....1..hK..y| -000002a0 6d 2e 54 d7 1c 9d 5d 62 fc 43 2f cb 6a 48 4d 2e |m.T...]b.C/.jHM.| -000002b0 07 71 7b f2 b3 e6 08 8b 13 ca f0 e9 c1 d2 cc 7a |.q{............z| -000002c0 9a 49 e9 7b aa e8 bb d2 cf 97 73 b8 9a 3f 8b 01 |.I.{......s..?..| -000002d0 b9 cf c6 81 fd 99 fc c9 43 08 35 2c a0 fb 38 32 |........C.5,..82| -000002e0 8b d8 5b d4 20 41 a0 57 e6 34 c1 d8 66 6e 16 e7 |..[. A.W.4..fn..| -000002f0 78 4f e8 58 16 03 03 00 bc d3 91 f3 88 2f ec 1c |xO.X........./..| -00000300 da 94 cb b0 69 70 a2 41 4c fd 40 0d a0 97 01 34 |....ip.AL.@....4| -00000310 35 83 e6 3f a8 b0 c9 26 8d f1 8a c1 f6 a6 ab a4 |5..?...&........| -00000320 63 65 5a 10 38 d2 87 a7 8d ae ca 9e c6 23 7e c6 |ceZ.8........#~.| -00000330 c8 45 37 e8 7c 4b 40 5a 5b 68 19 bb 36 83 81 41 |.E7.|K@Z[h..6..A| -00000340 b2 fe 7c 39 7e 9f 95 3a 45 2e 9f 96 35 26 81 73 |..|9~..:E...5&.s| -00000350 4d 0f c3 09 61 32 eb 64 4b 46 76 c1 0e ca cf 02 |M...a2.dKFv.....| -00000360 6a f3 75 f3 bf aa b0 f8 43 e3 6b d1 c4 27 3e fe |j.u.....C.k..'>.| -00000370 06 a2 49 e4 bb 56 c5 c0 5d 36 81 06 97 ed ff a2 |..I..V..]6......| -00000380 99 78 43 0a c5 20 df a3 ac b7 8f 61 a2 ff 48 66 |.xC.. .....a..Hf| -00000390 ea c1 b6 57 38 fc 36 7c dd 30 b5 ce 58 b1 18 82 |...W8.6|.0..X...| -000003a0 e5 2a 54 d8 4d da f1 fc 98 06 97 43 d5 dc d9 3e |.*T.M......C...>| -000003b0 d4 f8 a3 76 9c 16 03 03 00 4a 78 c0 f2 02 60 a4 |...v.....Jx...`.| -000003c0 8e 9a cd 31 30 e9 16 df ce 98 bb 95 50 a0 05 48 |...10.......P..H| -000003d0 6c c2 ce c5 e2 77 f2 4a d0 45 80 97 98 d4 38 d1 |l....w.J.E....8.| -000003e0 90 04 91 48 cb 52 40 d3 a4 cb 8d 68 dc 64 9c 07 |...H.R@....h.d..| -000003f0 cb 8c b9 3b f8 44 fe 47 69 67 fb 2d ab 44 db d0 |...;.D.Gig.-.D..| -00000400 58 55 83 81 16 03 03 00 14 51 82 e0 57 8e cb 4a |XU.......Q..W..J| -00000410 d4 59 6e 58 f7 6d 44 3f f5 83 64 52 51 |.YnX.mD?..dRQ| +00000000 16 03 03 00 81 60 70 d6 32 5a 0a 8f df ed cd f2 |.....`p.2Z......| +00000010 d7 bf d0 da fd 53 63 65 bf f5 26 83 0c f5 6e e9 |.....Sce..&...n.| +00000020 78 9b 03 7b 17 5f f4 d2 af 2a a3 85 13 92 be 00 |x..{._...*......| +00000030 93 3f b3 f1 cb 04 aa 55 f8 ed c8 e6 9c 32 08 79 |.?.....U.....2.y| +00000040 86 84 ef ac 72 bd 93 07 9c ca d2 e7 74 dd 51 a0 |....r.......t.Q.| +00000050 6d 0e d3 32 3c 33 9d 58 aa 46 a9 ff 22 08 bc 2c |m..2<3.X.F.."..,| +00000060 de 81 aa a8 5a 3c f8 36 93 d3 12 06 79 61 1f 71 |....Z<.6....ya.q| +00000070 5f 45 d7 99 b2 55 10 22 db 56 d9 39 64 57 ad c3 |_E...U.".V.9dW..| +00000080 59 a9 bd cb f2 22 16 03 03 02 69 34 e7 f2 7a bc |Y...."....i4..z.| +00000090 0b 90 72 a3 3b 6b 38 a3 f8 7a 19 39 ff b4 d6 8c |..r.;k8..z.9....| +000000a0 c9 92 4f a3 23 1a f0 89 bb 01 e4 b2 24 f7 db 3d |..O.#.......$..=| +000000b0 f4 4b 02 75 d0 ca 3c ed e8 d9 13 61 c5 61 4e 7c |.K.u..<....a.aN|| +000000c0 fe b9 49 69 63 cc 23 5f 9b 23 85 ec 86 e5 17 28 |..Iic.#_.#.....(| +000000d0 8a 1e 0c 45 e5 4d c2 be 66 92 47 88 28 ec 52 eb |...E.M..f.G.(.R.| +000000e0 72 e5 30 89 58 8d 15 2b 98 eb cd e2 18 7c 53 f2 |r.0.X..+.....|S.| +000000f0 89 ba 71 a5 91 20 64 17 7c 56 f1 01 8a 52 17 66 |..q.. d.|V...R.f| +00000100 ef d7 bc 5b ff 54 53 13 2e 80 53 4c 84 6d a2 20 |...[.TS...SL.m. | +00000110 0f e6 3d 33 90 7a 5b 1a 50 29 ce 1e af 74 a5 b3 |..=3.z[.P)...t..| +00000120 0e 29 c8 e5 c1 50 b6 5d c8 bb e4 b5 f5 6b 04 a8 |.)...P.].....k..| +00000130 24 a6 a8 cc 77 7c 72 d5 b1 f3 6a 1c 2e d7 7e e0 |$...w|r...j...~.| +00000140 4c 46 3f 26 61 2e 54 7d ab d8 d6 ec 1e b0 0d d1 |LF?&a.T}........| +00000150 02 57 00 7f 29 aa d3 1d a4 40 73 d7 21 12 76 58 |.W..)....@s.!.vX| +00000160 7d 79 a5 c1 d2 57 63 48 0e 63 5f 24 49 8a 57 ba |}y...WcH.c_$I.W.| +00000170 26 1c 39 4a f8 b3 89 79 e2 be 4e 8e 37 ae 16 75 |&.9J...y..N.7..u| +00000180 42 5e 2e 9b 14 d5 b3 06 5f b9 c8 f7 16 8f eb 1c |B^......_.......| +00000190 48 0a da 1e b3 4a 78 f7 f8 b4 35 bf 7d 3f c5 8d |H....Jx...5.}?..| +000001a0 fa 7d c0 b7 52 af d3 13 de 96 39 76 fd 49 80 55 |.}..R.....9v.I.U| +000001b0 bb b3 0f 5b 0c 84 4d 8b da 62 8a 20 4b a1 28 28 |...[..M..b. K.((| +000001c0 3d 74 cc 34 9d 95 8e af c0 05 a2 5c 73 9d 73 d8 |=t.4.......\s.s.| +000001d0 6c 4e 77 25 c5 8c 22 07 c6 b9 55 47 0c b2 12 73 |lNw%.."...UG...s| +000001e0 2e f5 95 f7 28 c3 e4 24 2c fd 05 ac e2 3e df 93 |....(..$,....>..| +000001f0 5a 28 66 aa d4 86 8a 48 e2 c8 69 01 18 90 54 10 |Z(f....H..i...T.| +00000200 67 80 a1 be a8 9a 7f f3 17 ee dc 83 06 7a 70 6c |g............zpl| +00000210 59 c2 2d 8f ff 79 a7 e5 e2 f2 f3 f3 5b 44 42 25 |Y.-..y......[DB%| +00000220 a3 8c a0 83 07 5c f6 73 e9 bd f5 6b 86 89 b4 11 |.....\.s...k....| +00000230 7b 9a 28 52 4f 55 70 4a 75 00 73 cc 84 fa 4a ef |{.(ROUpJu.s...J.| +00000240 f8 8a 8d f9 18 e2 bc 13 48 cb 80 4d 6f fc d7 23 |........H..Mo..#| +00000250 3a 9c 6c fd 46 27 94 8a 3d 9d fb 17 f5 06 4d a1 |:.l.F'..=.....M.| +00000260 18 75 a7 9b 08 f8 47 b5 52 b4 19 4b b7 0f a4 e0 |.u....G.R..K....| +00000270 78 f8 8b a4 cc eb d3 85 e1 ad 21 29 0f c7 09 28 |x.........!)...(| +00000280 3f 21 12 6c fd 76 05 13 10 a0 c1 ce ba 7c e8 6f |?!.l.v.......|.o| +00000290 e9 99 67 0a 9d 3a 7f f1 a6 8a 53 56 f1 09 22 21 |..g..:....SV.."!| +000002a0 24 23 6e bc 77 fc 56 3b 31 15 58 1b e9 03 a1 bf |$#n.w.V;1.X.....| +000002b0 0a 06 a0 fb 47 77 b7 ad 01 db ee 6a bc a4 a1 77 |....Gw.....j...w| +000002c0 6f 3e 70 84 4c a6 21 ec ff fa f0 f0 68 ee 7d b1 |o>p.L.!.....h.}.| +000002d0 e6 37 f1 1c aa 43 c7 b9 0e c4 52 7d 54 d8 f7 c5 |.7...C....R}T...| +000002e0 16 21 99 89 cb 02 d0 54 b8 0e 91 2e 58 25 32 6e |.!.....T....X%2n| +000002f0 fa ae 62 c9 16 03 03 00 bc 0c 2f 7e 22 d8 7f 21 |..b......./~"..!| +00000300 0c 1a ec e1 37 72 3f 03 1d cc 73 f9 63 95 cd 47 |....7r?...s.c..G| +00000310 66 17 60 8c da b4 35 a2 44 b1 d8 d1 1c 98 5b 8b |f.`...5.D.....[.| +00000320 c8 9b c8 cb c4 15 0d 8d 08 1e 7c 3a 6b 20 3a f1 |..........|:k :.| +00000330 d1 86 ae 08 bb fd 74 c5 62 9a 50 74 07 96 10 0e |......t.b.Pt....| +00000340 e0 e4 a4 da c4 9d d1 f4 15 97 7d 21 0f 6f cb 39 |..........}!.o.9| +00000350 8e 4e 40 1a 2a 7f 15 88 94 52 bc fd 61 b8 37 d1 |.N@.*....R..a.7.| +00000360 48 62 bc 53 a3 a6 62 ec 0e c3 1f 82 67 19 71 fa |Hb.S..b.....g.q.| +00000370 99 16 c3 cf d6 82 44 36 9e 0b f0 41 12 ca 7b 67 |......D6...A..{g| +00000380 c3 a6 2d f7 13 14 0f d1 16 f9 2a 5a dd 43 45 c6 |..-.......*Z.CE.| +00000390 c0 f4 17 36 64 11 fc ed e6 66 b6 0c e2 3d fb 72 |...6d....f...=.r| +000003a0 93 27 46 20 db 1b 24 f9 69 a0 c7 71 e2 27 6a 93 |.'F ..$.i..q.'j.| +000003b0 36 73 71 10 bd 16 03 03 00 4a cb 15 91 9c 22 96 |6sq......J....".| +000003c0 f0 c8 b9 4d 9a 6c b0 eb 1a c5 d4 06 12 89 44 1b |...M.l........D.| +000003d0 52 cd fb 32 3f 2c 25 f4 d3 88 0f e4 9c 18 91 59 |R..2?,%........Y| +000003e0 42 98 a8 65 35 62 f7 ce fa a3 56 46 c5 b1 da ac |B..e5b....VF....| +000003f0 9e 4e de 8d 14 fc 3c f3 94 74 50 99 1d 65 6b a6 |.N....<..tP..ek.| +00000400 a9 38 93 9f 16 03 03 00 14 d7 5b 68 ca 4c 80 92 |.8........[h.L..| +00000410 f8 13 5d fe 14 22 6f 9a 42 3a 27 de c8 |..].."o.B:'..| >>> Flow 9 (client to server) -00000000 16 03 03 02 69 96 85 13 d5 b1 07 ec bb 1c c1 be |....i...........| -00000010 a3 42 10 c8 e0 ec f8 f1 67 29 d5 52 ef bb 32 e8 |.B......g).R..2.| -00000020 7b e5 a7 3f ab 71 2d 74 20 f7 8a a7 1f bf 7c 4b |{..?.q-t .....|K| -00000030 8b 95 db 07 3c ad 86 5e b3 98 32 e9 5a ce 96 08 |....<..^..2.Z...| -00000040 c5 64 44 27 fb bc 44 29 49 44 32 3f 64 e8 86 1b |.dD'..D)ID2?d...| -00000050 54 63 74 3d a1 99 4d 4a 3e 5a 76 71 39 81 de df |Tct=..MJ>Zvq9...| -00000060 90 e4 f6 ac 96 15 0b 70 ad 7e 8a 1d 69 86 65 6e |.......p.~..i.en| -00000070 63 bf fb f2 6f 21 d5 66 ad f1 b1 09 05 04 f9 09 |c...o!.f........| -00000080 0e 0c 12 74 c1 cd f1 5e fa f1 1b cd 3b 2b 13 8f |...t...^....;+..| -00000090 fb f6 fd b0 ca ea 73 1b 38 ad db 6b fd 29 34 db |......s.8..k.)4.| -000000a0 51 4a 44 97 a7 2f 2a 98 d6 cc d5 c4 b9 17 23 ab |QJD../*.......#.| -000000b0 09 27 15 a5 35 3b 2b 7e b2 3b fd 12 1b 11 90 4d |.'..5;+~.;.....M| -000000c0 81 1b 84 bb fd 72 09 31 5e 78 0e f6 b6 60 44 bb |.....r.1^x...`D.| -000000d0 6c 06 72 0b ba ba 60 f6 c1 cb 7e 45 a9 25 44 3d |l.r...`...~E.%D=| -000000e0 ba da 71 99 bb 79 b3 73 ef eb c2 cc 07 87 76 f5 |..q..y.s......v.| -000000f0 e9 7c d9 47 8c fc 7d b7 a0 70 72 04 1e 3d 9b 2f |.|.G..}..pr..=./| -00000100 85 9f c8 2f d9 20 4e 00 97 d6 dd dc ae a1 04 96 |.../. N.........| -00000110 83 e1 4f f3 0d ad 9c ce 5f e7 7b 88 7a b7 d2 ce |..O....._.{.z...| -00000120 0a 61 95 d2 78 e3 45 a8 10 5e d9 ae d2 e1 22 bf |.a..x.E..^....".| -00000130 59 9c 4a 2c 28 fb c1 b6 89 3b 65 8c 94 a9 f0 7c |Y.J,(....;e....|| -00000140 86 98 8f 22 c4 18 47 e4 f0 b9 42 dd 34 ab 2a 8e |..."..G...B.4.*.| -00000150 fc 8f ce 09 ec 6f 57 6b d1 ab 32 fd 84 e2 9f 7e |.....oWk..2....~| -00000160 f5 b7 5d 26 aa 37 da e9 f3 18 6f 56 74 03 ff 1e |..]&.7....oVt...| -00000170 87 95 fb 93 57 2e 32 fb b3 cf d2 0d 42 02 4f 6a |....W.2.....B.Oj| -00000180 9e de ee 6a e6 7e e5 d2 ba cb 00 5d ff b4 6d 7f |...j.~.....]..m.| -00000190 23 5e 93 be e9 3a c1 b4 78 30 53 90 07 e4 a7 af |#^...:..x0S.....| -000001a0 da e1 29 7d 50 a5 76 ec a8 5e 96 50 45 26 c4 9d |..)}P.v..^.PE&..| -000001b0 c1 99 98 c6 1a bf 93 c1 63 b3 0a 2d af c8 29 7d |........c..-..)}| -000001c0 ef b2 d3 8f aa 93 fb be 39 c0 a1 65 51 e8 6e c4 |........9..eQ.n.| -000001d0 45 cb 2a 52 b7 ec e0 48 c0 b2 cc c7 72 12 18 e0 |E.*R...H....r...| -000001e0 c7 9f fa 09 97 95 16 9f f4 5d 70 c5 d6 7f 23 d5 |.........]p...#.| -000001f0 53 98 d0 80 50 9b 52 46 11 d4 97 ea 47 26 f5 6f |S...P.RF....G&.o| -00000200 66 7b 8a cc f8 8d 70 c7 ec fa 72 de ba ac d4 b2 |f{....p...r.....| -00000210 be 7d d8 78 44 dd de 66 53 26 f4 c0 8a 67 61 cb |.}.xD..fS&...ga.| -00000220 46 34 3d 6f 9e 9b dc ee 4a b9 5c 67 2b d9 87 2a |F4=o....J.\g+..*| -00000230 35 42 1c 3e b8 08 c9 32 13 a6 6f fc 4d cc be dd |5B.>...2..o.M...| -00000240 ad 76 19 1c 2d b3 6e 04 a1 17 05 93 b9 69 27 42 |.v..-.n......i'B| -00000250 23 13 7b c0 f1 53 9c b5 1d 8e 5c f6 40 7e 5a e9 |#.{..S....\.@~Z.| -00000260 20 dd 18 7a 0c f2 7b 5a ec 3d 4e 3b 29 b2 16 03 | ..z..{Z.=N;)...| -00000270 03 00 35 15 15 54 38 4e 87 f1 c1 9a 90 b2 74 df |..5..T8N......t.| -00000280 72 34 aa 0b 41 f3 df b4 c5 fd 50 00 2a 36 a8 d5 |r4..A.....P.*6..| -00000290 c4 49 ac b8 58 3e 89 48 cb a9 4e b1 a9 0f ee 51 |.I..X>.H..N....Q| -000002a0 37 d3 60 ca 23 76 68 0b 16 03 03 00 98 53 3c 0e |7.`.#vh......S<.| -000002b0 d5 3b d3 78 9f 47 5d 9e 1b b6 04 5f d4 04 66 55 |.;.x.G]...._..fU| -000002c0 68 bd d7 ab 54 b7 e5 9a 12 9b 0c 1d 75 7b c7 35 |h...T.......u{.5| -000002d0 e3 9e 9d a0 8f 61 7a 32 d1 a7 23 2a b6 ba 48 7c |.....az2..#*..H|| -000002e0 1a 62 66 61 b4 3d e8 e3 a9 4e 85 7a 8d 5b f3 69 |.bfa.=...N.z.[.i| -000002f0 c8 bc 0a 8a c7 e4 df 78 9b a8 cf 1d 37 14 90 a5 |.......x....7...| -00000300 a8 ce f7 1f e7 a3 e5 d8 97 be 95 fd d3 c0 d0 81 |................| -00000310 bf a6 e1 b3 6b 29 ee c6 16 3c 4c 68 6e b4 42 72 |....k)...<Lhn.Br| -00000320 84 a0 97 0f 0e b2 44 0c 4f c6 df 04 b7 bf d8 e7 |......D.O.......| -00000330 08 af 33 35 56 ed 6b cc 42 a8 9f 8e 59 9c 9c 32 |..35V.k.B...Y..2| -00000340 29 77 87 6e d6 14 03 03 00 11 97 7a db d1 50 96 |)w.n.......z..P.| -00000350 68 b7 04 90 79 fd f3 79 ed f3 de 16 03 03 00 20 |h...y..y....... | -00000360 16 57 80 e9 30 65 46 29 74 09 32 70 13 1f f8 5d |.W..0eF)t.2p...]| -00000370 54 3f 14 4b af a1 51 b3 cd 1f e6 01 d6 68 11 fc |T?.K..Q......h..| +00000000 16 03 03 02 69 aa 39 9e c8 e7 89 97 7f 22 3c 28 |....i.9......"<(| +00000010 76 ac d9 48 51 e0 cd 22 53 a1 6d e7 b4 00 27 7d |v..HQ.."S.m...'}| +00000020 89 4b f0 54 d8 39 d0 a3 fc 35 a6 36 4b 3c eb 3a |.K.T.9...5.6K<.:| +00000030 00 b0 c1 17 9d c8 13 a5 58 ba 16 9e cb 21 50 dd |........X....!P.| +00000040 8a e0 2d 57 dd a6 bf 4d 6e b3 21 3b 46 f4 c3 77 |..-W...Mn.!;F..w| +00000050 a1 86 07 c7 db e9 0a cb 2d 0f ff b5 1b ad 6b c4 |........-.....k.| +00000060 c4 a4 4e 14 cf cb b2 6c 07 65 17 d2 db 30 e9 ec |..N....l.e...0..| +00000070 41 4e 78 26 12 27 08 a6 a7 84 39 c0 4b e7 4b 23 |ANx&.'....9.K.K#| +00000080 2f ca ff 1e 41 9a e8 44 fc 5d a0 34 4e ca a8 6d |/...A..D.].4N..m| +00000090 31 51 57 c9 7e d1 0a 42 22 f2 b4 f9 a7 f9 28 d8 |1QW.~..B".....(.| +000000a0 2a dd 19 0d 90 8b e1 78 b1 1c da 3a bb 5e 05 54 |*......x...:.^.T| +000000b0 0d 0e f8 73 ed 01 e2 e4 d4 c1 f8 fa c3 d6 6f 42 |...s..........oB| +000000c0 cc cb 99 99 97 18 b0 fb ab 51 42 66 45 67 b6 29 |.........QBfEg.)| +000000d0 02 60 ab 74 30 db f6 16 8a 8f 8e 9c cc d5 47 fa |.`.t0.........G.| +000000e0 f5 af 94 4f b1 94 40 57 ab 85 59 e4 3e cc c5 a0 |...O..@W..Y.>...| +000000f0 61 b7 64 f9 dc 96 40 ae fb 4c 57 39 9e 9a 23 8e |a.d...@..LW9..#.| +00000100 c9 36 6c 75 11 c7 6e 54 c3 1c e9 25 6a a0 f8 bb |.6lu..nT...%j...| +00000110 6b 5c ca 5c 06 6c 03 88 01 27 4c 89 02 e6 b6 1a |k\.\.l...'L.....| +00000120 92 99 4d 15 c1 1a aa 58 20 49 d7 4a f9 09 34 1e |..M....X I.J..4.| +00000130 d7 d8 31 79 9f d8 b3 a0 76 ba 96 77 77 77 5b 80 |..1y....v..www[.| +00000140 88 ab a0 90 c7 5f 3d 82 e1 23 29 6e 3a 4d 9b f0 |....._=..#)n:M..| +00000150 7b 6a b1 9d 78 ba 4c 7e 02 1f a0 73 3e 91 cf 75 |{j..x.L~...s>..u| +00000160 c6 52 2d c6 79 be 85 65 0e e4 73 39 fe 53 6d e0 |.R-.y..e..s9.Sm.| +00000170 a3 18 d5 69 80 ca f1 c8 ad f5 f4 fb b5 40 2e f8 |...i.........@..| +00000180 30 82 ca 2c 46 6a ab a6 b2 83 9f a8 95 95 30 e3 |0..,Fj........0.| +00000190 e3 30 6d f5 7c 83 96 af 12 d8 d6 d6 f9 6a ad bd |.0m.|........j..| +000001a0 bb 96 83 99 99 d8 6d 20 0e e1 be da 58 05 44 88 |......m ....X.D.| +000001b0 a6 07 47 84 d4 77 fc 9b fb d7 ac 60 70 0b e7 76 |..G..w.....`p..v| +000001c0 13 c7 38 d9 3d 60 eb a6 9f a5 6d fc 5c d5 f6 2f |..8.=`....m.\../| +000001d0 31 02 38 65 8d be 04 06 84 95 86 b1 84 d9 ce c7 |1.8e............| +000001e0 30 b9 d3 85 9f 1b 12 0f 5c 0e d6 8d e3 a0 15 04 |0.......\.......| +000001f0 03 62 9d 52 7b e7 f4 13 aa 02 64 d9 d4 4b fd 6f |.b.R{.....d..K.o| +00000200 de ea 4a aa 91 60 e7 78 af 84 b5 9d c3 d2 c6 3a |..J..`.x.......:| +00000210 2a 9f 9b c6 8d 9e 5e 2c 90 6c d3 9d c1 be 96 5a |*.....^,.l.....Z| +00000220 60 d8 73 6c 49 50 c8 03 ec 58 73 bc b3 8c 30 c1 |`.slIP...Xs...0.| +00000230 f4 a2 7d 74 3d 8d 7e 64 c1 a7 b6 24 13 06 72 1b |..}t=.~d...$..r.| +00000240 d0 87 22 af df 2a e7 fe 57 fa db e7 00 ba 74 35 |.."..*..W.....t5| +00000250 16 34 20 3f 75 69 35 5f 64 7e 26 56 7c 93 05 4e |.4 ?ui5_d~&V|..N| +00000260 42 65 b8 bf 59 8e 82 13 f1 d0 05 95 c2 3d 16 03 |Be..Y........=..| +00000270 03 00 35 99 1d 52 84 73 d6 e7 90 f6 41 9e 69 07 |..5..R.s....A.i.| +00000280 39 0b bc b6 c7 f4 f2 a0 93 80 b9 c7 bb b4 a6 06 |9...............| +00000290 50 5b 5d 75 97 cf c5 dc 2d 07 3d 8f 9e ae fa bf |P[]u....-.=.....| +000002a0 5b 6b 3e 98 02 fd e4 7d 16 03 03 00 98 80 ac e9 |[k>....}........| +000002b0 4e e0 f8 b5 8c c2 2e 84 ec e0 3b eb b7 a0 14 2d |N.........;....-| +000002c0 ff d2 bf 35 14 20 06 00 2e 48 c7 f8 a3 fd 4f 50 |...5. ...H....OP| +000002d0 4a 04 3e c7 07 50 90 72 29 f0 5c ac e1 fd 9d 3f |J.>..P.r).\....?| +000002e0 42 99 77 32 a9 79 24 7f 9e cc 84 1c d0 db 87 1c |B.w2.y$.........| +000002f0 3c 9a ae e3 45 e5 67 83 5f 75 e9 27 f3 ef 8a 15 |<...E.g._u.'....| +00000300 88 2b 3f cc 6f 6f a4 78 d5 b2 96 3e 72 d4 c8 43 |.+?.oo.x...>r..C| +00000310 98 a7 60 ae 38 8e fe 21 49 5b c2 80 d6 ef 6f 9b |..`.8..!I[....o.| +00000320 08 18 07 c2 64 00 a1 a0 09 8b b4 b7 eb 0c 68 30 |....d.........h0| +00000330 26 87 f9 99 85 63 35 81 5a e4 31 19 9e f8 b8 7b |&....c5.Z.1....{| +00000340 81 aa 24 ff cd 14 03 03 00 11 84 c7 e1 8f 74 66 |..$...........tf| +00000350 e6 bd 14 55 a8 d3 67 30 2d c4 fb 16 03 03 00 20 |...U..g0-...... | +00000360 3a 63 a5 86 f3 78 f1 62 18 77 f7 25 71 52 56 17 |:c...x.b.w.%qRV.| +00000370 d2 a5 e4 fa bc bb 44 07 85 37 cb 36 84 c7 6a 97 |......D..7.6..j.| >>> Flow 10 (server to client) -00000000 14 03 03 00 11 1b a8 a8 a9 c6 a8 85 60 bc 14 0d |............`...| -00000010 86 ce a5 0f 45 17 16 03 03 00 20 cb 3a 73 db 55 |....E..... .:s.U| -00000020 05 7e 3e 4b 6d d0 eb ca 68 39 bf 71 ba 6c e5 0c |.~>Km...h9.q.l..| -00000030 a7 90 d6 c1 b8 55 87 c6 20 40 35 17 03 03 00 19 |.....U.. @5.....| -00000040 28 50 71 7c f0 7c 1e 61 fb de 5d d1 bb 77 f6 c8 |(Pq|.|.a..]..w..| -00000050 a4 76 8d ab d4 c2 fe 27 96 16 03 03 00 14 e4 7e |.v.....'.......~| -00000060 51 bb 26 a8 9c 0c b0 25 7a 57 b9 98 c2 20 5a 50 |Q.&....%zW... ZP| -00000070 07 ca |..| +00000000 14 03 03 00 11 9e 99 89 2d 10 21 a1 38 04 77 1a |........-.!.8.w.| +00000010 f8 1d b4 01 d1 9f 16 03 03 00 20 2a cb 67 8b 1b |.......... *.g..| +00000020 44 26 41 7b c4 6d a1 f4 cb ee 15 87 01 65 18 5a |D&A{.m.......e.Z| +00000030 c7 2d 10 e4 91 01 cb 22 e8 92 1a 17 03 03 00 19 |.-....."........| +00000040 1a 46 a0 9a c5 1a 27 0c e2 f9 03 55 3a e8 43 a7 |.F....'....U:.C.| +00000050 d7 47 a5 95 6a e7 a1 12 69 16 03 03 00 14 d6 e0 |.G..j...i.......| +00000060 1d 89 e0 c2 9a 52 d5 bc d4 08 3e f6 81 dd 57 a2 |.....R....>...W.| +00000070 25 f6 |%.| >>> Flow 11 (client to server) -00000000 16 03 03 01 16 66 3c 1a 62 c3 4a f9 e4 66 01 d4 |.....f<.b.J..f..| -00000010 f7 e8 5a fb 95 c4 40 33 d4 af 61 78 d6 54 91 2b |..Z...@3..ax.T.+| -00000020 62 72 d5 7b b8 2c 71 11 4e 0c 2d 79 6d 41 b1 9e |br.{.,q.N.-ymA..| -00000030 df 59 d8 e0 5c 72 98 b5 29 55 1e 9b 01 a5 af 2c |.Y..\r..)U.....,| -00000040 c3 87 4b f0 c8 ca 4d 56 fb 3a 7e 04 e5 b6 4f 6d |..K...MV.:~...Om| -00000050 1e 53 26 5d af fb 17 ee 97 87 45 2f df 1b 21 80 |.S&]......E/..!.| -00000060 21 81 2b 18 2d 2d e9 3c c4 01 32 91 b7 88 27 9e |!.+.--.<..2...'.| -00000070 26 40 e7 6a 27 c5 a0 b4 a3 ed 4d 4b a4 e3 0b c7 |&@.j'.....MK....| -00000080 49 42 ca ef e9 16 5c 98 8d ab fc 7d 00 83 03 89 |IB....\....}....| -00000090 a4 97 1e 3f 9e d8 ba c5 f5 2a 0b 0a ed a0 a5 59 |...?.....*.....Y| -000000a0 27 03 36 7e 94 d8 9a 3c fc f6 f6 52 b6 a7 fa 36 |'.6~...<...R...6| -000000b0 04 83 2f e7 99 e5 1c 56 27 48 13 a0 59 ca ca 3b |../....V'H..Y..;| -000000c0 36 2d 25 e8 6f 6a cb 07 74 f8 1b 7d ba 3e 6e e1 |6-%.oj..t..}.>n.| -000000d0 1d 3e 93 c6 23 f4 eb bf ad 62 21 1a da 53 e1 13 |.>..#....b!..S..| -000000e0 0a 3a 9c 57 48 d5 ee d3 72 af c3 74 fc 74 67 7d |.:.WH...r..t.tg}| -000000f0 b4 76 fc 21 55 67 49 92 fc 71 5d 42 69 d6 01 b5 |.v.!UgI..q]Bi...| -00000100 83 4e b8 cd f9 ed 28 41 ae 95 2f d6 69 b0 d3 b8 |.N....(A../.i...| -00000110 bd 06 d6 00 74 44 c9 47 aa 8e 1d |....tD.G...| +00000000 16 03 03 01 16 27 50 ce c0 8e 5a e2 54 55 cb c0 |.....'P...Z.TU..| +00000010 08 c7 20 87 7e 78 c6 da a6 7a 62 fd 7f f5 87 b3 |.. .~x...zb.....| +00000020 83 a0 c8 70 ab 57 9b ca bf 4c 07 06 f1 89 b9 b6 |...p.W...L......| +00000030 24 f0 ae 72 e1 36 31 9f 74 ed 06 ad 44 3b 51 2c |$..r.61.t...D;Q,| +00000040 ed f0 c2 d8 9b 27 d2 9a ec 44 88 80 7c 5a d0 66 |.....'...D..|Z.f| +00000050 3d 84 e3 7c 24 89 b9 dd 8c eb 86 cd ce 69 0d e3 |=..|$........i..| +00000060 97 ee ad 74 53 7f 9c f0 05 31 43 2a 8c 09 c4 11 |...tS....1C*....| +00000070 46 3e 82 2c 3c 69 91 d1 eb 4b 8a ab a9 cb 24 00 |F>.,<i...K....$.| +00000080 00 25 bd 26 d3 85 19 ff 3b 2b 92 3f 43 b0 9f 24 |.%.&....;+.?C..$| +00000090 59 4f 3d a6 ce 65 27 5c 75 47 92 7b 4a d3 ca 55 |YO=..e'\uG.{J..U| +000000a0 38 00 ac 37 0c 6e 2d 04 bc 6e fe 3a 9a 43 b6 7f |8..7.n-..n.:.C..| +000000b0 18 c1 a6 ce 49 b4 61 d3 97 8d a2 c9 fb fb cd 23 |....I.a........#| +000000c0 f6 2f 0c 0b 2a b8 31 9e fd ff 9f 44 1e 33 c3 23 |./..*.1....D.3.#| +000000d0 bf 09 d2 de 90 b6 61 9c 33 33 33 46 bc 00 7e 16 |......a.333F..~.| +000000e0 3c bd 82 2d 31 51 5b 11 87 ec 7f 25 d8 95 f9 9c |<..-1Q[....%....| +000000f0 df 00 54 40 f3 c1 08 fa ef ba bc 5d b1 96 ae 8f |..T@.......]....| +00000100 35 0e 43 b2 50 c7 7e c4 b2 71 2e 40 3a b7 90 2b |5.C.P.~..q.@:..+| +00000110 81 ac 00 14 9d da d8 ca 5e 25 62 |........^%b| >>> Flow 12 (server to client) -00000000 16 03 03 00 81 d3 99 6f 14 2b a1 f4 d7 45 c9 94 |.......o.+...E..| -00000010 69 0b b3 72 f4 2c 2e 5c 80 96 09 20 2f 63 a1 e4 |i..r.,.\... /c..| -00000020 8b df d7 22 11 71 bd 17 db da 2d c6 78 e8 9a 95 |...".q....-.x...| -00000030 6b 39 34 a2 13 7f 39 77 8b e5 1b 6c 4b 20 79 40 |k94...9w...lK y@| -00000040 a1 d9 69 89 b1 e2 60 8a 75 88 ae 83 b9 4f 42 a4 |..i...`.u....OB.| -00000050 c9 c7 44 ac 0d 3f 1c ca 49 f9 a7 05 e2 c7 05 cd |..D..?..I.......| -00000060 30 30 d2 f9 c2 87 60 33 3b 25 d0 e0 5e c2 bd 98 |00....`3;%..^...| -00000070 9c 51 d8 38 c9 ef 04 f4 39 30 50 b6 35 53 f6 95 |.Q.8....90P.5S..| -00000080 eb 5d 67 05 62 9a 16 03 03 02 69 39 94 a1 8d 01 |.]g.b.....i9....| -00000090 37 64 c6 be bb 9c 22 9d 56 e8 68 ab 0f 7a 3a e7 |7d....".V.h..z:.| -000000a0 2d 26 b7 ba 3e 54 38 b3 32 9d 7b d7 43 c4 d2 b3 |-&..>T8.2.{.C...| -000000b0 9a 84 62 73 03 7a f2 68 ec 3e 41 d2 68 c9 22 1a |..bs.z.h.>A.h.".| -000000c0 e9 4d 9c e8 80 6a a9 9e 6a bd 67 5d 77 97 8b f7 |.M...j..j.g]w...| -000000d0 32 cb 3a cb c2 c0 a1 40 7e 63 81 5f 19 a5 71 20 |2.:....@~c._..q | -000000e0 c3 76 88 ae 5c d4 bd 54 08 e7 7e e7 77 7e 3d 91 |.v..\..T..~.w~=.| -000000f0 b5 40 f7 7e 95 d5 e3 f2 e5 4a 57 f6 d9 94 df 07 |.@.~.....JW.....| -00000100 56 45 09 c4 bc 65 05 04 57 f4 00 c5 91 4c dc 4d |VE...e..W....L.M| -00000110 a0 1e c6 e2 37 35 d0 5a e9 79 ce f5 91 6d 3e 39 |....75.Z.y...m>9| -00000120 c3 68 6a 76 6d f3 29 1d e0 ef b2 20 3e 2a ac 11 |.hjvm.).... >*..| -00000130 7e 11 2d a3 84 60 94 b5 8e 3a e6 4b 34 70 aa f8 |~.-..`...:.K4p..| -00000140 e3 f9 0f 2c a4 bf 5b 27 7e c9 5e 6f c0 11 b4 ff |...,..['~.^o....| -00000150 53 6b 98 ee 20 77 87 87 fc 8e 30 1b 8f 74 29 af |Sk.. w....0..t).| -00000160 a2 c7 e8 c1 da e5 d7 0f 70 ec 27 23 46 3f 16 b1 |........p.'#F?..| -00000170 59 bd 43 76 09 1d 8c f4 eb 17 10 a5 c1 1a e0 c6 |Y.Cv............| -00000180 45 e2 d2 dc 6d f4 9a 87 36 ef 71 18 5c 1d e7 7c |E...m...6.q.\..|| -00000190 40 d6 4c 16 ee 58 75 d7 56 9f 2e 17 80 1d 74 1c |@.L..Xu.V.....t.| -000001a0 fd 86 7c 2b 05 ac ef 07 18 a3 98 73 fa 9c 16 6c |..|+.......s...l| -000001b0 14 95 37 91 1e a2 c7 47 a8 87 11 35 30 d8 ed 60 |..7....G...50..`| -000001c0 ba 65 ee 66 2b 1f db 67 c2 d0 71 26 3d ae 17 94 |.e.f+..g..q&=...| -000001d0 f0 f6 65 01 bb 1d 85 7e b3 d8 2c f1 96 c5 d5 e0 |..e....~..,.....| -000001e0 97 a4 3e df 97 ff 8f 4b e3 72 49 c4 5b 87 4e 06 |..>....K.rI.[.N.| -000001f0 93 11 75 04 7b 80 9d 1c a7 85 a3 2c f1 16 8a b9 |..u.{......,....| -00000200 78 6b 27 1e 9a e3 86 eb f9 42 95 10 02 d5 b6 01 |xk'......B......| -00000210 b3 94 04 63 49 50 9e 11 71 07 aa a1 d6 9d d1 db |...cIP..q.......| -00000220 f4 ea 2e bb fa ca 1e 00 53 75 70 de 0a 72 eb 55 |........Sup..r.U| -00000230 ab b7 ff 30 ad 5e 7e 13 90 75 42 5d 07 07 21 0f |...0.^~..uB]..!.| -00000240 db a6 f4 61 9c bf 31 34 e4 98 bb c4 ac 41 2d 76 |...a..14.....A-v| -00000250 fb 6c 30 b0 e2 98 5f ed d9 a8 42 d7 75 a1 bc 36 |.l0..._...B.u..6| -00000260 f2 3e c5 ac 50 ae c7 2e 42 35 6c 1a 47 aa 1f 0a |.>..P...B5l.G...| -00000270 2f ff 6e 0a a5 c4 b5 a5 92 3f 54 d0 4e 62 6e 3e |/.n......?T.Nbn>| -00000280 cb 07 2d 4d 1a fb 94 5b f8 d0 5b 26 34 2b 1b 26 |..-M...[..[&4+.&| -00000290 8c dd 91 a7 66 21 89 d0 11 24 a5 5f 99 ae 62 84 |....f!...$._..b.| -000002a0 34 9c d2 45 71 74 8c 68 db 8b ad 6f df 08 35 38 |4..Eqt.h...o..58| -000002b0 ed 5c 3b 3e 55 a1 c3 16 b6 61 f4 4d 6d d0 2a 5d |.\;>U....a.Mm.*]| -000002c0 10 fb 64 c9 6f 87 6f 3d ff d1 a0 97 64 b4 12 f9 |..d.o.o=....d...| -000002d0 2a a8 46 59 1b e4 6b d8 c9 3e ac 14 00 4f 1a e6 |*.FY..k..>...O..| -000002e0 26 9b 86 32 a3 9b 37 eb c1 cf 9a 70 16 2e 4a b0 |&..2..7....p..J.| -000002f0 6e e5 fc c2 16 03 03 00 bc bf c4 ea e0 dc be fe |n...............| -00000300 33 7f ef 2b d9 50 f7 87 d5 30 2b 09 bb 63 1e 4c |3..+.P...0+..c.L| -00000310 9c 3c a9 10 4e 04 e1 85 29 44 f9 ea 32 61 12 6e |.<..N...)D..2a.n| -00000320 63 0f d9 e7 e9 c8 81 a0 eb 4e fe 90 bf f4 f4 af |c........N......| -00000330 22 66 21 86 dc 2c f6 ed b1 be eb b1 ac 14 f5 ce |"f!..,..........| -00000340 6c b9 a8 45 e4 3f 09 d1 b1 f3 69 f7 df c4 f0 6c |l..E.?....i....l| -00000350 48 f6 15 80 8a b8 b0 39 0e e9 22 9a 5c 72 f9 fa |H......9..".\r..| -00000360 95 01 9d ca e4 68 ef 72 e2 34 28 a5 04 5d d2 30 |.....h.r.4(..].0| -00000370 c6 33 80 a8 f1 8f fb 6c ec 15 c3 7c 68 7c a2 2e |.3.....l...|h|..| -00000380 4d ba 64 af fb f5 b8 f7 6b 6b 8c 5c 56 dc dd 69 |M.d.....kk.\V..i| -00000390 39 d8 73 75 e3 be 17 09 3f 80 ed cc 12 5b ca d9 |9.su....?....[..| -000003a0 e6 e2 50 88 41 0b 39 8e 84 6f fb 6a c3 8e 4f fc |..P.A.9..o.j..O.| -000003b0 dc 18 ca 02 18 16 03 03 00 14 5e ac 52 4d 0b 89 |..........^.RM..| -000003c0 33 7d fe 1c d9 b5 1d 1c 2b 6d d4 4f 12 33 |3}......+m.O.3| +00000000 16 03 03 00 81 37 3a f4 1b 6a 43 d2 6a 02 02 33 |.....7:..jC.j..3| +00000010 b9 d5 9a 5c d1 3b 52 73 f2 27 a6 c0 f0 9b dd f3 |...\.;Rs.'......| +00000020 d7 cd 89 ec 21 e0 d3 2f 4d 6c b0 cf 50 a7 39 43 |....!../Ml..P.9C| +00000030 c2 56 d2 f8 45 d7 3c a6 b6 b9 06 3f ca a7 f8 37 |.V..E.<....?...7| +00000040 4c 89 01 49 82 5f 27 15 3c bf f0 86 7c 1a 84 03 |L..I._'.<...|...| +00000050 5a 90 77 03 01 fd b8 60 2a be cc 60 c6 54 b5 ec |Z.w....`*..`.T..| +00000060 c1 5d 6b e6 f0 2c 8c e6 7e e3 b6 c3 8b 63 3c 69 |.]k..,..~....c<i| +00000070 ac 2c 9a 24 a7 77 5f 0c 36 08 68 6c 8b 76 f1 80 |.,.$.w_.6.hl.v..| +00000080 4a bf f7 e6 15 5b 16 03 03 02 69 a1 ce a6 de 44 |J....[....i....D| +00000090 cf d6 f7 88 f4 da 01 06 2b e5 cf 54 8d f6 78 ab |........+..T..x.| +000000a0 53 c5 ea d9 97 4b 94 22 24 9b 98 ba ba ee 42 9d |S....K."$.....B.| +000000b0 c3 e4 12 e3 be 35 24 86 3d 38 a0 6e b7 e6 cf dc |.....5$.=8.n....| +000000c0 e7 5c e1 0d 7c 05 bb 63 7c 8b c4 a4 db 9a 85 a4 |.\..|..c|.......| +000000d0 ba d6 d4 79 38 79 01 52 2d cf c1 c7 6e 09 64 ff |...y8y.R-...n.d.| +000000e0 e9 b6 3e f2 a0 2b 4c 91 3f e2 fe 1a 40 4b 14 ea |..>..+L.?...@K..| +000000f0 77 8f 40 1c a2 96 7c d3 ce 34 5e d8 13 5a 82 33 |w.@...|..4^..Z.3| +00000100 41 59 fa d9 81 1c 85 41 9c 61 b9 ca d5 46 e2 77 |AY.....A.a...F.w| +00000110 3d a9 50 4f 11 b1 34 aa ae fd e5 ec fe 12 e6 10 |=.PO..4.........| +00000120 36 84 fb 25 f8 a4 6f 44 e3 ac 89 67 e4 9a 02 c4 |6..%..oD...g....| +00000130 8f a9 4a d0 f4 64 e2 de da 80 02 60 cb a9 2d e0 |..J..d.....`..-.| +00000140 fa d9 b9 ee 43 e1 3e ed 79 79 6b 21 62 3d 6f b0 |....C.>.yyk!b=o.| +00000150 77 53 db 26 60 e1 d6 ff a7 01 2b b7 f0 49 df b8 |wS.&`.....+..I..| +00000160 bc d9 ac 77 80 f8 53 66 16 8d 3a 8d 63 fa 12 e1 |...w..Sf..:.c...| +00000170 ed f7 8b c0 40 46 16 70 e3 db f3 38 87 9f 11 eb |....@F.p...8....| +00000180 0b f5 b3 44 e4 16 e1 ed 85 e6 67 d5 35 60 20 99 |...D......g.5` .| +00000190 7d bd 9f 65 b9 52 68 6c 6b 83 f9 06 e3 a7 3e 0f |}..e.Rhlk.....>.| +000001a0 9e 7c a5 ac 87 7a 45 53 a5 3f 27 5b 99 a9 34 c2 |.|...zES.?'[..4.| +000001b0 5a 44 9a 30 08 30 c6 ff 60 8a a5 72 f7 49 d3 7c |ZD.0.0..`..r.I.|| +000001c0 1f f9 8b 74 a0 b1 c8 65 84 6d 91 86 ab 1e 82 3b |...t...e.m.....;| +000001d0 d5 c4 bb 06 b3 31 61 bb 0e 65 3e 18 4d 0c c1 c1 |.....1a..e>.M...| +000001e0 9d 7f ea ad cf 53 2e 9c 1c 7e aa c8 84 9e 0d ce |.....S...~......| +000001f0 91 53 3c d4 05 7e 57 d1 8b 55 ea e4 6e 57 90 4c |.S<..~W..U..nW.L| +00000200 bb 74 9c 87 1c 6a 89 cf 2c 50 8d 04 04 e6 18 c8 |.t...j..,P......| +00000210 0c 9f 38 84 f4 f4 94 8d 33 2b a1 27 0b 5c 6a 2a |..8.....3+.'.\j*| +00000220 0c 13 b7 07 b7 a0 c9 e5 3c 9d 5a 7e 96 c9 53 fc |........<.Z~..S.| +00000230 ff c4 3a 8f 16 1f 2d 64 50 1d 13 c3 55 fb af d2 |..:...-dP...U...| +00000240 0e f9 e6 18 e3 62 ce 6a 8f 96 ff 00 0e fe 27 53 |.....b.j......'S| +00000250 70 57 53 2d fd f3 02 c7 fe b3 19 49 88 27 7e a2 |pWS-.......I.'~.| +00000260 42 7b 22 d0 77 4e e5 04 aa 0d b6 9d b9 48 97 ab |B{".wN.......H..| +00000270 33 e7 14 97 65 82 f9 2c dc 71 9e 4b eb ed 42 73 |3...e..,.q.K..Bs| +00000280 c6 c8 93 8a 3a 24 bd f9 b4 6a 95 c1 1b 22 1d f5 |....:$...j..."..| +00000290 c8 33 c5 38 1e a7 2e 91 68 35 4c 0a 37 57 ac e2 |.3.8....h5L.7W..| +000002a0 c9 37 9e d9 1c b8 76 73 c2 d2 0c d0 c4 a1 c0 d5 |.7....vs........| +000002b0 72 39 bf 03 f7 8d db e0 8f fe e2 d6 d0 d4 cc bb |r9..............| +000002c0 7d 78 c6 c5 13 a8 4e 45 1e 66 60 77 fe 26 4d 18 |}x....NE.f`w.&M.| +000002d0 90 e8 e1 0c 5b 2b 25 9b ee 6d 76 3f f6 23 a2 26 |....[+%..mv?.#.&| +000002e0 52 8d a9 4e 7f ed 8e e2 6d 7c b4 eb 25 46 54 27 |R..N....m|..%FT'| +000002f0 e2 2d 2c 59 16 03 03 00 bc 6e c1 fb 66 55 ca ea |.-,Y.....n..fU..| +00000300 56 62 78 2f fd c4 ff da 78 dd e7 4d 34 59 a5 8f |Vbx/....x..M4Y..| +00000310 05 ab ac 7f 80 35 f6 de 9d 3f fe 4b d4 79 07 3b |.....5...?.K.y.;| +00000320 c0 8d 02 b8 1a 28 b5 eb 9b 55 6c 26 12 8d 38 01 |.....(...Ul&..8.| +00000330 55 ed 28 68 aa 48 13 61 d3 fe 29 f0 fe 18 4e ae |U.(h.H.a..)...N.| +00000340 6e f9 47 7c 65 91 f9 5e 17 80 68 fd 19 4d ed 17 |n.G|e..^..h..M..| +00000350 7f 11 c4 15 5d 4b fc ea a7 5c df 76 a0 08 2e 15 |....]K...\.v....| +00000360 d1 c6 ae 7b 0d 1f 79 d7 0c 59 6b 53 46 b6 c0 2b |...{..y..YkSF..+| +00000370 ce 09 39 12 7a df f6 7d a2 4b 86 2a df ab b8 7c |..9.z..}.K.*...|| +00000380 07 10 3c 34 cd 15 4c ac 68 a4 28 8a f8 fc 30 a4 |..<4..L.h.(...0.| +00000390 4f 15 77 b4 91 ca 02 ee bb 64 36 90 1b 4b 9d 2b |O.w......d6..K.+| +000003a0 72 e7 dc 10 bd 83 97 18 3c 56 68 58 c9 e3 22 df |r.......<VhX..".| +000003b0 33 43 81 7d 5f 16 03 03 00 14 a8 eb 40 73 19 19 |3C.}_.......@s..| +000003c0 22 10 63 ed f0 6d 73 8c f4 bd f9 ba ad 2e |".c..ms.......| >>> Flow 13 (client to server) -00000000 16 03 03 00 35 a4 b8 43 07 6e 71 c9 b4 fa e1 9c |....5..C.nq.....| -00000010 a7 9d 0b 47 d8 ea 8b bd ea c2 f5 bf 36 fa 88 95 |...G........6...| -00000020 3b 98 b3 7e 19 21 9b 0f 58 76 e8 de 5b 24 d3 b5 |;..~.!..Xv..[$..| -00000030 81 bd 11 ce 86 02 b0 d1 3b ac 14 03 03 00 11 3f |........;......?| -00000040 4e a4 96 06 71 44 5f 57 30 5e 1a bc 22 8d 42 97 |N...qD_W0^..".B.| -00000050 16 03 03 00 20 23 e7 90 a5 0a 32 b4 69 06 d7 77 |.... #....2.i..w| -00000060 df ef f6 2f b8 d8 22 39 08 4f 39 02 e0 7f 62 93 |.../.."9.O9...b.| -00000070 02 b9 8e a5 b6 |.....| +00000000 16 03 03 00 35 67 14 4b ca 21 7f d2 82 1d 2e b3 |....5g.K.!......| +00000010 1a 82 ae 2d d9 d6 7c 76 94 78 d4 ec 0e 4d fe 5c |...-..|v.x...M.\| +00000020 d5 56 5e 6d 32 f4 a0 64 50 1e f6 e4 32 28 92 80 |.V^m2..dP...2(..| +00000030 d4 15 1c d5 f6 52 fc ca c0 e7 14 03 03 00 11 df |.....R..........| +00000040 9d f3 d1 64 92 92 7e 11 77 64 e5 67 01 33 49 17 |...d..~.wd.g.3I.| +00000050 16 03 03 00 20 c8 0f d9 d2 c8 b7 d6 a5 ac 2c 33 |.... .........,3| +00000060 f8 77 8f b1 df db 16 de 43 6c e6 5a eb a0 6e ff |.w......Cl.Z..n.| +00000070 be 1d 69 ab 30 |..i.0| >>> Flow 14 (server to client) -00000000 14 03 03 00 11 0e 2d 1e 73 95 29 15 86 03 a2 da |......-.s.).....| -00000010 6c f4 d2 02 2c 57 16 03 03 00 20 cd a2 f5 b6 da |l...,W.... .....| -00000020 0c 35 45 96 54 c3 96 5d d8 e6 03 49 7b 5c d4 6f |.5E.T..]...I{\.o| -00000030 02 da 27 9e 2f a7 09 57 1b de 7b 17 03 03 00 19 |..'./..W..{.....| -00000040 18 06 7d aa 5c 93 a9 b3 d3 14 0b 76 78 a2 57 73 |..}.\......vx.Ws| -00000050 2f a3 4f 66 c4 b3 ee 21 95 |/.Of...!.| +00000000 14 03 03 00 11 6e 2c 51 c5 dd fa 70 2a 34 e0 cc |.....n,Q...p*4..| +00000010 3c 9f b8 66 15 e6 16 03 03 00 20 78 02 96 c6 24 |<..f...... x...$| +00000020 57 ca 4a 60 47 68 f6 5a 13 8b 3b ce 90 60 d2 e3 |W.J`Gh.Z..;..`..| +00000030 1b d8 ab 1c df d4 5e c2 8d 5c 5b 17 03 03 00 19 |......^..\[.....| +00000040 b7 15 fb 91 10 48 ae 25 0c cd 4f 06 fa 2a 59 49 |.....H.%..O..*YI| +00000050 2f 18 5e 7e 36 1b 2e cb 3a |/.^~6...:| >>> Flow 15 (client to server) -00000000 15 03 03 00 12 55 f7 2f b2 a2 e7 59 6c f6 a9 2d |.....U./...Yl..-| -00000010 d1 17 88 01 49 c6 f2 |....I..| +00000000 15 03 03 00 12 c3 ff f7 b3 dc d4 b3 f5 d4 7c a3 |..............|.| +00000010 18 db 08 a2 50 ad 75 |....P.u| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected index 441fa0f..784bcef 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 bb ec 39 c5 f2 |....Y...U....9..| -00000010 dd a8 26 56 80 09 60 f5 d8 0a 93 6d 08 c4 30 c2 |..&V..`....m..0.| -00000020 cf 0c 44 86 49 a3 19 84 20 38 98 20 0d 8b 81 b5 |..D.I... 8. ....| -00000030 a7 42 37 27 1b 9c be 36 8f 9b 49 31 4f 73 67 a7 |.B7'...6..I1Osg.| -00000040 78 9f 46 e5 9e 3b 45 ff e9 16 11 ca cc a8 00 00 |x.F..;E.........| +00000000 16 03 03 00 59 02 00 00 55 03 03 96 8a 79 30 8b |....Y...U....y0.| +00000010 13 f5 d3 1c 09 45 76 83 d7 2e e5 ad e3 ee e1 c4 |.....Ev.........| +00000020 d4 b4 4c 37 93 cb 90 e1 9a 5e 52 20 fb 25 91 ea |..L7.....^R .%..| +00000030 1a 96 b6 fb 1f 0c a8 62 06 a0 fe 51 68 c0 fb a5 |.......b...Qh...| +00000040 f1 05 28 02 be dc 87 31 e6 ff 90 1a cc a8 00 00 |..(....1........| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,188 +60,188 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| -000002c0 ac 0c 00 00 a8 03 00 1d 20 2f ad 87 a5 c9 9e c7 |........ /......| -000002d0 f6 f1 05 9a 44 97 57 34 6b 3a 30 54 4c 0e 47 5e |....D.W4k:0TL.G^| -000002e0 16 d3 c9 c2 25 a8 47 e5 63 08 04 00 80 9f 54 b4 |....%.G.c.....T.| -000002f0 c1 aa bb 15 07 5c b1 52 ef bd 26 fa ec ce 70 31 |.....\.R..&...p1| -00000300 90 fb f5 4d d2 26 0c 64 6f b3 9f 7f 27 c7 a5 b2 |...M.&.do...'...| -00000310 d1 6d cf 0e 9c 91 e3 c4 20 f7 e3 ae 95 ff 6d ce |.m...... .....m.| -00000320 80 b5 30 89 6c a2 dd 31 26 5b 24 19 7a 30 f7 43 |..0.l..1&[$.z0.C| -00000330 71 a8 e9 1a 27 ee 46 86 44 56 b1 f3 2e e1 bd d5 |q...'.F.DV......| -00000340 79 99 34 0c 9b 01 e6 bb 0f ad 96 4a 68 0f 10 79 |y.4........Jh..y| -00000350 e9 91 7f 06 e6 02 32 ba 8c b6 a2 0c 4b 6d 09 f6 |......2.....Km..| -00000360 28 8f 94 e8 10 e1 ca 48 6c de 56 c2 5c 16 03 03 |(......Hl.V.\...| +000002c0 ac 0c 00 00 a8 03 00 1d 20 ad 8e 56 2a c0 d0 7c |........ ..V*..|| +000002d0 e1 cb 6b 20 0b 3e 53 33 28 25 37 42 5b 13 3c d5 |..k .>S3(%7B[.<.| +000002e0 26 98 9e 0f df 45 6d 27 67 08 04 00 80 72 49 21 |&....Em'g....rI!| +000002f0 f0 02 02 a3 7c e1 2a 18 d0 d0 21 8e 50 17 ad 0c |....|.*...!.P...| +00000300 3c a2 6d 65 b5 cb bc 7f 9e 7d 7f e2 36 3d b6 c8 |<.me.....}..6=..| +00000310 df 7e b9 28 ab 01 99 2a 68 a4 be 46 11 94 9f 8c |.~.(...*h..F....| +00000320 67 02 92 1e 3c 51 78 f3 7a 35 ed f4 bb 8b fe b3 |g...<Qx.z5......| +00000330 8c 32 aa c1 05 4f 99 68 b0 8a 75 65 1d e6 d6 6a |.2...O.h..ue...j| +00000340 61 65 aa 00 01 6b 29 06 99 d4 5b c7 c3 d2 0c 17 |ae...k)...[.....| +00000350 74 59 d4 ee 99 b8 ef 5b 53 ff 33 df 9e 05 49 4f |tY.....[S.3...IO| +00000360 31 c6 95 81 67 c2 52 8a 0c e9 6a 46 22 16 03 03 |1...g.R...jF"...| 00000370 00 04 0e 00 00 00 |......| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 d5 77 86 8e 32 60 6b 0f 0f 36 33 |.... .w..2`k..63| -00000040 89 fe 51 b8 69 3a 1f 37 b3 d1 eb 43 ab e0 f6 db |..Q.i:.7...C....| -00000050 8b 9d 3c 0d 9a |..<..| +00000030 16 03 03 00 20 b8 c8 5d 3d b8 b8 2b c7 06 94 ec |.... ..]=..+....| +00000040 cc 92 01 22 3d cd 38 d8 aa 9f 1f 18 ef a0 ee 59 |..."=.8........Y| +00000050 c0 3b 04 56 49 |.;.VI| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 ed 78 35 a3 71 |.......... .x5.q| -00000010 34 a9 40 b2 be 15 dc a9 10 86 e0 de 94 23 e9 51 |4.@..........#.Q| -00000020 2c 01 1e 34 19 07 53 20 59 ac f9 |,..4..S Y..| +00000000 14 03 03 00 01 01 16 03 03 00 20 be 6c dd f4 ef |.......... .l...| +00000010 71 1d 9c a7 24 ef 74 81 c4 01 1e e0 ef ac 78 90 |q...$.t.......x.| +00000020 4e 51 fd 8a ca 83 e7 57 95 07 fa |NQ.....W...| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 f3 a2 5f da 1c 09 70 76 af 14 83 |......._...pv...| -00000010 e5 7f 6f c9 9a 61 7f d9 e6 86 3c |..o..a....<| +00000000 17 03 03 00 16 35 96 43 38 06 49 b1 3f 01 ae 85 |.....5.C8.I.?...| +00000010 1a ee 4b 2b fe c0 75 76 b6 4a b0 |..K+..uv.J.| >>> Flow 6 (server to client) -00000000 16 03 03 00 14 71 23 15 46 93 87 94 38 01 d0 1b |.....q#.F...8...| -00000010 1a 34 db 58 17 d0 ac 62 87 |.4.X...b.| +00000000 16 03 03 00 14 df 6c d7 78 02 f5 a7 cb d8 2f fb |......l.x...../.| +00000010 04 dc 30 bc 28 51 f9 ec b8 |..0.(Q...| >>> Flow 7 (client to server) -00000000 16 03 03 01 16 46 70 b5 5f 98 fc af a8 cb d6 7c |.....Fp._......|| -00000010 8c 1e 60 c3 68 25 20 7b 95 9a 0c 04 b3 2c 52 b2 |..`.h% {.....,R.| -00000020 30 f9 db cf 64 48 0a 46 9b 7a 11 76 11 5c 22 0c |0...dH.F.z.v.\".| -00000030 ef fa e6 6e a1 90 29 b3 64 aa ff 4d cb 7d 4d 91 |...n..).d..M.}M.| -00000040 c0 05 99 a0 3d 25 b2 1e 7c c4 d2 94 6b bf f0 f7 |....=%..|...k...| -00000050 0f 6a 3b 4c 66 c7 8a 26 9e 4f 79 68 50 5c f9 92 |.j;Lf..&.OyhP\..| -00000060 97 e1 a5 86 aa f2 e9 d5 8a a1 96 a7 37 82 71 7d |............7.q}| -00000070 7d 7e b6 77 a3 3d 84 40 58 0d 66 cd 52 6c 9b 18 |}~.w.=.@X.f.Rl..| -00000080 e2 c4 f0 dc 3d 9e 0e b8 49 ca 64 f3 71 c5 24 34 |....=...I.d.q.$4| -00000090 e7 ca c3 87 f6 b9 2c 6a 95 12 4d 9d 4a 4d fe 8a |......,j..M.JM..| -000000a0 51 16 6e c9 00 64 c0 d1 da ae e6 14 66 d2 a8 80 |Q.n..d......f...| -000000b0 35 ae 86 f6 64 f8 56 87 8a 40 46 43 ae d1 d1 fb |5...d.V..@FC....| -000000c0 64 1d 00 a1 3d e9 d9 7a b5 fb 71 2a db 76 5a 74 |d...=..z..q*.vZt| -000000d0 03 c3 79 df e6 90 e9 7e de f9 0e 70 7a 65 3c 68 |..y....~...pze<h| -000000e0 4f 2e c0 b8 13 e6 9d 1b 86 b8 65 57 fa dc 46 a7 |O.........eW..F.| -000000f0 26 ba c3 64 fa b3 6f d5 e8 98 1f 10 d5 a5 1f 3e |&..d..o........>| -00000100 cc f9 8d a6 56 37 0d ff 92 8f 1b 36 b3 3d 0b f5 |....V7.....6.=..| -00000110 5b fb fb 1e 4d c8 cb 84 39 5b 87 |[...M...9[.| +00000000 16 03 03 01 16 8c 2a 91 5b 60 aa 44 e7 b7 7e b8 |......*.[`.D..~.| +00000010 ee c2 3e f3 c4 2f 6a 75 8e 25 07 5a 5c 42 81 fd |..>../ju.%.Z\B..| +00000020 65 4c 2a fb a9 80 f0 ba 33 1b 06 a8 79 a8 15 8e |eL*.....3...y...| +00000030 3a c4 08 95 a5 23 f0 ba fb 43 58 26 84 b5 9d 17 |:....#...CX&....| +00000040 03 e5 e7 08 ce 8b 79 9c 5e fb c6 6e a6 b8 12 cf |......y.^..n....| +00000050 b9 6e 4a 2a 90 d0 6b 65 93 bf 41 31 25 7f 3a 7c |.nJ*..ke..A1%.:|| +00000060 75 1f d6 4e 22 d3 90 7b 71 14 57 c6 b6 89 ef 79 |u..N"..{q.W....y| +00000070 74 7e 63 79 b9 63 d6 ef 02 b7 54 4b 53 0e 7f 70 |t~cy.c....TKS..p| +00000080 8a 34 b1 85 98 ae a7 05 b8 41 9d 49 a3 ca eb 7d |.4.......A.I...}| +00000090 8b 64 e7 5d ca 11 71 93 e0 ff 6e 43 37 b4 e9 ec |.d.]..q...nC7...| +000000a0 23 6f d6 c6 bc cb ef a2 0b d0 4b ba 4f 40 b0 4b |#o........K.O@.K| +000000b0 ec 57 cb 8a 10 ae fe cd 14 70 42 a0 b9 1c 81 f6 |.W.......pB.....| +000000c0 d2 79 47 31 4a b8 aa ac 89 98 cf ae 4e 8f 3d 36 |.yG1J.......N.=6| +000000d0 c5 41 0e d8 e6 f3 88 2a 19 e5 e7 71 e2 2f 32 93 |.A.....*...q./2.| +000000e0 ae 05 95 25 8f ec 4e 10 25 7e 53 60 6e c2 f2 72 |...%..N.%~S`n..r| +000000f0 fc 7a 69 c1 93 e9 b8 2e 94 f3 19 31 5b 23 7c fd |.zi........1[#|.| +00000100 04 5d 59 ca 00 cc 37 0b 05 0d 50 10 50 3f b0 86 |.]Y...7...P.P?..| +00000110 84 d4 fc 6a 0a 94 dc ba 88 fe ad |...j.......| >>> Flow 8 (server to client) -00000000 16 03 03 00 81 25 44 f6 91 ed d5 01 fa 88 d6 74 |.....%D........t| -00000010 f7 cd 6d ba 85 76 1d bd ef 7b 31 51 db b4 42 a3 |..m..v...{1Q..B.| -00000020 0a 89 3f 47 dc ca 18 39 84 5d 5a 4e d2 cd ba 75 |..?G...9.]ZN...u| -00000030 b9 75 53 28 8c 85 6e 84 02 39 0a d2 59 ee ac 2f |.uS(..n..9..Y../| -00000040 fe a3 e4 fb 8c a1 72 e3 9f 28 8b 13 92 a8 5b 70 |......r..(....[p| -00000050 24 f0 1b 6d 19 aa f1 b2 bf 8a 1f e2 3a 3e 3f e2 |$..m........:>?.| -00000060 57 16 12 9e e8 21 11 66 b9 96 71 36 46 e1 2e fc |W....!.f..q6F...| -00000070 1e 40 a2 e2 6a 4d 4b 91 7a 50 0b d0 87 d1 04 16 |.@..jMK.zP......| -00000080 2f 47 4d f2 c9 68 16 03 03 02 69 9a 28 7b f7 fc |/GM..h....i.({..| -00000090 8b e7 2b 40 88 1c 30 c1 5a f6 1d 51 a9 a8 5e 70 |..+@..0.Z..Q..^p| -000000a0 73 1c 43 a7 3c 11 7e d5 92 78 b1 4f fd 5d 55 c6 |s.C.<.~..x.O.]U.| -000000b0 5a ef 83 88 b2 e2 33 2a 27 cd 2e e8 d2 f4 2b d4 |Z.....3*'.....+.| -000000c0 d5 b0 35 54 f6 a1 9c 07 75 10 8b 5d b9 dc bb 83 |..5T....u..]....| -000000d0 76 43 f6 7e 70 2f 7c fe 8e 64 ca 00 65 df a4 e1 |vC.~p/|..d..e...| -000000e0 a9 ad 71 79 d6 83 21 f6 9c 1b 88 d4 bb 51 3c 8a |..qy..!......Q<.| -000000f0 8c e5 c2 13 30 bd 6b 60 29 01 3e a0 cc 19 69 54 |....0.k`).>...iT| -00000100 f0 2d dd a9 a1 24 a3 cc 13 9b 9a 8b f5 06 88 a9 |.-...$..........| -00000110 9d ec c1 6f 0c b2 dd b3 60 be 23 ee 67 26 2d 65 |...o....`.#.g&-e| -00000120 b1 99 9a 5b 92 c5 06 79 47 c6 4d 39 36 83 3b 4b |...[...yG.M96.;K| -00000130 96 f0 03 41 5c f9 fa 7c 3e d5 bf 67 1c a3 cf 6f |...A\..|>..g...o| -00000140 26 98 e0 2a 2d 64 60 c2 71 b1 b3 35 ba 8a 38 00 |&..*-d`.q..5..8.| -00000150 88 cf 5a a5 2b 89 83 f3 04 ad 24 97 fa 34 69 fd |..Z.+.....$..4i.| -00000160 d7 70 00 09 ce 0f 60 f7 84 7d e3 5e 19 a9 1b dd |.p....`..}.^....| -00000170 45 3f 34 ae d4 c5 5c 1f 32 81 69 ea 22 44 1d c6 |E?4...\.2.i."D..| -00000180 a3 ca 99 c5 44 09 76 cb e2 ed 2e fd 23 09 d4 ea |....D.v.....#...| -00000190 62 cf cb 93 88 02 ca 8c 90 05 c9 0e 8d ff 8f e1 |b...............| -000001a0 2d ef 52 1c ed 01 53 ef a6 ee 11 11 b7 2b c8 b4 |-.R...S......+..| -000001b0 6e 32 8c 54 7a 2b 19 e1 32 3e d0 92 87 81 76 04 |n2.Tz+..2>....v.| -000001c0 c0 fd 99 3b 04 00 fb 76 d7 ed b0 81 e3 81 8c 1f |...;...v........| -000001d0 2b a0 59 d6 41 cd 8d 7d b6 62 9d ab 60 33 24 f5 |+.Y.A..}.b..`3$.| -000001e0 ec 70 8b b2 46 60 8f 53 c8 a3 f1 47 df e0 e8 b0 |.p..F`.S...G....| -000001f0 9a cf 61 d4 d0 f5 0b b6 cd 85 47 1b b2 26 7d f2 |..a.......G..&}.| -00000200 0a 32 af 5c 25 2a cc d2 66 9a 36 a1 68 95 34 18 |.2.\%*..f.6.h.4.| -00000210 2d 9a 5a 62 a7 39 be 00 70 59 63 38 6a f9 53 b7 |-.Zb.9..pYc8j.S.| -00000220 6d dd d4 cd c4 d2 12 b0 67 06 b5 d3 28 06 e4 43 |m.......g...(..C| -00000230 98 b5 13 9f 1a d5 5e 07 70 f9 96 3c 66 a0 60 d6 |......^.p..<f.`.| -00000240 79 1f 67 98 0b 38 ab 5a 1c 6f b0 31 e9 d9 6e 58 |y.g..8.Z.o.1..nX| -00000250 28 c4 c5 82 9f 57 12 ae 35 12 c5 5c 29 f9 50 93 |(....W..5..\).P.| -00000260 07 d8 e4 b8 36 5a 1e 10 a9 ee 33 5d ce 9c fe b8 |....6Z....3]....| -00000270 78 11 99 2a 88 9d ce 49 6f 1c 73 41 65 5f c2 d5 |x..*...Io.sAe_..| -00000280 46 a7 25 27 bc 3d 69 25 04 3a 37 ee e6 8a c0 d8 |F.%'.=i%.:7.....| -00000290 e8 72 7a a9 21 03 9a 63 c9 f5 16 76 c4 11 b9 12 |.rz.!..c...v....| -000002a0 03 cf ec 91 a0 6b 90 24 ba 0b f6 f2 4a 41 0d 9f |.....k.$....JA..| -000002b0 32 23 a3 df 3c ff c3 44 01 9c 77 5a 01 3f 00 d0 |2#..<..D..wZ.?..| -000002c0 44 4d 48 23 58 9f 18 99 97 9c 32 7f cb 40 bb 35 |DMH#X.....2..@.5| -000002d0 1f b8 06 07 28 7d 39 5a 47 66 12 95 30 07 24 b1 |....(}9ZGf..0.$.| -000002e0 81 bc ea c0 6d 10 15 82 5f fe 68 50 1d aa 61 19 |....m..._.hP..a.| -000002f0 c9 47 7c dc 16 03 03 00 bc e8 5f 40 20 1a cd d8 |.G|......._@ ...| -00000300 5b b7 1e db 9d c0 10 96 e2 11 86 bc 0c e1 5f bd |[............._.| -00000310 9c cc 70 37 85 87 94 3c cd 7d 0a c3 56 1e 18 9a |..p7...<.}..V...| -00000320 dc 21 4b e6 e1 63 c0 e6 2e 32 69 96 7e a0 cf cc |.!K..c...2i.~...| -00000330 58 74 a9 31 97 c1 e4 87 79 7f e7 7e 94 32 93 8d |Xt.1....y..~.2..| -00000340 31 97 51 27 26 cf ac e9 f9 34 ae 3e 1d f0 e9 5a |1.Q'&....4.>...Z| -00000350 71 82 05 10 8e be 0b 83 39 44 28 45 c6 e1 4a 85 |q.......9D(E..J.| -00000360 c0 bf 3f 80 9b 61 97 82 d1 54 37 5f bc b2 f7 1f |..?..a...T7_....| -00000370 a1 ef 0f c5 be 74 96 3b e8 89 30 3f d7 06 18 77 |.....t.;..0?...w| -00000380 ed 3b aa 6e df 0c 15 e1 3e b1 36 ae 85 23 7d 9a |.;.n....>.6..#}.| -00000390 17 c3 f4 91 3a ac b1 64 03 a9 59 19 89 c2 d9 ad |....:..d..Y.....| -000003a0 82 d7 8e 85 36 cb 81 61 0d 3a 24 a1 84 55 37 bb |....6..a.:$..U7.| -000003b0 13 80 61 38 ef 16 03 03 00 4a 88 8d 13 b9 32 18 |..a8.....J....2.| -000003c0 3c e2 72 b5 5c 0b 81 87 a0 ef 87 53 89 b1 f4 8b |<.r.\......S....| -000003d0 6a 87 68 c4 7d 59 2c 44 46 bb b1 40 8e 0a 45 4e |j.h.}Y,DF..@..EN| -000003e0 b8 a1 ba 72 bb 71 f9 52 55 c7 44 cd b3 56 82 68 |...r.q.RU.D..V.h| -000003f0 8c 57 39 58 0b 40 12 4f 5d a2 91 3a ab 68 55 19 |.W9X.@.O]..:.hU.| -00000400 26 dc ed 30 16 03 03 00 14 52 f8 53 d9 fc a6 a3 |&..0.....R.S....| -00000410 89 c4 5a 2d 66 46 17 16 c3 bb f9 3c ca |..Z-fF.....<.| +00000000 16 03 03 00 81 41 25 27 5b 76 24 a0 4f f0 bf ca |.....A%'[v$.O...| +00000010 c4 4f f8 7c c6 e8 2a d4 d1 ed f1 b8 34 84 d6 d5 |.O.|..*.....4...| +00000020 93 20 70 7d 8e 75 c5 16 a8 ff 5c e6 de 16 ea 96 |. p}.u....\.....| +00000030 3f 86 3b bd 6d fa 96 3d 27 18 34 b8 18 86 ee 65 |?.;.m..='.4....e| +00000040 7f f2 cc 7a b9 f8 2e 5a 32 f3 16 e2 a2 27 fd 4b |...z...Z2....'.K| +00000050 31 19 e6 81 d9 ef 02 10 ac b6 55 d3 0b e2 b0 09 |1.........U.....| +00000060 56 ea 50 5a 96 b3 ff 07 78 48 df 77 3f 15 c9 ff |V.PZ....xH.w?...| +00000070 a7 24 af 28 ec 99 1a c9 36 09 16 9c 7c 5a c0 85 |.$.(....6...|Z..| +00000080 7c 93 e4 61 2e 5b 16 03 03 02 69 ef 17 31 d5 9c ||..a.[....i..1..| +00000090 bc 09 f9 b7 75 e2 c8 ea 93 6f b7 49 e3 0e af bb |....u....o.I....| +000000a0 84 d6 3b 20 e2 89 13 6f 7a d1 73 a7 cb d5 03 b2 |..; ...oz.s.....| +000000b0 20 40 40 76 d9 5d 3b 23 cb 48 ba 3c 1b e7 5d de | @@v.];#.H.<..].| +000000c0 16 be 82 91 39 d0 b4 83 3e 4c b8 a0 66 56 47 6c |....9...>L..fVGl| +000000d0 08 03 b1 0f be 3f d3 5e 7e b4 40 db db 5b ce 61 |.....?.^~.@..[.a| +000000e0 d9 dc 02 7d ea df ea 43 08 2c b0 1c af 76 8f d3 |...}...C.,...v..| +000000f0 cd af 51 cd 17 df 70 58 90 bd 83 aa 4b e5 fe cd |..Q...pX....K...| +00000100 90 30 e0 b5 d0 95 49 c2 10 06 8c 5a dd a2 37 ad |.0....I....Z..7.| +00000110 d5 d1 0e 73 c7 92 a9 ab 67 51 da 9d a4 62 6d a6 |...s....gQ...bm.| +00000120 d7 89 22 2b 97 59 ad 02 65 e9 1d 48 44 07 c9 c0 |.."+.Y..e..HD...| +00000130 c4 1f 7f da 64 0c 35 19 16 b3 70 41 d8 61 c3 47 |....d.5...pA.a.G| +00000140 59 4d c2 e6 07 86 55 92 b9 98 8e 5c 86 d2 d5 51 |YM....U....\...Q| +00000150 6a 50 19 99 75 0a cf 6e 49 cc 8a 76 b5 2b 20 48 |jP..u..nI..v.+ H| +00000160 2b 11 d4 54 a2 ea 98 ce d8 56 22 c8 f8 eb e5 25 |+..T.....V"....%| +00000170 c8 cf ec 86 95 09 51 7e 18 89 bb 8f d4 66 b8 44 |......Q~.....f.D| +00000180 c2 78 f4 4d ad eb 2d 79 f8 f6 02 4f d2 35 d4 71 |.x.M..-y...O.5.q| +00000190 b3 ae e6 7d f6 45 6c 99 07 57 3c 01 bb c1 fb f1 |...}.El..W<.....| +000001a0 1a ac ba 92 b6 60 52 63 8b 21 eb bf 77 02 c6 29 |.....`Rc.!..w..)| +000001b0 7f 10 f7 11 ac a2 90 a9 8b 47 da c1 2c 41 c9 da |.........G..,A..| +000001c0 3f 18 ab be f0 eb 20 98 80 c6 d2 14 9e 8e d3 41 |?..... ........A| +000001d0 c3 37 ab 12 5b cc d0 25 bd af 16 49 4e 89 a1 92 |.7..[..%...IN...| +000001e0 d1 09 49 59 dc cf f8 6c 73 02 cb 72 6d 28 6e 28 |..IY...ls..rm(n(| +000001f0 c5 a8 84 20 e6 f8 1b ad c1 6c 8f b0 30 b2 49 84 |... .....l..0.I.| +00000200 22 42 7d ec e1 c7 ab 29 de 1c 84 1f cf 59 c6 80 |"B}....).....Y..| +00000210 7e 13 13 d7 c5 e5 f2 e0 3b 9d 81 c9 3f 86 21 27 |~.......;...?.!'| +00000220 d7 c8 45 c1 25 f6 19 8d 0a f6 e9 5a 9b d5 64 a1 |..E.%......Z..d.| +00000230 e4 6d fe 6a cf d1 c3 1b d4 ea d9 1f 6b dc f9 a7 |.m.j........k...| +00000240 e9 d2 6c 31 19 db e1 f4 f8 82 6e 8b da fd b1 fd |..l1......n.....| +00000250 0a 56 84 73 db 25 5f bb 12 61 70 de 67 34 28 1c |.V.s.%_..ap.g4(.| +00000260 c3 e6 eb 81 c8 94 55 ca 52 25 e8 72 bf a1 c5 88 |......U.R%.r....| +00000270 b8 ce 72 8d 64 6c 38 d9 19 07 f3 51 51 91 84 f2 |..r.dl8....QQ...| +00000280 c4 76 7f 8b 57 09 71 94 38 aa f1 64 51 6f 62 50 |.v..W.q.8..dQobP| +00000290 c8 50 68 82 b9 54 b1 28 54 99 21 26 7d 75 c7 c7 |.Ph..T.(T.!&}u..| +000002a0 79 e7 65 93 72 a4 39 2d 4c ec ba b2 4c 92 ae ee |y.e.r.9-L...L...| +000002b0 34 a2 22 2f f9 b9 75 a9 27 77 63 2d ac 27 87 ce |4."/..u.'wc-.'..| +000002c0 ee 37 c0 c7 c1 b6 4c 13 d7 78 97 64 dc af ea 0d |.7....L..x.d....| +000002d0 7c 12 0e 7b 0b 26 77 01 e4 1c 24 e8 9f fc 19 2f ||..{.&w...$..../| +000002e0 46 a2 81 3d 0d c7 16 7e 49 25 b4 c1 0f 0a 71 05 |F..=...~I%....q.| +000002f0 25 eb 53 e4 16 03 03 00 bc 0b 79 2d c6 0a 63 68 |%.S.......y-..ch| +00000300 f0 21 37 d0 42 4a 0f 2f 7d 2f a0 7d 3d c3 94 c4 |.!7.BJ./}/.}=...| +00000310 36 f5 a6 db e1 ad 0f 94 07 67 57 54 d4 57 86 50 |6........gWT.W.P| +00000320 a2 e1 78 09 f2 e3 7b bc 6d 1b c0 fe 16 eb d3 ef |..x...{.m.......| +00000330 fb ec 22 44 ee 2f 78 99 84 e2 c1 4c f7 0d 4f bc |.."D./x....L..O.| +00000340 ca 57 be de 5f 52 08 33 b0 e1 1d 7b 45 9e 5d 17 |.W.._R.3...{E.].| +00000350 41 2c 10 43 44 18 84 38 f3 0b 6a a1 76 bf 75 c9 |A,.CD..8..j.v.u.| +00000360 56 b2 53 4c 98 39 c0 6f 30 13 96 8a 27 59 12 03 |V.SL.9.o0...'Y..| +00000370 60 64 ce 28 54 c0 03 f4 c4 d1 df 94 e3 6e 43 61 |`d.(T........nCa| +00000380 fa 43 40 e5 05 3b 26 dc c4 41 bd 73 c3 9e a0 db |.C@..;&..A.s....| +00000390 fb c9 50 b4 4a d9 2d 71 cf e8 ff 3d 17 9e 29 35 |..P.J.-q...=..)5| +000003a0 61 6c ab 11 ac 21 fa 90 6b 75 1f 0a 9d 30 3f 13 |al...!..ku...0?.| +000003b0 fa c3 97 7a 74 16 03 03 00 4a 3d ca 3b 3d c8 6f |...zt....J=.;=.o| +000003c0 44 4e 53 3d 05 27 97 aa bd 58 33 d6 ad 4a 34 71 |DNS=.'...X3..J4q| +000003d0 22 d9 36 96 17 a5 ba 6b b3 20 2e da 64 65 14 c7 |".6....k. ..de..| +000003e0 6a c7 07 39 55 db bb ad e2 49 84 09 5e 78 88 b5 |j..9U....I..^x..| +000003f0 4b d5 23 fa 17 c5 f2 b8 2a c6 e5 1e 15 47 01 36 |K.#.....*....G.6| +00000400 ef 7f 0a 14 16 03 03 00 14 28 e3 58 7e b9 36 d6 |.........(.X~.6.| +00000410 ef 65 c8 bc fb 10 57 3d 48 70 7f 68 7d |.e....W=Hp.h}| >>> Flow 9 (client to server) -00000000 16 03 03 02 69 fe 0d 45 cb 57 12 fa 9e 10 d7 b3 |....i..E.W......| -00000010 a5 dd 33 0e 39 41 77 63 8e 99 e0 5b b9 5e 94 0a |..3.9Awc...[.^..| -00000020 48 b2 6b e9 61 ab f2 74 6b 5e a3 f9 3f 9c 29 0b |H.k.a..tk^..?.).| -00000030 6b 34 29 92 d8 c8 2c 61 84 f2 3b 0f c2 5c e5 19 |k4)...,a..;..\..| -00000040 6a f0 e2 03 e3 93 a6 1e 4e 87 79 6b 07 dc 18 d2 |j.......N.yk....| -00000050 9a 25 be f3 d6 ab 2a be f8 68 65 68 92 8a 80 04 |.%....*..heh....| -00000060 26 eb 62 ae 6b bc 81 27 82 76 25 e0 6b ac 04 e9 |&.b.k..'.v%.k...| -00000070 67 68 13 f6 7b 7e 24 c2 75 27 8a c9 3a 7a 2f aa |gh..{~$.u'..:z/.| -00000080 a2 37 d9 73 97 bc 4b 09 ba 1b 2c ba 08 85 c6 82 |.7.s..K...,.....| -00000090 50 a3 e0 00 6e a8 7c 14 ab 38 ae c4 82 ee 05 4b |P...n.|..8.....K| -000000a0 9a c0 19 62 1e de ef 7f 8c a4 a0 0e 29 0f b4 09 |...b........)...| -000000b0 f1 b9 39 ae 09 1b 6e 6f ee 3d 31 72 70 09 51 44 |..9...no.=1rp.QD| -000000c0 1c 33 64 6d ae 8d da a5 e0 7b a3 49 19 2c 3f dd |.3dm.....{.I.,?.| -000000d0 6b 1e d1 a7 bb 8a 13 8c e9 aa 5f b3 fd 88 89 5a |k........._....Z| -000000e0 4a 30 dd d0 1e 6a 8c 8a 0d 35 82 01 64 c1 42 ff |J0...j...5..d.B.| -000000f0 60 ac 3d 62 bf 31 3e ab 42 7e b0 da 4a cc 9c d8 |`.=b.1>.B~..J...| -00000100 0e 92 97 a2 40 48 48 ce 66 49 bd 1b 8a ee ed 46 |....@HH.fI.....F| -00000110 18 98 b9 43 b8 76 e8 93 07 3c 38 6e c2 cd 9c ce |...C.v...<8n....| -00000120 e2 38 f0 d7 ee ad c7 4a c4 ed 3b fd 2e f2 9b 43 |.8.....J..;....C| -00000130 6c fe 75 d7 4d 61 2a c5 16 e2 3d af 98 5b 76 f5 |l.u.Ma*...=..[v.| -00000140 3e 96 b9 81 b3 cb 0c 91 89 44 6e d6 66 c4 f2 dd |>........Dn.f...| -00000150 c9 21 09 91 95 f2 99 29 62 54 44 03 b0 fe 84 bb |.!.....)bTD.....| -00000160 96 86 c4 ca 6e 7f c9 f9 1a 80 38 42 7d 54 b3 6f |....n.....8B}T.o| -00000170 2a 2d c3 19 54 60 3f fb 00 95 65 6a 85 4b a2 8f |*-..T`?...ej.K..| -00000180 6a 3d 38 61 e9 36 c2 25 92 3b 53 f2 ea bb 60 42 |j=8a.6.%.;S...`B| -00000190 ab 83 83 c0 2e 95 6d 5a 19 61 9f b3 29 ee b2 52 |......mZ.a..)..R| -000001a0 5f 27 16 46 d9 ad 62 45 d5 81 9a 93 ef a1 4f e7 |_'.F..bE......O.| -000001b0 0e e0 71 bf cd 49 68 e7 13 f1 71 59 8c f5 2d 05 |..q..Ih...qY..-.| -000001c0 5d 65 c4 6e 2c 91 c5 d3 40 c4 2f df c8 f6 59 55 |]e.n,...@./...YU| -000001d0 05 6b c1 b7 59 15 8e b8 85 1b 75 dd 44 9e b7 f3 |.k..Y.....u.D...| -000001e0 00 73 bf c6 93 d4 43 27 bd 60 79 1a 28 93 2d 64 |.s....C'.`y.(.-d| -000001f0 fb 2f 77 a6 79 22 54 f3 c3 3c 3f cd 4d ea 79 3b |./w.y"T..<?.M.y;| -00000200 aa 4c e6 86 55 8d e0 5c ce 00 1e d4 fa ab bb de |.L..U..\........| -00000210 8f 41 95 15 d3 6a 21 02 cb 4a f5 b6 2d 8c da 99 |.A...j!..J..-...| -00000220 93 1f 9f 81 cf 77 f8 01 0a ab 77 03 5c a3 bd 3a |.....w....w.\..:| -00000230 ba 07 51 17 50 06 c9 51 f8 f1 ec 3f 60 44 df 1b |..Q.P..Q...?`D..| -00000240 06 05 bd 8f 17 99 00 73 38 e5 bb fb 08 1b e7 ea |.......s8.......| -00000250 b5 36 e0 4e 67 d9 11 90 5e d9 8e 63 7b f9 03 4b |.6.Ng...^..c{..K| -00000260 ef cd 4d 2c d9 4b eb 8a bb 62 85 03 16 e2 16 03 |..M,.K...b......| -00000270 03 00 35 d1 39 57 66 1b 70 63 8f 6a b4 1d 5f 5e |..5.9Wf.pc.j.._^| -00000280 dd 31 7e 5b 0e e3 d5 98 90 8b 60 33 0c 10 7c 01 |.1~[......`3..|.| -00000290 4c 40 88 e9 a3 8c 61 ab dc 4a e2 ce 0a fc 56 7b |L@....a..J....V{| -000002a0 ef e3 19 60 62 18 97 7c 16 03 03 00 98 2f 65 76 |...`b..|...../ev| -000002b0 15 2e 76 82 e8 70 6d c4 17 72 e7 30 9c 14 af d4 |..v..pm..r.0....| -000002c0 0f 1e ec b5 5c 80 31 dc 15 fc 81 06 20 f1 e5 99 |....\.1..... ...| -000002d0 67 c6 eb cc 77 57 2c 55 85 dc f9 9f 6f 19 7a d0 |g...wW,U....o.z.| -000002e0 a0 45 17 b9 8c e4 19 46 ef dc 28 e1 e7 87 93 e0 |.E.....F..(.....| -000002f0 c5 83 70 28 23 90 b9 c2 53 a3 67 d8 09 1f 47 0e |..p(#...S.g...G.| -00000300 a3 de bf a3 07 2d e7 3b a5 e9 11 c4 30 59 fb cd |.....-.;....0Y..| -00000310 5d 6a d0 47 6f 43 a4 bd 2f 56 67 7d b2 c8 f5 2a |]j.GoC../Vg}...*| -00000320 9b ce ea 10 ec 83 f8 bc 87 19 c8 97 a9 ee 80 3c |...............<| -00000330 cb de 1a 22 60 ed 77 f7 57 5f 20 54 62 ca b0 e7 |..."`.w.W_ Tb...| -00000340 75 a0 ba fc 32 14 03 03 00 11 86 a9 6a 14 1a 4c |u...2.......j..L| -00000350 1d 21 1f 3c c2 19 85 02 88 f5 f6 16 03 03 00 20 |.!.<........... | -00000360 03 f9 fc ed cf 15 ed 86 d2 69 49 d7 e2 01 06 96 |.........iI.....| -00000370 42 74 89 3f bf 98 56 0f c1 1b 61 b6 36 3b ae 87 |Bt.?..V...a.6;..| +00000000 16 03 03 02 69 d8 c1 81 7e a9 d7 70 97 62 c7 68 |....i...~..p.b.h| +00000010 df 02 01 9d cc dc 38 d0 d6 bb 48 03 1d 0b be 73 |......8...H....s| +00000020 b3 1a 88 91 a0 1b 55 91 51 a5 d7 54 58 c4 ea 50 |......U.Q..TX..P| +00000030 e5 67 b1 60 78 b6 e2 7f d7 6c b4 76 d7 24 fd af |.g.`x....l.v.$..| +00000040 f6 68 90 8c de 71 cd 15 4f d0 c8 f6 ba 89 ce 05 |.h...q..O.......| +00000050 be 35 e8 9e 7a 8b 8d 0d 23 d4 5a bd 3a 9e d0 bf |.5..z...#.Z.:...| +00000060 80 08 f5 ad 7d 84 f1 8a 16 de 97 6b b2 75 8e 49 |....}......k.u.I| +00000070 0f d7 8b 10 57 f7 21 1f c0 87 de 06 c5 ae ae dd |....W.!.........| +00000080 9c 22 92 a1 6c c7 46 8d e2 be 43 32 9c be 47 6b |."..l.F...C2..Gk| +00000090 4d 2a 60 f0 b6 3a 09 16 d6 16 a1 92 4a 2d 2d 72 |M*`..:......J--r| +000000a0 00 8f 40 7c 3e a9 61 be 35 c8 f8 48 b4 1c 90 61 |..@|>.a.5..H...a| +000000b0 90 c5 aa f8 ae aa d4 8a 15 74 b2 5d aa 24 cf 45 |.........t.].$.E| +000000c0 ef 02 bd 29 b9 50 b4 fe 83 05 fa 4a a5 82 10 28 |...).P.....J...(| +000000d0 b7 ab c3 ca c3 65 bb 51 a4 7c ac 57 03 78 28 e3 |.....e.Q.|.W.x(.| +000000e0 91 9f c1 ce 02 08 70 84 8c 11 1f ae 35 a5 06 12 |......p.....5...| +000000f0 f8 78 5b 38 0a 11 c8 1c 2d 1b 0c 21 66 d9 41 b2 |.x[8....-..!f.A.| +00000100 ed 66 3c 47 f2 dc ab c1 59 7d 65 df bb 80 37 1c |.f<G....Y}e...7.| +00000110 5e 9b 41 e1 1d 5f b5 24 e4 77 61 3b e8 36 93 03 |^.A.._.$.wa;.6..| +00000120 6d 87 17 e9 d7 77 35 b1 83 a3 b9 80 4d 40 20 82 |m....w5.....M@ .| +00000130 94 36 53 94 ad 6b b3 ad 0a 70 fd 11 ce 81 56 ca |.6S..k...p....V.| +00000140 c2 5d 16 69 e3 59 7e 37 3b cd f3 54 1e b8 5e 1a |.].i.Y~7;..T..^.| +00000150 64 3f bf c6 ba ff fa b5 bf 4b c2 8e 5a 4d 43 1f |d?.......K..ZMC.| +00000160 8e 50 bc 7a 82 13 c7 25 aa b4 a8 97 45 49 12 25 |.P.z...%....EI.%| +00000170 f5 4d 52 df 90 e5 74 0f a0 d2 fd c3 6f bd 41 ed |.MR...t.....o.A.| +00000180 ff 78 e8 97 f2 e2 d1 5b 7c e6 27 01 16 27 1d b6 |.x.....[|.'..'..| +00000190 8a cf c6 5b 8d b3 d8 8e 0c ee 2a d5 21 f6 4b d3 |...[......*.!.K.| +000001a0 5a 74 7e 3d c6 fb 0e 35 97 de e7 52 c0 b2 c3 37 |Zt~=...5...R...7| +000001b0 94 28 41 e0 3b 65 56 f1 4f 60 03 48 88 1d db fc |.(A.;eV.O`.H....| +000001c0 60 9f 33 e1 4d 37 eb 22 36 b2 76 ae 1c 3d 1c 5e |`.3.M7."6.v..=.^| +000001d0 3a c5 5b 00 eb 72 8b 54 ba 76 d1 71 77 5f 76 54 |:.[..r.T.v.qw_vT| +000001e0 5f fd 0e d1 3a 50 ad b1 55 4a db 6d bf 2f 33 90 |_...:P..UJ.m./3.| +000001f0 fc 42 de cd e4 a9 dd 11 25 d1 9f 56 1e 8a 2b 5c |.B......%..V..+\| +00000200 6c ed e7 51 84 42 6b ab 7d 77 b4 95 c3 75 b3 24 |l..Q.Bk.}w...u.$| +00000210 ce 70 b0 e1 63 7f ec b0 ea 6a a4 a1 d5 e8 3e 96 |.p..c....j....>.| +00000220 65 99 40 46 73 c8 e1 6e 86 65 92 bf 3d 92 a3 4f |e.@Fs..n.e..=..O| +00000230 37 6d bb 80 33 a5 7d aa d3 a9 37 77 a6 4e 5b d6 |7m..3.}...7w.N[.| +00000240 f3 f9 b2 42 75 18 1f 5a 58 f3 08 35 bc f4 2b 93 |...Bu..ZX..5..+.| +00000250 62 0b 8a 83 f9 44 d0 e1 1a 44 b2 66 45 6f de b3 |b....D...D.fEo..| +00000260 d2 ec 34 ac 15 89 76 b4 da dd 95 ca 44 5b 16 03 |..4...v.....D[..| +00000270 03 00 35 39 e8 06 21 47 85 b5 53 96 03 0b 08 3b |..59..!G..S....;| +00000280 d2 9d 55 1f 23 4f 3a c0 be 4f e0 e0 0a f1 65 6f |..U.#O:..O....eo| +00000290 78 22 c4 10 6b d0 96 dc 04 78 e8 d3 95 f6 9a 78 |x"..k....x.....x| +000002a0 09 f2 42 d3 79 57 99 c4 16 03 03 00 98 37 6b 75 |..B.yW.......7ku| +000002b0 79 17 fa 67 7f 94 2e aa 88 61 91 97 dc 10 1e e6 |y..g.....a......| +000002c0 6d 6d fa d5 64 17 f4 ec ba 01 43 99 88 e2 a7 13 |mm..d.....C.....| +000002d0 e0 9e 6a e9 97 c7 b3 ec b9 c9 72 51 3d 01 eb c0 |..j.......rQ=...| +000002e0 03 0f 08 48 90 27 36 6b bd e7 0d 4e 41 6a ef 11 |...H.'6k...NAj..| +000002f0 42 5b ae d1 16 ec 8f b7 47 a2 f5 b4 6a d4 32 bb |B[......G...j.2.| +00000300 0c cc 4f 2a e0 be 44 47 c8 77 09 f5 78 4b d6 ec |..O*..DG.w..xK..| +00000310 87 95 dc e1 74 75 54 af 45 bb 7a f5 2e f7 ac 3d |....tuT.E.z....=| +00000320 d1 b2 31 5a c0 24 c7 7c 25 36 62 a7 48 73 66 44 |..1Z.$.|%6b.HsfD| +00000330 c1 78 47 f3 48 c5 a0 f7 66 3e 78 27 2c 3c dc 83 |.xG.H...f>x',<..| +00000340 f5 6c e1 09 31 14 03 03 00 11 79 32 99 fd 2d 8d |.l..1.....y2..-.| +00000350 14 33 fd 1b 1b a8 3d 99 4b 0a b7 16 03 03 00 20 |.3....=.K...... | +00000360 76 25 53 83 f2 c5 bf a6 fa 2e d3 5a 62 67 5b 1d |v%S........Zbg[.| +00000370 23 9a 9c b3 16 01 3f 6a e9 4c ea e1 d4 d1 09 42 |#.....?j.L.....B| >>> Flow 10 (server to client) -00000000 14 03 03 00 11 00 e4 ef 62 c1 c0 72 f3 98 4d 5a |........b..r..MZ| -00000010 6a c8 7e 29 92 b8 16 03 03 00 20 ff 7e fc cb b5 |j.~)...... .~...| -00000020 07 5f ea 8a 89 2a 46 1b c6 33 41 fe f9 f4 1e 3a |._...*F..3A....:| -00000030 9d 8b 1d 8f 9b 7b 89 07 b4 e8 59 17 03 03 00 19 |.....{....Y.....| -00000040 a3 ba 0c 9b 54 cd 59 6a e1 db 33 80 38 a9 95 a1 |....T.Yj..3.8...| -00000050 95 5b a5 5f ad 3c d0 52 f7 16 03 03 00 14 e6 22 |.[._.<.R......."| -00000060 84 a7 02 10 1e ee 58 88 a5 b8 e8 bf 0a 9b 61 46 |......X.......aF| -00000070 0c ae |..| +00000000 14 03 03 00 11 a7 38 2a 4e 04 a5 b7 df d6 05 bb |......8*N.......| +00000010 b5 93 38 bc 9e 62 16 03 03 00 20 f3 d3 e1 7d 80 |..8..b.... ...}.| +00000020 41 ce 05 99 92 c7 47 fe b5 08 3b 78 9d ae b0 5f |A.....G...;x..._| +00000030 2c ed bd 0b 90 e0 94 9e 0b b0 a5 17 03 03 00 19 |,...............| +00000040 27 f0 6a 55 af 3f c1 82 85 1a 6b 28 e1 cd dc 59 |'.jU.?....k(...Y| +00000050 43 be c7 18 16 30 08 b2 9e 16 03 03 00 14 c1 c5 |C....0..........| +00000060 64 ef 72 4f 6c 96 f1 f6 5b 70 29 e4 59 36 0a cd |d.rOl...[p).Y6..| +00000070 d2 a3 |..| >>> Flow 11 (client to server) -00000000 15 03 03 00 12 7f 90 91 7b 93 4e 24 25 5e cb 35 |........{.N$%^.5| -00000010 2c eb ee 29 6a b3 a3 15 03 03 00 12 3d b7 30 fe |,..)j.......=.0.| -00000020 63 90 c3 2d 17 a0 e1 ed 8d bb a4 f6 f6 17 |c..-..........| +00000000 15 03 03 00 12 af 73 0e 40 39 dd 1e 04 99 3e 10 |......s.@9....>.| +00000010 c9 62 b3 78 77 9b 56 15 03 03 00 12 25 8b 87 29 |.b.xw.V.....%..)| +00000020 82 d0 9f 5e 9a 27 bd c1 bf b7 a2 f0 92 ac |...^.'........| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected index 3502977..f7a7668 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 9c d0 eb d6 42 |....Y...U......B| -00000010 2e ff 6e 5a 19 33 6d 12 97 56 56 2b f5 1b 86 c8 |..nZ.3m..VV+....| -00000020 38 83 59 37 ac 17 46 ed 73 53 43 20 e4 94 9b 71 |8.Y7..F.sSC ...q| -00000030 f4 94 d9 d9 3a a1 e1 99 1e b4 a5 55 46 88 e0 0a |....:......UF...| -00000040 af 0a 0e ff 81 10 e2 e0 63 21 ae 2a cc a8 00 00 |........c!.*....| +00000000 16 03 03 00 59 02 00 00 55 03 03 a3 55 d2 e2 bd |....Y...U...U...| +00000010 94 8f 04 51 26 1c a6 61 b1 ed 05 e2 39 44 33 05 |...Q&..a....9D3.| +00000020 79 14 b7 1f 89 1e bb ba 53 0d 12 20 09 29 6d 26 |y.......S.. .)m&| +00000030 04 70 4a 5d 01 90 f2 c6 28 df 11 6a 64 23 ec 9e |.pJ]....(..jd#..| +00000040 9f 2b 15 33 dc 88 26 35 3a b0 86 92 cc a8 00 00 |.+.3..&5:.......| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,36 +60,36 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| -000002c0 ac 0c 00 00 a8 03 00 1d 20 9b 89 08 0d ea c2 d3 |........ .......| -000002d0 4f 73 77 a0 e3 0e 1a 68 13 2c 5c a5 ec 39 75 1b |Osw....h.,\..9u.| -000002e0 c2 95 fe b8 fe 58 f4 bb 16 08 04 00 80 d4 e8 d3 |.....X..........| -000002f0 d4 5b 1f ee ff 60 f5 86 b1 f4 06 c0 a8 ab 90 b0 |.[...`..........| -00000300 26 15 d5 4e 3f d6 a5 e2 a3 3a e0 0f 9a 92 bd 96 |&..N?....:......| -00000310 9d 98 15 f3 95 82 a9 5d 9f 1d 9b 4f 2e 77 58 40 |.......]...O.wX@| -00000320 58 3d fd 8f a6 09 1c fa 61 77 2e 87 df e7 76 8b |X=......aw....v.| -00000330 bf f1 dd 29 f8 70 c0 6d db e5 a0 55 92 77 44 75 |...).p.m...U.wDu| -00000340 d9 95 a6 17 67 93 47 8e 1f 61 50 65 31 94 d3 79 |....g.G..aPe1..y| -00000350 5f 25 a6 f0 3e 19 9a c8 ad b9 1a af 5b 50 2c 97 |_%..>.......[P,.| -00000360 78 1e 71 3a e0 fa 7c 44 1e d1 32 56 4e 16 03 03 |x.q:..|D..2VN...| +000002c0 ac 0c 00 00 a8 03 00 1d 20 43 6b 44 5b 79 c9 38 |........ CkD[y.8| +000002d0 dc e4 ab fa 88 fa e6 06 89 b1 4e ff ab 8d d6 f7 |..........N.....| +000002e0 21 b4 ff 9d a0 c8 54 cc 63 08 04 00 80 cd f4 d6 |!.....T.c.......| +000002f0 c8 ad 03 e7 f0 e8 f4 c9 f0 e6 28 db cd 3b 7c bf |..........(..;|.| +00000300 05 af 3d fe c1 f9 f1 7a ec 41 bf 1f a8 95 6d ee |..=....z.A....m.| +00000310 e6 92 cb c0 ff fd c1 ed 86 b0 59 45 3e 2d 1d 66 |..........YE>-.f| +00000320 56 d1 9f e2 b7 79 ac aa 81 6d b0 42 36 96 80 4d |V....y...m.B6..M| +00000330 ca 36 29 1b 65 03 73 3f 85 ec 59 cb b4 a5 a0 c0 |.6).e.s?..Y.....| +00000340 0c 16 ad e2 6b 35 3c ab 1e da 69 19 7d a2 63 a7 |....k5<...i.}.c.| +00000350 69 2a d2 3f 12 17 bf 4c ed 8a f7 75 fe ce d4 2b |i*.?...L...u...+| +00000360 4d 35 bf 65 d6 9e 01 69 a8 0a 73 26 34 16 03 03 |M5.e...i..s&4...| 00000370 00 04 0e 00 00 00 |......| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 88 fe 97 82 bd a7 99 c6 a6 2f c1 |.... ........./.| -00000040 1a a8 54 8c e5 c6 39 0a 6b 07 9b 1a 05 f4 fb e3 |..T...9.k.......| -00000050 67 f5 c8 6e 17 |g..n.| +00000030 16 03 03 00 20 b8 d8 22 20 8d 69 23 05 34 eb 69 |.... .." .i#.4.i| +00000040 92 a0 a9 6c cd 94 3b 72 49 91 72 8e 65 79 ca 62 |...l..;rI.r.ey.b| +00000050 14 cf da 2e b6 |.....| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 3b 6d ac 1c 8b |.......... ;m...| -00000010 1b 46 3a 4e 03 75 51 9e 99 6e 5a a8 4f 07 91 a3 |.F:N.uQ..nZ.O...| -00000020 18 2c bf 88 92 17 e5 13 65 a3 6c |.,......e.l| +00000000 14 03 03 00 01 01 16 03 03 00 20 31 25 d4 c7 92 |.......... 1%...| +00000010 16 0b 92 2d a2 20 8b b2 c7 96 a6 b7 b6 b3 82 3a |...-. .........:| +00000020 4d a1 a8 96 29 fb 99 e9 ea 04 6c |M...).....l| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 c7 94 fc be 3d 73 fd ec ce b2 f6 |.........=s.....| -00000010 bf 17 bf 52 3e b4 98 39 43 c0 0a |...R>..9C..| +00000000 17 03 03 00 16 8b 92 f3 f8 99 bf a3 7c c4 03 d8 |............|...| +00000010 4d e7 1b ad 50 e1 99 17 33 68 e2 |M...P...3h.| >>> Flow 6 (server to client) -00000000 16 03 03 00 14 cf 01 f5 e6 eb 60 e3 49 c4 fb 84 |..........`.I...| -00000010 e1 11 69 e1 91 c0 02 d2 e3 |..i......| +00000000 16 03 03 00 14 91 99 15 68 ae 92 52 bd 13 75 45 |........h..R..uE| +00000010 6d a9 f0 2d ee f5 c3 9b e7 |m..-.....| >>> Flow 7 (client to server) -00000000 15 03 03 00 12 4d 7f de 01 23 f7 3f 0d e6 1a f1 |.....M...#.?....| -00000010 19 a2 cd 58 1a 25 f5 15 03 03 00 12 95 78 52 00 |...X.%.......xR.| -00000020 65 aa 6d 77 5a 66 d5 95 c4 5a 9b 1b 05 b2 |e.mwZf...Z....| +00000000 15 03 03 00 12 be 8b 4b a6 a7 7a 62 45 32 ff db |.......K..zbE2..| +00000010 07 ad a0 1b 46 9d c9 15 03 03 00 12 16 da d4 86 |....F...........| +00000020 4f c8 26 5a d0 34 82 fe 47 34 ae 31 db a7 |O.&Z.4..G4.1..| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-SCT b/libgo/go/crypto/tls/testdata/Client-TLSv12-SCT index d12e263..8492ee9 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-SCT +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-SCT @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,11 +16,11 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 01 c6 02 00 01 c2 03 03 d8 a9 75 cc 9a |.............u..| -00000010 81 df 5a a0 3b ba 51 74 52 50 72 08 35 02 35 77 |..Z.;.QtRPr.5.5w| -00000020 28 ff 44 e6 d9 c6 8b f8 54 67 b4 20 62 80 60 cc |(.D.....Tg. b.`.| -00000030 09 90 52 66 75 72 a2 c5 dc 8d 18 ce 9a d5 7e cd |..Rfur........~.| -00000040 a5 36 2a 2e 65 72 6f f0 dd b0 8c 14 cc a8 00 01 |.6*.ero.........| +00000000 16 03 03 01 c6 02 00 01 c2 03 03 b0 59 eb bc ae |............Y...| +00000010 f3 42 03 d1 fe 2c 7d 6f 0e ff e4 0c 9e 13 00 b9 |.B...,}o........| +00000020 46 99 e2 84 49 64 a9 05 05 8a fb 20 16 12 dc b7 |F...Id..... ....| +00000030 e0 09 a2 a6 56 83 43 54 de 40 53 47 43 f0 2f c9 |....V.CT.@SGC./.| +00000040 2d 92 5e a0 9d a3 6a c4 55 17 01 cb cc a8 00 01 |-.^...j.U.......| 00000050 7a 00 12 01 69 01 67 00 75 00 a4 b9 09 90 b4 18 |z...i.g.u.......| 00000060 58 14 87 bb 13 a2 cc 67 70 0a 3c 35 98 04 f9 1b |X......gp.<5....| 00000070 df b8 e3 77 cd 0e c8 0d dc 10 00 00 01 47 97 99 |...w.........G..| @@ -83,31 +83,31 @@ 00000400 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 |.....@.a.Lr+...F| 00000410 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 |..M...>...B...=.| 00000420 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 ac 0c 00 |`.\!.;..........| -00000430 00 a8 03 00 1d 20 cd 2a 10 ee 97 4a 83 7b 0e 6d |..... .*...J.{.m| -00000440 e7 00 5a ce bc d8 1c 57 fa f6 ec 52 0d 0f be 6d |..Z....W...R...m| -00000450 c8 5d 27 3c 8c 1b 08 04 00 80 a9 4c bb 3a 0a d7 |.]'<.......L.:..| -00000460 db 72 3d 88 49 a6 0b f7 dc d5 e1 d0 07 e8 6c fa |.r=.I.........l.| -00000470 b0 5e 0b 13 27 29 6f 1f 1e b9 05 60 16 cc ea 7b |.^..')o....`...{| -00000480 46 d7 12 58 03 43 b0 fe 8e 7b 83 3b ee 11 78 8c |F..X.C...{.;..x.| -00000490 60 0f 9c 76 63 60 01 78 a0 9b 19 b9 32 99 a9 9d |`..vc`.x....2...| -000004a0 42 b8 1f f1 8b 87 07 32 fa 5e 74 d5 3e 5e ba 21 |B......2.^t.>^.!| -000004b0 ff 63 b7 c6 68 bc b3 f9 52 1a ea 23 c7 f2 ec ff |.c..h...R..#....| -000004c0 d4 10 0d f8 76 2f bc 0d e5 12 7f ee d3 8d 9e 6b |....v/.........k| -000004d0 5e 22 78 d6 fa 5e 6a 53 16 44 16 03 03 00 04 0e |^"x..^jS.D......| +00000430 00 a8 03 00 1d 20 4c 46 c9 9f ed 2e 81 0f 8c 4b |..... LF.......K| +00000440 bc 05 53 74 c6 c8 76 99 21 94 1b 8f 93 c6 64 ce |..St..v.!.....d.| +00000450 e9 9d 6b 1d 66 51 08 04 00 80 09 9e c2 21 89 93 |..k.fQ.......!..| +00000460 1f c5 2e 2c fa 67 7b 42 23 e1 e0 67 5c 6d e9 1e |...,.g{B#..g\m..| +00000470 e8 a2 ac d7 cf f4 12 98 f6 e6 3d 51 0c 2c 29 ad |..........=Q.,).| +00000480 f8 8e 24 2a a3 99 2e f3 b2 a7 fe a9 6c e9 00 d8 |..$*........l...| +00000490 6a 7f 41 12 84 a0 d6 19 38 b1 5a 13 b6 71 cf bd |j.A.....8.Z..q..| +000004a0 e2 6e 04 01 c8 cd 83 12 71 85 ae bc 94 b1 e4 4d |.n......q......M| +000004b0 a5 5f 9e a5 5d 95 76 fe f5 d6 a9 f0 4c 07 c9 6e |._..].v.....L..n| +000004c0 fc 4a 56 2b 56 4e 9c ec 2c fe bc 9c 9e 57 f3 90 |.JV+VN..,....W..| +000004d0 c6 6e 77 5a cf 8c 1a 15 cd 90 16 03 03 00 04 0e |.nwZ............| 000004e0 00 00 00 |...| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 20 5c 1a 1b 0e 7e 83 4f 9b f6 8e 9f |.... \...~.O....| -00000040 ca 95 86 c3 7b 60 73 d3 8d 3c 6d 18 6a eb 70 a3 |....{`s..<m.j.p.| -00000050 d9 08 f7 77 a3 |...w.| +00000030 16 03 03 00 20 19 bf ac 05 d4 bb 8a 6d 11 f4 98 |.... .......m...| +00000040 0d af 78 57 49 74 5c 44 45 9e 2c 92 26 b9 10 b5 |..xWIt\DE.,.&...| +00000050 6d 5f 24 bc a6 |m_$..| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 20 1f a2 50 dd c5 |.......... ..P..| -00000010 ba 96 4a 63 e1 cc b6 45 77 09 c1 49 cb 5f eb 4b |..Jc...Ew..I._.K| -00000020 38 9b b1 40 1c af b1 a2 dc 7c ba |8..@.....|.| +00000000 14 03 03 00 01 01 16 03 03 00 20 69 3a c4 9c ee |.......... i:...| +00000010 91 6b bc 33 39 82 64 c2 0a f0 a4 dd 85 16 3c ce |.k.39.d.......<.| +00000020 39 c4 98 37 77 47 1e c2 c6 d8 f6 |9..7wG.....| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 e7 54 f6 bf 56 39 57 c4 b2 ac f2 |......T..V9W....| -00000010 b1 f4 b1 2f ad ae d7 87 21 ff 1c 15 03 03 00 12 |.../....!.......| -00000020 5d b6 56 77 55 99 b6 7b a4 0b d8 8e 8d 93 b6 35 |].VwU..{.......5| -00000030 ce 9a |..| +00000000 17 03 03 00 16 92 25 9b 97 11 08 71 63 b2 c1 35 |......%....qc..5| +00000010 14 3b e7 15 f6 05 67 51 46 db ba 15 03 03 00 12 |.;....gQF.......| +00000020 b2 53 a1 ec a8 cf 79 7d f8 86 70 05 e5 81 a1 6c |.S....y}..p....l| +00000030 41 ab |A.| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE b/libgo/go/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE index d58a32f..3d3de61 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 75 00 05 00 05 01 00 00 00 00 00 0a 00 |...u............| 00000090 04 00 02 00 1d 00 0b 00 02 01 00 00 0d 00 1a 00 |................| 000000a0 18 08 04 04 03 08 07 08 05 08 06 04 01 05 01 06 |................| @@ -16,11 +16,11 @@ 000000e0 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| 000000f0 c2 ed 90 99 5f 58 cb 3b 74 |...._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 59 02 00 00 55 03 03 e0 c7 ce be 3a |....Y...U......:| -00000010 a6 34 5f b7 c5 ec f1 f3 09 df 4d db 39 60 71 93 |.4_.......M.9`q.| -00000020 db 7c 30 e0 81 93 f0 19 57 6b 6b 20 9e 4b e2 1e |.|0.....Wkk .K..| -00000030 27 8d d3 f6 0c f3 3d bc 67 3e 79 33 fd c9 cc 55 |'.....=.g>y3...U| -00000040 36 55 a5 aa 89 94 fe b2 51 cf 24 56 c0 2f 00 00 |6U......Q.$V./..| +00000000 16 03 03 00 59 02 00 00 55 03 03 f7 79 97 18 3c |....Y...U...y..<| +00000010 fa 52 c6 d2 6b 1e de a5 60 da d5 e2 0b f6 23 a8 |.R..k...`.....#.| +00000020 48 94 e8 1f fb b9 76 43 94 e8 98 20 31 a5 85 d5 |H.....vC... 1...| +00000030 2f c4 93 b1 ae aa 50 bc 14 9e 57 79 18 85 cd ef |/.....P...Wy....| +00000040 b4 f0 42 c9 6c b1 86 c1 03 27 ca df c0 2f 00 00 |..B.l....'.../..| 00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| 00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..| 00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............| @@ -60,33 +60,33 @@ 00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.| 000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..| 000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......| -000002c0 ac 0c 00 00 a8 03 00 1d 20 9b 73 58 2f 9a aa 8b |........ .sX/...| -000002d0 3e 80 1c b1 8e e5 d4 54 c2 d0 b1 94 16 86 e2 4b |>......T.......K| -000002e0 9c ab d7 ce 2c e5 26 20 04 08 04 00 80 d8 c0 18 |....,.& ........| -000002f0 90 8e 06 d8 d6 4c af a1 ae 5e ca 4b a1 18 bb 31 |.....L...^.K...1| -00000300 f5 3a 75 c3 d7 73 69 a7 e0 0f 8e f2 c5 92 0a bd |.:u..si.........| -00000310 7f 91 36 6c 01 c3 eb 08 9a 3b 25 2c bd 86 88 05 |..6l.....;%,....| -00000320 64 e0 38 5b 75 01 10 1f 1b d5 34 09 04 2e 34 6d |d.8[u.....4...4m| -00000330 71 d2 6c b6 f3 7a 1e ed a9 9d 28 60 13 fc 02 6f |q.l..z....(`...o| -00000340 f6 17 99 52 7b 19 60 e5 a6 11 d4 b3 4c 52 03 b5 |...R{.`.....LR..| -00000350 3e 28 91 c6 66 87 25 df 10 c6 cf b9 5f 92 0e d7 |>(..f.%....._...| -00000360 b6 19 f0 19 b9 f6 e9 e9 24 74 35 3b c6 16 03 03 |........$t5;....| +000002c0 ac 0c 00 00 a8 03 00 1d 20 90 95 bd 82 cf 8a cc |........ .......| +000002d0 08 b4 09 09 8d 59 2d 03 7a bb 92 4a c4 5c 08 4d |.....Y-.z..J.\.M| +000002e0 42 a3 ba cb 9a 43 ae f0 22 08 04 00 80 a0 97 ac |B....C..".......| +000002f0 01 a5 c8 7b 4c 73 7e 70 7a 9a fc 9d 71 2f fe 67 |...{Ls~pz...q/.g| +00000300 ca dd 6b 43 db 64 0f 64 52 e7 d3 5d 6d b2 7c 50 |..kC.d.dR..]m.|P| +00000310 74 7e 80 d5 22 77 3f fb c2 e8 dc 92 37 4f 1e 1e |t~.."w?.....7O..| +00000320 e7 13 f2 01 33 80 32 66 4f c2 17 8e ec 4f ed 4a |....3.2fO....O.J| +00000330 15 6c e8 86 ec df d5 46 6c a5 43 0d 40 fe a0 c8 |.l.....Fl.C.@...| +00000340 65 b4 76 46 b8 36 2c da 87 7c 60 87 db 39 4c 2e |e.vF.6,..|`..9L.| +00000350 0f e4 72 32 11 26 99 7e c8 7a c0 bc 9c a7 29 57 |..r2.&.~.z....)W| +00000360 9d 27 37 4e ec c5 bb fd a1 3c f3 66 63 16 03 03 |.'7N.....<.fc...| 00000370 00 04 0e 00 00 00 |......| >>> Flow 3 (client to server) 00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.| 00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....| 00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......| -00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 01 e4 5a |....(..........Z| -00000040 e9 dc dd 98 cd 5f d2 d2 eb 84 12 c9 96 ca 91 d7 |....._..........| -00000050 ae f4 db 44 a4 37 f3 a3 b2 8d db ed 3d |...D.7......=| +00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 81 b1 2c |....(..........,| +00000040 a2 3b 38 34 a6 66 57 02 e3 67 1b ee 73 95 50 de |.;84.fW..g..s.P.| +00000050 dd 5a fd 4e 0d ee b7 a6 46 1a 34 61 73 |.Z.N....F.4as| >>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 28 c2 2d 32 ba 46 |..........(.-2.F| -00000010 27 8d 87 13 7f b9 49 04 64 2f 6e cc 32 81 f8 3c |'.....I.d/n.2..<| -00000020 7f 0f 19 13 5c 11 33 a1 05 5f 91 bc 97 30 64 84 |....\.3.._...0d.| -00000030 57 69 90 |Wi.| +00000000 14 03 03 00 01 01 16 03 03 00 28 2f a9 80 36 d8 |..........(/..6.| +00000010 d0 74 e4 39 46 04 88 8e 91 ea fd 96 ed 1f 89 9f |.t.9F...........| +00000020 a4 e9 24 0e ca 48 2b 5c 5d f1 cc 57 ce 92 1a ad |..$..H+\]..W....| +00000030 b9 10 11 |...| >>> Flow 5 (client to server) -00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 fd 0f a5 |................| -00000010 74 98 c4 98 ee 67 74 d4 c1 d4 fe d3 c7 e2 1b 2c |t....gt........,| -00000020 e5 3c be 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.<..............| -00000030 f8 d4 60 41 13 6a 9c e3 0e 56 e2 ab 96 45 7e 06 |..`A.j...V...E~.| -00000040 87 63 |.c| +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 da be 68 |...............h| +00000010 97 b4 a4 72 d0 ed 75 66 6a a9 6f 39 8a 08 a9 db |...r..ufj.o9....| +00000020 de 4d e1 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.M..............| +00000030 14 90 0e 1d 26 5c 18 c6 5c 93 66 c4 90 78 a8 91 |....&\..\.f..x..| +00000040 cb fd |..| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv13-AES128-SHA256 b/libgo/go/crypto/tls/testdata/Client-TLSv13-AES128-SHA256 index 4273484..f8a733e 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv13-AES128-SHA256 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv13-AES128-SHA256 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,75 +16,75 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 f7 30 f3 d1 e7 |....z...v...0...| -00000010 eb 94 97 a2 c6 d5 be 74 e0 6c 08 80 2f ad 11 6b |.......t.l../..k| -00000020 b3 ce 22 59 06 a9 eb 41 9c 97 a8 20 00 00 00 00 |.."Y...A... ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 f1 4c f4 16 24 |....z...v...L..$| +00000010 e5 c6 b5 ce 72 08 3b 33 9f 1f 1f 80 2c 10 0b 34 |....r.;3....,..4| +00000020 01 99 85 ba b0 3c 85 50 3d bf 73 20 00 00 00 00 |.....<.P=.s ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 01 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 c0 |..+.....3.$... .| -00000060 47 7e ad a1 41 53 e5 25 ec 74 46 bc 9e 80 08 3b |G~..AS.%.tF....;| -00000070 0b f5 7e fb 71 1f 00 d5 4b 27 51 22 4a 5e 5f 14 |..~.q...K'Q"J^_.| -00000080 03 03 00 01 01 17 03 03 00 17 e9 e8 56 00 26 9e |............V.&.| -00000090 92 60 84 6c 07 3d b1 ef e4 63 51 ba 48 ee d7 fe |.`.l.=...cQ.H...| -000000a0 57 17 03 03 02 6d 2e d4 bb bf a2 e8 3b 84 47 2e |W....m......;.G.| -000000b0 22 66 c1 98 ea 11 6b a3 4d 1b 64 c0 02 32 76 9b |"f....k.M.d..2v.| -000000c0 29 8a 4a 96 68 5b d1 fd a0 0f a6 9b 70 20 c7 08 |).J.h[......p ..| -000000d0 7b 25 07 d1 54 8c b1 bb 4e ba 32 65 2c 1e 16 29 |{%..T...N.2e,..)| -000000e0 e7 d2 df e3 84 60 e1 43 07 99 35 4d 95 7c 27 96 |.....`.C..5M.|'.| -000000f0 be f4 bf 0a e9 3b 9d 60 7a 6e 34 82 1f 03 ca 17 |.....;.`zn4.....| -00000100 ac d1 a1 b5 dc 3f 20 7b 42 f6 94 43 60 ff 3f 1b |.....? {B..C`.?.| -00000110 b1 2e 2d 71 55 07 fb 65 40 56 59 82 1e 31 83 c9 |..-qU..e@VY..1..| -00000120 35 6c 28 ad c1 bd 88 55 1b b6 1e 89 af 64 7f 11 |5l(....U.....d..| -00000130 53 80 3a 62 ef 34 a7 d0 ce 38 9b 19 d6 5f 78 0d |S.:b.4...8..._x.| -00000140 66 73 b2 bd b6 a6 f8 70 c8 40 f9 aa a2 86 f4 48 |fs.....p.@.....H| -00000150 0d 6c 54 67 c6 3c 91 97 ff 94 4d 9a 01 d5 e1 c9 |.lTg.<....M.....| -00000160 8f 27 d3 8d b3 72 cd 34 eb 7a 6d 48 84 f3 8b 84 |.'...r.4.zmH....| -00000170 34 d2 68 bd 26 bc 6d e5 46 41 cc 86 d4 7a b6 31 |4.h.&.m.FA...z.1| -00000180 05 b3 bc a4 fe e1 5c d4 eb 8b fe 64 0e be 89 c4 |......\....d....| -00000190 ce e0 49 a0 ba 7a 83 b6 fb 31 17 42 fd b4 e3 59 |..I..z...1.B...Y| -000001a0 48 df f6 a8 e4 5c d1 77 77 cb c2 31 85 8a 26 65 |H....\.ww..1..&e| -000001b0 20 fa 05 90 ae 66 95 7a 75 4b bc 93 15 dd a0 13 | ....f.zuK......| -000001c0 61 d5 99 fb b2 27 bd ec fd 10 b5 d2 c7 18 ac b9 |a....'..........| -000001d0 bd bc 35 72 d0 42 6c f7 5a e0 67 46 45 10 f7 50 |..5r.Bl.Z.gFE..P| -000001e0 e4 14 47 ac 39 5a 05 38 b9 25 4a 43 fa 57 b2 51 |..G.9Z.8.%JC.W.Q| -000001f0 b7 3e f7 ef d5 b5 de 2e 2f 5c d0 d7 00 23 ac 4b |.>....../\...#.K| -00000200 65 8d 6c f4 ab 6f ef 1e c2 66 c5 b2 cb 1a 51 4c |e.l..o...f....QL| -00000210 ef 96 8f 28 65 2f 50 9c 91 1f 73 87 fc 81 db 90 |...(e/P...s.....| -00000220 16 69 00 06 98 6b 00 33 41 e1 e6 12 89 cb c9 f3 |.i...k.3A.......| -00000230 23 2c 28 83 00 ca 4f 42 f5 26 bc 94 39 3b 18 31 |#,(...OB.&..9;.1| -00000240 41 a9 19 4a 60 e8 de 8f 1d d0 e8 96 77 c0 49 bd |A..J`.......w.I.| -00000250 a2 98 bd b1 0a 6f bd 27 79 1d c4 33 50 37 a8 eb |.....o.'y..3P7..| -00000260 a5 4e 59 87 58 cd f0 a0 34 4e 2b 9d ee 03 e4 8a |.NY.X...4N+.....| -00000270 24 94 86 11 e1 94 f0 2b 3e 27 9a 92 1c 17 d3 96 |$......+>'......| -00000280 c0 71 ab ee 75 5f 99 ca 0e 42 65 5d ed 48 0c 7a |.q..u_...Be].H.z| -00000290 95 8a d9 da f7 60 ee de 46 f2 f4 7a d6 ce 38 41 |.....`..F..z..8A| -000002a0 fa e8 1f 3e 77 be 02 53 0c 33 96 5b 0d 38 bb 08 |...>w..S.3.[.8..| -000002b0 5e 92 1a 81 f1 be c7 9a e2 02 80 09 3b b7 62 b0 |^...........;.b.| -000002c0 7c a7 85 3a d9 52 34 23 4f a3 04 e7 35 98 9e 18 ||..:.R4#O...5...| -000002d0 13 0b 71 12 6d a4 2e 11 bf 39 8c 94 ef 15 96 27 |..q.m....9.....'| -000002e0 9e be 81 d9 55 5a 8b 14 c5 49 dd 6e 6e 7b 6b c2 |....UZ...I.nn{k.| -000002f0 f3 7d ef 24 88 b9 eb a6 15 3e aa a8 3e eb 37 54 |.}.$.....>..>.7T| -00000300 fc 86 9f 51 30 5f 9c a5 fc 7a af f6 1b a5 a4 27 |...Q0_...z.....'| -00000310 51 78 f7 17 03 03 00 99 79 14 63 10 91 cd 73 f5 |Qx......y.c...s.| -00000320 a8 62 c3 92 a3 04 c2 3d 58 5e d3 6e 93 eb 9b b1 |.b.....=X^.n....| -00000330 11 f0 3c c6 96 9f c6 c8 9b de 2c d5 12 c2 bd d1 |..<.......,.....| -00000340 2a 68 89 4a 07 1e 23 d2 45 ca a1 0f 92 71 b7 f7 |*h.J..#.E....q..| -00000350 d0 2f 2a be d0 5e 0c 5d 13 8f b0 7f df b8 52 2e |./*..^.]......R.| -00000360 7a 5e c8 eb 84 06 46 81 d0 f7 09 18 52 fb ce fd |z^....F.....R...| -00000370 22 d8 74 71 e8 7d 41 5f 3a 5d e5 f9 bb e6 99 03 |".tq.}A_:]......| -00000380 32 d1 58 e8 5a 58 d8 b2 39 61 01 33 72 7d d2 11 |2.X.ZX..9a.3r}..| -00000390 8f f7 58 55 c8 f2 64 63 33 9b 78 36 bf 9b 8b 40 |..XU..dc3.x6...@| -000003a0 8c ec 7b a2 bb 51 ed b1 fe 74 c2 c9 1f b4 2b cb |..{..Q...t....+.| -000003b0 fd 17 03 03 00 35 75 46 88 74 06 9b 5e 88 c2 0d |.....5uF.t..^...| -000003c0 fc 7d 29 bd 6c 1c 23 2f 06 3f 14 b1 55 e4 98 b1 |.}).l.#/.?..U...| -000003d0 ed c3 9a ed ea be 29 60 15 ac 80 c7 a8 f7 9b ce |......)`........| -000003e0 f3 79 b3 be ad ff ab b4 a7 45 57 |.y.......EW| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 69 |..+.....3.$... i| +00000060 94 3b 83 cd 1f 93 53 53 82 de 14 cb 76 2a 19 62 |.;....SS....v*.b| +00000070 0f f8 9e d1 e3 e0 a9 d5 23 ac 07 64 53 27 4b 14 |........#..dS'K.| +00000080 03 03 00 01 01 17 03 03 00 17 ef 24 2c ea 6f 05 |...........$,.o.| +00000090 c2 07 7a d2 12 30 ce 01 f4 96 b8 dc e6 c2 27 02 |..z..0........'.| +000000a0 bd 17 03 03 02 6d 99 2b cb 79 43 01 66 24 eb f1 |.....m.+.yC.f$..| +000000b0 14 d2 ea 1e 57 67 81 e3 a0 9c 99 1b 1f d5 f0 c7 |....Wg..........| +000000c0 78 48 61 01 42 25 85 0b cd a1 b1 75 3c 50 01 cc |xHa.B%.....u<P..| +000000d0 69 09 22 a5 fb db 43 76 2f 4e 34 4e 14 a3 e4 89 |i."...Cv/N4N....| +000000e0 f7 d7 cd 66 da b3 1d fd f0 98 60 18 41 09 a5 22 |...f......`.A.."| +000000f0 6d c9 21 bc c3 cd 53 ca c3 a5 d7 24 57 b4 f5 bc |m.!...S....$W...| +00000100 ec b1 48 70 12 55 a5 a6 01 10 68 0f c4 e5 de 89 |..Hp.U....h.....| +00000110 f9 0d ab 48 92 d4 12 d7 75 77 c3 2f ae 2f 6f 58 |...H....uw././oX| +00000120 2d 6e ad 72 43 dc ce 4b c9 74 3d eb db da 37 2c |-n.rC..K.t=...7,| +00000130 1e a2 86 c4 b3 64 69 f6 84 ce 52 b5 32 c6 b9 c2 |.....di...R.2...| +00000140 49 2d 08 f9 d4 9a 29 09 5b 71 09 81 a3 19 c2 4d |I-....).[q.....M| +00000150 8c 48 2c e3 c6 cb 81 d4 7f 10 b3 c8 2b 21 ad 83 |.H,.........+!..| +00000160 97 d2 bd 11 90 39 1e f4 de 65 e2 e8 e8 c7 ce f9 |.....9...e......| +00000170 6d ad b0 60 5c 4b 59 c4 96 ce b3 a1 83 b2 7c 71 |m..`\KY.......|q| +00000180 74 e6 a9 a7 89 bf 8d 0d 6c 8d b5 04 33 38 ff 68 |t.......l...38.h| +00000190 42 0e 84 da d2 b2 16 29 83 66 82 a9 2a d2 67 1b |B......).f..*.g.| +000001a0 18 a6 7d e3 f1 d3 f1 b4 cc 6c 14 e2 cd 2d 96 7b |..}......l...-.{| +000001b0 76 dd b0 1d 24 7f ea c0 14 24 d7 37 00 7c cd e3 |v...$....$.7.|..| +000001c0 20 33 a4 3a 22 2a be 3e e8 f8 7c 0d 3e 51 f7 6b | 3.:"*.>..|.>Q.k| +000001d0 ce f3 51 cf 7e ae 55 40 bb ab 0e 40 6b d9 8a 3b |..Q.~.U@...@k..;| +000001e0 d5 f2 1f 76 6a 05 9b 87 e2 3b db fa cc e8 93 8a |...vj....;......| +000001f0 d9 ba 2b 63 77 77 62 f1 22 ce 11 a9 26 b5 e8 a2 |..+cwwb."...&...| +00000200 ec 3f 98 44 01 27 d7 e1 39 26 33 e3 86 00 60 f7 |.?.D.'..9&3...`.| +00000210 a7 91 07 45 f8 3f 78 dc 88 71 30 26 0c f9 0d 51 |...E.?x..q0&...Q| +00000220 2a c5 ce 33 ac b7 91 a9 74 2e 46 68 80 6e 62 cd |*..3....t.Fh.nb.| +00000230 2d 5e 43 fe bd d1 37 07 71 85 5d c7 38 17 50 3a |-^C...7.q.].8.P:| +00000240 1c 5e 9f cf 1e 3c 96 d0 26 5d 4c 82 78 a8 69 e7 |.^...<..&]L.x.i.| +00000250 d3 9a 81 e5 85 66 c3 d9 74 a1 82 9d fb 24 81 13 |.....f..t....$..| +00000260 0d ce cb 43 61 3c 3a a7 d1 80 7f 1d 41 d8 62 43 |...Ca<:.....A.bC| +00000270 c6 08 5d 91 05 ed 2c 50 04 42 8c db 2a 11 61 96 |..]...,P.B..*.a.| +00000280 9b d2 1d 40 af 83 ed 93 06 ba 65 22 0a a5 e8 a6 |...@......e"....| +00000290 b9 4a 63 6f c0 ac da 72 10 24 c6 ed 08 86 c8 a1 |.Jco...r.$......| +000002a0 92 5e d0 d8 8b 04 b7 43 50 0b 03 41 3f f9 96 16 |.^.....CP..A?...| +000002b0 a3 c8 09 e8 ac 91 b2 45 d5 58 5f 41 05 7c b3 88 |.......E.X_A.|..| +000002c0 7a 59 cd 1a 00 86 29 72 77 a5 19 43 32 79 fc d6 |zY....)rw..C2y..| +000002d0 d7 e9 81 08 e3 d9 d9 56 39 59 7c 1e d3 10 3e a4 |.......V9Y|...>.| +000002e0 c6 80 d3 8b 9b 36 51 c5 d3 14 64 a6 65 e2 1a 26 |.....6Q...d.e..&| +000002f0 c4 a8 31 07 bb 58 8c 9b d8 7d 86 fd 54 6c c9 ae |..1..X...}..Tl..| +00000300 7d 88 4b 13 0f 52 10 41 d6 be 01 32 f2 42 47 0f |}.K..R.A...2.BG.| +00000310 7a 8c 7e 17 03 03 00 99 8b ce c4 db 9c 9c 88 e3 |z.~.............| +00000320 88 58 de 8f 10 e9 fb 4a c7 26 96 60 48 84 2c b1 |.X.....J.&.`H.,.| +00000330 2b 6c 35 70 8a d7 39 91 51 d7 3f db 81 f0 41 07 |+l5p..9.Q.?...A.| +00000340 a2 c9 c1 74 76 62 58 f1 cb e2 50 48 57 bb 6e 3d |...tvbX...PHW.n=| +00000350 ee ee 4a 53 e7 3c 66 aa e3 d9 c1 f1 74 1a 93 b9 |..JS.<f.....t...| +00000360 44 90 f6 a5 a4 da f5 6b 75 01 38 52 8f 9c ab 01 |D......ku.8R....| +00000370 78 88 a6 cc 65 15 61 a8 8c cc 14 59 07 ea 6f 25 |x...e.a....Y..o%| +00000380 5c 86 89 16 eb e7 da 20 82 d7 96 e4 78 7a c3 36 |\...... ....xz.6| +00000390 b3 5c e7 17 1b 07 30 a2 72 ca a2 f3 dc 7e 45 c9 |.\....0.r....~E.| +000003a0 7f 94 f8 a1 7b bb 2a 30 d7 bc 51 03 fb e6 2a fa |....{.*0..Q...*.| +000003b0 17 17 03 03 00 35 c1 a0 76 b6 35 4b 5c 26 94 c6 |.....5..v.5K\&..| +000003c0 ba b1 7b b1 13 00 f2 2c 17 ed ac ab 47 9a a1 8d |..{....,....G...| +000003d0 3a 1c 78 44 14 a1 04 31 3d eb 9a 8d bb 2f 73 46 |:.xD...1=..../sF| +000003e0 cb 5c f6 86 81 fa 56 fb 39 8c 55 |.\....V.9.U| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 b5 22 19 23 49 |..........5.".#I| -00000010 48 33 a5 f3 b2 72 2b 31 ab 89 27 f9 eb 1b b7 b1 |H3...r+1..'.....| -00000020 bc 2b 99 9e 73 24 42 c4 2a 68 2c 76 e1 45 61 09 |.+..s$B.*h,v.Ea.| -00000030 18 c7 44 45 9a 05 86 4c 90 c1 41 c6 fd 6a c2 95 |..DE...L..A..j..| -00000040 17 03 03 00 17 ee 18 4e d9 94 15 50 a9 99 4a 82 |.......N...P..J.| -00000050 10 13 26 7b 74 10 db ef fe b8 96 f6 17 03 03 00 |..&{t...........| -00000060 13 2a 4c 52 8d c3 c5 af d0 cd 5a 7d 0d a5 59 90 |.*LR......Z}..Y.| -00000070 ce 59 3b af |.Y;.| +00000000 14 03 03 00 01 01 17 03 03 00 35 97 2c 39 3a a5 |..........5.,9:.| +00000010 32 33 e5 74 43 97 98 ef ef 30 de 27 8b f7 b5 ab |23.tC....0.'....| +00000020 dd af 87 7c a5 5e 76 cf 50 2a 03 f8 94 a4 7a df |...|.^v.P*....z.| +00000030 14 0a 2d 39 57 3b 02 97 c5 d7 63 85 21 3f 55 27 |..-9W;....c.!?U'| +00000040 17 03 03 00 17 7c b4 8b 82 f0 0a ec 6f fa 60 ef |.....|......o.`.| +00000050 4c 0a 1c 0b ad 99 c3 89 fb a4 40 2c 17 03 03 00 |L.........@,....| +00000060 13 f2 d5 58 ba 6b ca e8 f4 14 4c 66 23 38 f2 e8 |...X.k....Lf#8..| +00000070 ea a9 ba c1 |....| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv13-AES256-SHA384 b/libgo/go/crypto/tls/testdata/Client-TLSv13-AES256-SHA384 index 7fecc79..8ea3ed6 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv13-AES256-SHA384 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv13-AES256-SHA384 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,77 +16,77 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 dd df 8d 85 da |....z...v.......| -00000010 3c 99 a3 0c 01 90 5f ec b8 3d 28 ce e4 32 c0 e8 |<....._..=(..2..| -00000020 fe 77 03 ad 0f e1 33 1f dc 89 cb 20 00 00 00 00 |.w....3.... ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 71 00 90 30 07 |....z...v..q..0.| +00000010 24 01 ae 33 b2 e8 4f 1f 9a 2c 83 e5 7b 30 1e a2 |$..3..O..,..{0..| +00000020 8e 4a d0 df d1 ec 23 b5 ba aa 75 20 00 00 00 00 |.J....#...u ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 02 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 03 |..+.....3.$... .| -00000060 6b 91 90 36 f0 54 da 66 8e 47 9b 26 9f 9f ae 30 |k..6.T.f.G.&...0| -00000070 69 9e a2 6a 70 fb ef b2 f1 76 2b 32 90 0e 63 14 |i..jp....v+2..c.| -00000080 03 03 00 01 01 17 03 03 00 17 46 47 2e ae ea 9b |..........FG....| -00000090 78 7b 0c d4 74 e2 b5 bf 7b 64 da c3 d3 c9 55 7f |x{..t...{d....U.| -000000a0 e3 17 03 03 02 6d a8 c1 57 27 66 9d 16 f6 4f 1b |.....m..W'f...O.| -000000b0 17 b6 5d 8c 3c fe f5 d5 4a d3 c6 8d e2 a8 2d d0 |..].<...J.....-.| -000000c0 01 8d db 18 e8 c8 69 74 eb 81 9e 97 20 01 60 d5 |......it.... .`.| -000000d0 96 d1 8f 9c de 09 ff 1d e7 45 97 97 36 fa 89 77 |.........E..6..w| -000000e0 88 20 30 c6 5b 42 d6 0e 85 9a 11 43 60 a1 86 34 |. 0.[B.....C`..4| -000000f0 22 47 25 23 a5 35 87 a9 74 5d fe eb c9 70 32 44 |"G%#.5..t]...p2D| -00000100 17 60 55 99 7a 93 b5 92 8b 66 31 ce dc e0 39 f2 |.`U.z....f1...9.| -00000110 6a b3 db 43 5d 3f ba e5 12 12 1f 0e 3c 35 3b 72 |j..C]?......<5;r| -00000120 9f 9d 69 d5 d6 cb ac b5 9e f4 af f5 74 68 67 f4 |..i.........thg.| -00000130 e9 5f a4 4a d7 27 5b a5 2a 39 b7 30 49 4d 64 bb |._.J.'[.*9.0IMd.| -00000140 5d 89 10 ff a6 2c 42 a1 4a 2a 0c 28 c6 cd 4a e8 |]....,B.J*.(..J.| -00000150 7d 24 d0 75 ff 61 08 3f 3b 05 ec f3 d6 61 ed 43 |}$.u.a.?;....a.C| -00000160 08 5e 07 1c f2 15 96 22 2a c0 3c 5f 04 d1 17 82 |.^....."*.<_....| -00000170 ea ee ee c7 49 cc 3e e4 65 15 97 6e 6f 36 24 a9 |....I.>.e..no6$.| -00000180 27 34 3a 75 dc 07 1e 4c f1 29 d1 e3 22 31 7d 84 |'4:u...L.).."1}.| -00000190 a8 2a 7f 37 03 ab 13 ae 15 e2 74 50 bd 54 5b 32 |.*.7......tP.T[2| -000001a0 ea 75 10 ed 39 5c 69 90 f6 74 09 53 c1 ce 44 49 |.u..9\i..t.S..DI| -000001b0 64 fb f2 c6 bd 93 b2 07 06 96 94 04 a5 9e ed 67 |d..............g| -000001c0 10 cb 01 fc 85 45 d7 22 76 3c c6 2f 14 4c 31 e1 |.....E."v<./.L1.| -000001d0 73 81 7b 8b 6b 54 d6 34 15 d2 eb d0 03 10 c7 3d |s.{.kT.4.......=| -000001e0 f5 07 48 cc 72 9b e9 48 ee 13 9f 80 b5 13 86 77 |..H.r..H.......w| -000001f0 33 91 79 6f f2 13 17 68 ca 72 6b 0d 93 9a 20 30 |3.yo...h.rk... 0| -00000200 70 c3 30 ab 13 7e 14 39 97 4b ce c5 3d 8b 03 7f |p.0..~.9.K..=...| -00000210 cd 4b 67 c4 c5 79 0c bb cd ba 17 c5 d5 15 51 cb |.Kg..y........Q.| -00000220 ac b7 f7 19 43 ff f5 c4 09 8c 44 67 ca e6 a1 5f |....C.....Dg..._| -00000230 1d 27 29 63 f2 0d 75 6d b7 62 52 c9 1d 8e 0e 3b |.')c..um.bR....;| -00000240 6c cb 04 3e f7 13 74 bb 03 35 2e 4e 41 9a b7 72 |l..>..t..5.NA..r| -00000250 15 ed 02 79 c7 bc 38 b3 65 75 0a 8e 82 dc d4 79 |...y..8.eu.....y| -00000260 1c 10 3f 78 8c be 78 b0 73 18 cc 52 1d 3b 91 66 |..?x..x.s..R.;.f| -00000270 33 fe 63 b2 ec 19 92 44 8f 06 4e 20 85 94 5c b4 |3.c....D..N ..\.| -00000280 ad 22 16 a0 b3 76 03 dc 62 e9 0c ac 8c e1 67 c9 |."...v..b.....g.| -00000290 d8 6f 40 51 b5 39 9a 61 b6 63 e0 d5 60 6a 27 78 |.o@Q.9.a.c..`j'x| -000002a0 62 ec 94 1c 75 2c 38 f2 a6 f2 f0 c4 8f 98 ad cc |b...u,8.........| -000002b0 2e ce 7d 13 76 f4 4f 94 78 3f 85 cf ea 52 c4 6e |..}.v.O.x?...R.n| -000002c0 16 65 f9 48 5e f9 0b 07 bc 3e 38 91 06 e1 b0 76 |.e.H^....>8....v| -000002d0 82 60 25 03 36 9c 3e 5e 54 73 8d cf df 91 19 33 |.`%.6.>^Ts.....3| -000002e0 a7 18 96 d4 86 ea 7c 00 88 e6 a3 fe ea a1 14 db |......|.........| -000002f0 ae da 07 ef 1e 6f 16 bb ad fb c0 f4 60 2f 75 5c |.....o......`/u\| -00000300 a4 43 a0 fc 3c d6 5e 89 cf 6e 1a c6 de 61 65 34 |.C..<.^..n...ae4| -00000310 03 e5 cd 17 03 03 00 99 0a f3 a2 45 fe 53 22 37 |...........E.S"7| -00000320 cd 31 9d 67 31 56 f9 99 c2 d1 bc 6d 47 de 9a e7 |.1.g1V.....mG...| -00000330 67 c0 89 84 ac bf 27 b5 32 f0 e9 a5 9d f2 e0 ad |g.....'.2.......| -00000340 fd 12 6a a4 5d 50 4c b9 ed f1 f4 0e c0 c0 6c c4 |..j.]PL.......l.| -00000350 39 9b 10 02 fa 10 64 a6 8b af 9d 6e d9 40 6d 0c |9.....d....n.@m.| -00000360 b0 6c b8 8d d5 b0 14 f0 ed 85 d6 66 8f 6f 61 43 |.l.........f.oaC| -00000370 49 dd 95 08 94 2e a8 a6 19 b9 7b 6b 99 09 af 4c |I.........{k...L| -00000380 5f 41 48 da 10 b6 cf ee 68 b6 6e 03 d7 29 93 8e |_AH.....h.n..)..| -00000390 1a ab d1 ad d4 bf 33 2a 53 87 92 05 d1 1a de c0 |......3*S.......| -000003a0 aa ef b9 9c 4d 2d f6 b1 72 60 22 80 bb 46 24 75 |....M-..r`"..F$u| -000003b0 35 17 03 03 00 45 46 9e b3 7f d0 82 b6 ef 45 1f |5....EF.......E.| -000003c0 18 6d 3b b6 23 f5 c9 f4 54 e3 08 d0 8b 30 c7 31 |.m;.#...T....0.1| -000003d0 af 98 26 69 b7 6e 08 1d 1f be 1a 7e 5b 97 91 28 |..&i.n.....~[..(| -000003e0 fa b7 78 05 ee 3f a1 9e a0 79 fc 45 51 4c 96 fb |..x..?...y.EQL..| -000003f0 03 46 24 7d fe ec a4 40 51 d6 73 |.F$}...@Q.s| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 06 |..+.....3.$... .| +00000060 2a 26 bd 81 c2 90 9b 17 6e d0 b5 ab 72 e6 93 ce |*&......n...r...| +00000070 53 6d 8c 54 b5 a4 50 91 93 32 6e 88 e6 b2 69 14 |Sm.T..P..2n...i.| +00000080 03 03 00 01 01 17 03 03 00 17 7d 11 37 f0 18 b1 |..........}.7...| +00000090 53 55 38 bb 12 7c e8 b3 89 bc 35 fb 2a 36 d1 0f |SU8..|....5.*6..| +000000a0 3a 17 03 03 02 6d a0 fa dc 8e ac a6 90 5a 20 0e |:....m.......Z .| +000000b0 ee 22 89 7b 69 5b c9 1a a1 c6 43 b9 40 f6 85 78 |.".{i[....C.@..x| +000000c0 61 0b 14 c6 e6 3b a9 ac 4c 7a 96 9b 7b 87 d0 ce |a....;..Lz..{...| +000000d0 42 cc 75 9d fc 06 44 3e e8 12 3a 94 b7 de 86 c4 |B.u...D>..:.....| +000000e0 b5 66 e1 f5 48 21 f7 f1 58 7f 23 6c 3f 76 a0 cb |.f..H!..X.#l?v..| +000000f0 a7 f6 72 34 07 fa c1 55 3e 61 cf 72 c4 6c f1 ca |..r4...U>a.r.l..| +00000100 dd dc ec 66 3d 7b f6 cf 53 3b 28 bd 27 1b aa a6 |...f={..S;(.'...| +00000110 28 2a ab fa 48 a5 08 67 b5 49 c7 c7 5d f8 2c ec |(*..H..g.I..].,.| +00000120 83 af 58 33 42 6c c1 4c 94 17 7e 36 1c a9 48 34 |..X3Bl.L..~6..H4| +00000130 5f 26 78 f6 69 88 3a a5 1b d1 76 ad 88 63 25 33 |_&x.i.:...v..c%3| +00000140 0d e3 d0 34 6b 7f fc 96 2b 8d 22 6f 3f 21 8a 14 |...4k...+."o?!..| +00000150 01 e0 5c 54 6c c3 b8 12 f9 17 f5 4c ce e0 bd 10 |..\Tl......L....| +00000160 e7 e1 29 24 73 94 c2 5e b0 ad d3 91 9e 87 ea 23 |..)$s..^.......#| +00000170 4d fd 8f 12 ca 87 ff 2e 93 9f 16 a8 18 e1 66 8f |M.............f.| +00000180 50 76 15 cd 70 5c a2 1d 91 51 e5 54 13 5f 73 d3 |Pv..p\...Q.T._s.| +00000190 b2 6e b1 27 80 0b 3d 64 d5 fa f3 a4 fb 77 33 cb |.n.'..=d.....w3.| +000001a0 ac 93 54 36 2d 71 c3 9e dd 37 02 a9 9d b0 9b ac |..T6-q...7......| +000001b0 f8 c5 dc 43 9b d8 db c7 d0 fb cf 69 fa 62 e4 9d |...C.......i.b..| +000001c0 b7 04 f8 49 d3 a7 8d bd cf 8a e3 4a 62 cb bb 29 |...I.......Jb..)| +000001d0 b5 db 21 80 76 eb 28 67 34 1e 40 0b 83 83 19 10 |..!.v.(g4.@.....| +000001e0 46 8f bd 78 d6 7c 05 c2 19 82 1c e8 7d 84 f2 79 |F..x.|......}..y| +000001f0 c4 a6 e0 f7 7e df 70 7f 42 48 9f e4 99 03 7f 9e |....~.p.BH......| +00000200 e8 fd 75 c3 8a 55 55 8e 08 2e 62 28 a5 16 b7 11 |..u..UU...b(....| +00000210 d8 9a 11 48 46 ad d3 ba 4f 91 c8 fd 72 d9 df 98 |...HF...O...r...| +00000220 1a 59 51 55 af ab 73 b9 f3 bf fe 7d 55 7d 44 54 |.YQU..s....}U}DT| +00000230 cd bb f3 eb 6e ff 5a 09 e9 b9 c1 66 97 8e a5 7c |....n.Z....f...|| +00000240 89 4a 51 1d 8b e4 40 fb 97 ce ef 9d 7c 02 e4 db |.JQ...@.....|...| +00000250 f1 ca 01 d9 05 b4 de 10 23 33 92 ff 26 3b 09 8f |........#3..&;..| +00000260 11 7c 37 ad fb 58 ed 7a 10 08 fd df 98 dd d6 c5 |.|7..X.z........| +00000270 b8 fd 59 37 21 1d 6e 27 8a 56 24 45 e7 64 61 0b |..Y7!.n'.V$E.da.| +00000280 20 2d bc 79 89 fa 6d 7a 06 77 61 0c 60 25 e2 79 | -.y..mz.wa.`%.y| +00000290 6a 54 9e 5b 4b 33 68 17 da 63 ba a7 f9 ad 2c 84 |jT.[K3h..c....,.| +000002a0 52 e9 27 85 71 74 d2 5f c9 f8 8e 67 f7 47 58 f5 |R.'.qt._...g.GX.| +000002b0 e4 72 a7 bd 1c 94 4b 4d 13 5a 62 69 d9 6f 3a 51 |.r....KM.Zbi.o:Q| +000002c0 f0 18 90 e5 b6 21 23 97 70 74 93 ba 9b bc dc e4 |.....!#.pt......| +000002d0 3d 9c 52 3f 93 f0 48 05 e8 50 d0 b4 98 92 7a 18 |=.R?..H..P....z.| +000002e0 3f 39 ba f8 f7 ee 19 b0 ce ac d0 ab 9e 83 ee 0e |?9..............| +000002f0 5d 2a 72 74 a8 8b 4d de 6b a9 91 ad b4 a4 26 99 |]*rt..M.k.....&.| +00000300 4e aa 6d 48 77 83 78 78 be 96 f1 17 d6 96 74 4a |N.mHw.xx......tJ| +00000310 80 d1 5b 17 03 03 00 99 d9 40 96 5c fb 5d 65 69 |..[......@.\.]ei| +00000320 db 54 a8 f6 8c b7 d3 25 8d 2d c5 f1 40 5b f2 26 |.T.....%.-..@[.&| +00000330 f3 86 9e 61 6a a5 b9 66 b1 27 b1 20 6b 2c 64 84 |...aj..f.'. k,d.| +00000340 3f 48 24 5d d9 90 4b d1 ed 1b 0e 05 84 7f ad 0e |?H$]..K.........| +00000350 e6 75 f6 f9 33 90 73 7c 88 10 d7 e9 74 41 4b c3 |.u..3.s|....tAK.| +00000360 19 8e e1 a8 a6 7c 3c 9a bc 69 a7 e7 bb d6 af 98 |.....|<..i......| +00000370 f1 49 53 14 95 80 d6 95 81 5a 5e 88 2c 29 70 df |.IS......Z^.,)p.| +00000380 b2 df fe f3 17 03 e7 de af 12 57 c5 7a ef 70 eb |..........W.z.p.| +00000390 8a c6 c3 05 de 5b 15 af 5f 54 8c 7b 23 b7 e1 f1 |.....[.._T.{#...| +000003a0 30 b1 ed 34 4c 59 f5 68 c2 50 e8 c3 83 78 1d 1f |0..4LY.h.P...x..| +000003b0 eb 17 03 03 00 45 1a d4 61 ba 4a a5 1e 02 80 04 |.....E..a.J.....| +000003c0 2a 19 11 af 8c e9 bd ab 22 6b 75 41 a8 40 de 57 |*......."kuA.@.W| +000003d0 54 8c dc 09 cc 57 76 82 27 5e 59 0c 30 f7 9d c4 |T....Wv.'^Y.0...| +000003e0 fe 1c 09 f2 f4 5f e0 79 ac 02 06 80 f3 60 c4 92 |....._.y.....`..| +000003f0 cd 6a df b6 46 7c de 90 8d bb 94 |.j..F|.....| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 45 44 15 b9 ed d8 |..........ED....| -00000010 10 2c 88 80 79 f3 38 a4 bc 42 9b 22 09 44 d9 19 |.,..y.8..B.".D..| -00000020 e1 0a ec 15 aa d5 15 e9 19 6d b8 6b 71 63 86 ce |.........m.kqc..| -00000030 e7 16 0d 8e 3f 9a 3b 52 25 1e 96 f6 d9 d1 6c dd |....?.;R%.....l.| -00000040 e3 20 e9 97 f9 60 81 f5 4a b2 26 b5 d3 9e 84 46 |. ...`..J.&....F| -00000050 17 03 03 00 17 de 4a e9 44 21 88 ef ce 78 35 6d |......J.D!...x5m| -00000060 b2 e4 78 47 39 8d 1f fd 9b 2d a4 47 17 03 03 00 |..xG9....-.G....| -00000070 13 98 f9 1c 9c d4 b1 42 f7 e7 a1 9b 6d b1 b1 cb |.......B....m...| -00000080 86 e3 c2 27 |...'| +00000000 14 03 03 00 01 01 17 03 03 00 45 8c 37 d5 7e 3e |..........E.7.~>| +00000010 c4 24 64 8b fa fc 8d 03 a7 92 34 35 c3 2c f2 54 |.$d.......45.,.T| +00000020 43 06 5d 8a c9 c0 e8 7d 22 d3 99 58 01 0e 44 aa |C.]....}"..X..D.| +00000030 3c 26 eb 68 45 14 cd bf 6c 61 bb 31 91 9d b4 57 |<&.hE...la.1...W| +00000040 42 79 14 8c 67 c6 65 52 15 07 c8 f3 c3 9f 23 ef |By..g.eR......#.| +00000050 17 03 03 00 17 21 51 dd 67 e4 be f8 7c 7b 84 0d |.....!Q.g...|{..| +00000060 78 3c 7f ac 50 f8 34 7b fb 38 09 d0 17 03 03 00 |x<..P.4{.8......| +00000070 13 35 1a 52 9d de 4a 74 1f 01 70 de 05 c5 c3 b9 |.5.R..Jt..p.....| +00000080 e6 de 9c 0f |....| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv13-ALPN b/libgo/go/crypto/tls/testdata/Client-TLSv13-ALPN index 0ac9b36..1d8da26 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv13-ALPN +++ b/libgo/go/crypto/tls/testdata/Client-TLSv13-ALPN @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 8f 00 05 00 05 01 00 00 00 00 00 0a 00 |................| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -18,76 +18,76 @@ 00000100 bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 |.).0.........._X| 00000110 cb 3b 74 |.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 23 c5 c4 0c 4a |....z...v..#...J| -00000010 d2 5f 0b f6 ea 21 7a d1 a0 7d 21 26 b5 a3 94 ca |._...!z..}!&....| -00000020 91 6c 13 58 60 4f 39 cc 1a f7 c0 20 00 00 00 00 |.l.X`O9.... ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 c2 91 70 7a 7a |....z...v....pzz| +00000010 d4 c9 46 7a e9 44 d1 c0 92 a6 0a 43 34 08 b2 ce |..Fz.D.....C4...| +00000020 14 99 8f 6c f7 37 fb a1 28 00 ae 20 00 00 00 00 |...l.7..(.. ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 01 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 f9 |..+.....3.$... .| -00000060 64 7e 54 8f 64 ec 3d 7c 17 f1 96 3c 44 ca cd d7 |d~T.d.=|...<D...| -00000070 3d 92 02 06 5a f8 ab dc f3 50 fe 5c ab 04 6b 14 |=...Z....P.\..k.| -00000080 03 03 00 01 01 17 03 03 00 24 9f 15 ee 1e 43 26 |.........$....C&| -00000090 31 53 01 8b a0 a7 e9 ac 96 51 a7 bc fe 46 6c 60 |1S.......Q...Fl`| -000000a0 d1 8b c4 a9 34 cd 93 13 51 50 e9 02 f9 ce 17 03 |....4...QP......| -000000b0 03 02 6d c3 ad 14 a8 d3 81 87 26 7d a0 60 57 2c |..m.......&}.`W,| -000000c0 d2 65 f5 a5 fc a8 c4 dd 2e e2 04 57 1f 94 a4 4a |.e.........W...J| -000000d0 3a 43 92 f4 f5 58 e9 11 d7 b1 62 0d d1 f4 d5 43 |:C...X....b....C| -000000e0 4a c8 fa d9 28 18 ca 74 1a b2 39 e2 9b 95 40 0e |J...(..t..9...@.| -000000f0 63 ed 11 52 9b 61 36 0c c3 a6 7b de 4d 68 48 55 |c..R.a6...{.MhHU| -00000100 e2 05 e8 59 e1 df 51 08 06 a8 09 a0 d5 e7 14 e9 |...Y..Q.........| -00000110 13 c6 a4 6d ff 7b b0 98 50 ef 81 1b 64 6f 44 c1 |...m.{..P...doD.| -00000120 cd da 85 a0 80 0c da 54 90 8e a1 7d 4b 1d 16 fc |.......T...}K...| -00000130 40 ba e3 25 e3 c2 52 29 7a 23 50 2a 43 3f 7e 32 |@..%..R)z#P*C?~2| -00000140 73 e0 5a a5 3f 09 b0 3a b8 90 8b 36 06 ac fc ef |s.Z.?..:...6....| -00000150 e8 9c ba f3 fb 8e 2d ab b3 c6 f4 d0 1d eb 7b 20 |......-.......{ | -00000160 2b 68 1f e9 25 49 c9 2a 45 6e 2b a5 00 12 54 b2 |+h..%I.*En+...T.| -00000170 a7 16 2f 00 72 d4 ed 7d ea 7e cb b1 0a 03 c6 3b |../.r..}.~.....;| -00000180 b8 fe 97 59 6a b4 07 d3 2c b1 cc ca e8 46 24 97 |...Yj...,....F$.| -00000190 d2 b8 a5 8e 7d 6f 78 7f bd ee 7d 5a f6 ec 07 50 |....}ox...}Z...P| -000001a0 00 c4 63 33 03 e5 09 44 c3 68 61 ec 5b 52 f8 67 |..c3...D.ha.[R.g| -000001b0 66 60 fd 68 fe d7 b7 df 96 2c 1b 00 93 89 24 58 |f`.h.....,....$X| -000001c0 20 2d 0a c1 c4 80 fc 03 8c 16 d1 83 11 a9 e7 70 | -.............p| -000001d0 69 3f cf c2 dc 90 40 70 1a 1e d9 8e 36 02 61 57 |i?....@p....6.aW| -000001e0 49 60 2d ba 59 76 fb 26 50 c8 db 82 b3 62 e5 d7 |I`-.Yv.&P....b..| -000001f0 fb c6 91 9b 99 6e d2 d7 e1 8a da ec 87 e9 d8 71 |.....n.........q| -00000200 3a 01 01 c9 9c da 3c 81 67 bc fb 30 0c 81 31 62 |:.....<.g..0..1b| -00000210 c2 ff 1f ee db 27 e2 07 59 51 fb e2 64 89 e5 0e |.....'..YQ..d...| -00000220 0a 37 06 07 8a 96 34 b9 53 8d 0a ed 60 02 cb f5 |.7....4.S...`...| -00000230 af b2 9c 77 27 2a 23 69 5f 58 cc 46 32 ab 76 df |...w'*#i_X.F2.v.| -00000240 1b c1 17 98 6e fb 9e 15 e0 7f e1 00 75 6d b2 cf |....n.......um..| -00000250 ce 6e dd 6c 00 b6 81 14 bb 06 60 b4 47 07 2a cf |.n.l......`.G.*.| -00000260 dc 87 72 07 7e 1d 76 fc 17 14 8a d7 5c 32 9b d2 |..r.~.v.....\2..| -00000270 c6 45 24 d5 d0 ea a4 c6 b5 6e 63 fc c7 12 0c a7 |.E$......nc.....| -00000280 0a 73 70 89 ce 3d 1f aa d5 ad ba bc 16 e8 15 80 |.sp..=..........| -00000290 14 16 84 f6 06 38 23 b7 21 ec 27 50 a8 76 cf 0c |.....8#.!.'P.v..| -000002a0 4f 58 f7 57 7f b3 bd 55 0c f4 53 6e 9f f4 f2 12 |OX.W...U..Sn....| -000002b0 5b c4 e7 68 9c 17 8b 76 88 1e 42 1b 32 e0 81 4d |[..h...v..B.2..M| -000002c0 ce 16 73 59 74 bd 56 be fd fe 42 21 07 bd f4 e9 |..sYt.V...B!....| -000002d0 ff 83 f3 97 a8 9e d4 c6 3c 6f 43 9d 0b 3c dc 35 |........<oC..<.5| -000002e0 29 e4 bd b1 75 a4 70 30 8d bd fa 25 74 6c 11 ea |)...u.p0...%tl..| -000002f0 44 38 b5 8f f9 7a 71 c6 f8 ea c7 2c 23 d2 29 6d |D8...zq....,#.)m| -00000300 dc 8f e5 f7 c6 80 3b 8d 47 da 19 da 28 26 26 e6 |......;.G...(&&.| -00000310 0f 83 d5 e9 33 42 0b 21 f4 1c 48 c0 19 ed e6 84 |....3B.!..H.....| -00000320 17 03 03 00 99 d6 56 fb 52 63 57 c0 61 ec 30 04 |......V.RcW.a.0.| -00000330 0a ee 10 39 7b e4 6a 38 8b 29 9a 6c 40 88 1d a1 |...9{.j8.).l@...| -00000340 8b 53 2b fe 47 66 75 70 5b 03 33 fc ca e6 4f 8d |.S+.Gfup[.3...O.| -00000350 f1 40 63 c2 24 97 b4 c8 dd b1 20 27 e0 28 03 7a |.@c.$..... '.(.z| -00000360 f1 cd b3 df 8a 93 39 fa b9 f9 0e 62 4c 47 24 69 |......9....bLG$i| -00000370 9a f3 a5 7b 0d 14 33 00 c3 ab ae 4a 46 c2 40 42 |...{..3....JF.@B| -00000380 d7 36 c1 74 7a c6 1a 42 d2 e0 fe e6 4b 5c 96 1a |.6.tz..B....K\..| -00000390 24 05 13 2c ad aa 25 02 ae 1b 3a 87 a7 60 1c d4 |$..,..%...:..`..| -000003a0 98 53 ee 33 e9 36 37 d0 97 c2 e9 2d b9 a0 ac 4f |.S.3.67....-...O| -000003b0 c8 82 d8 a4 28 2e e4 db a1 8f 71 cb ee 28 17 03 |....(.....q..(..| -000003c0 03 00 35 5d 41 7c b0 af b5 49 e8 dc 8a 7f c8 1f |..5]A|...I......| -000003d0 af 70 8b c4 35 7b 7b 57 3a 49 f2 ef 75 4c 27 39 |.p..5{{W:I..uL'9| -000003e0 bf a6 45 fd 9c 64 b2 6e 7c c0 d3 c0 c7 a6 25 2f |..E..d.n|.....%/| -000003f0 f7 48 6d 7c a4 33 ad 61 |.Hm|.3.a| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 60 |..+.....3.$... `| +00000060 96 62 c2 30 4e ae b6 89 f2 06 e0 4e 8e 32 27 04 |.b.0N......N.2'.| +00000070 b5 74 80 d8 c3 f5 76 7d 0e 0e e1 8d bc 2c 2c 14 |.t....v}.....,,.| +00000080 03 03 00 01 01 17 03 03 00 24 45 c7 50 3e a9 63 |.........$E.P>.c| +00000090 24 0b e9 80 3f 59 bb be 23 8a 5d 46 eb ee 17 9c |$...?Y..#.]F....| +000000a0 70 6f 52 1f 18 f3 9f 72 d6 35 44 55 91 d2 17 03 |poR....r.5DU....| +000000b0 03 02 6d c2 c0 1f 53 2a 0c 3c 7f 08 c3 cb 53 4e |..m...S*.<....SN| +000000c0 b2 f5 b3 2d a5 10 e1 97 00 89 67 db 4e df ad 75 |...-......g.N..u| +000000d0 94 b4 56 c4 8a a3 49 41 43 a1 3f aa 9b 8e e1 8d |..V...IAC.?.....| +000000e0 4c 9c 36 f6 80 da 4e 7f 00 10 c0 81 3e 45 1b a0 |L.6...N.....>E..| +000000f0 b7 7f 2c bd eb 2a 8b c4 e6 fa c8 b3 59 28 f6 b8 |..,..*......Y(..| +00000100 0a 93 cb b3 bf 28 e7 1a ae a0 f5 ff 3a 42 f5 64 |.....(......:B.d| +00000110 92 2c dd c2 24 77 2f a6 7e 23 63 3f 24 16 b3 d5 |.,..$w/.~#c?$...| +00000120 b7 df 3f 30 23 a4 aa c9 14 78 6c f2 82 45 52 df |..?0#....xl..ER.| +00000130 cf a1 1d 35 fd 2a 30 89 14 38 5a 23 b1 63 2c c1 |...5.*0..8Z#.c,.| +00000140 6d 6b 07 d0 41 38 4f 4c 87 d3 bd f1 ec ed 29 52 |mk..A8OL......)R| +00000150 3d c7 74 3d e9 d3 ce 47 1c 24 d5 78 19 c9 5e 01 |=.t=...G.$.x..^.| +00000160 66 a0 f1 8f ea a6 c1 e4 b4 e0 c2 2e d7 d6 64 36 |f.............d6| +00000170 c9 bc d1 27 33 6f 26 a8 c6 aa 0d bc ae f9 2e bc |...'3o&.........| +00000180 f1 a7 82 42 09 83 62 88 c0 9f 20 95 a9 38 50 b4 |...B..b... ..8P.| +00000190 55 d6 e9 f4 c6 a1 e6 67 a9 5f e4 15 97 44 13 ef |U......g._...D..| +000001a0 d3 50 8b 61 38 5e 89 75 b1 cf 6a 6f 0c c5 26 13 |.P.a8^.u..jo..&.| +000001b0 2c 5a 26 c9 81 98 88 cd ec 8c 2c 99 a0 ff 55 8f |,Z&.......,...U.| +000001c0 3f 9b c3 3b 52 d0 a3 3a f9 b8 f0 17 81 53 00 f3 |?..;R..:.....S..| +000001d0 ef 72 b3 4e b9 65 28 8f a2 48 dc dd 6b 16 61 c3 |.r.N.e(..H..k.a.| +000001e0 4e 0e c0 1c ac 8c 40 28 27 63 66 c7 74 40 8d 93 |N.....@('cf.t@..| +000001f0 71 e9 f6 3f d8 8d 5d c6 28 11 4f ac 55 6f 80 1b |q..?..].(.O.Uo..| +00000200 2e 84 05 94 e0 4f e7 63 62 65 c7 52 99 49 2f 5d |.....O.cbe.R.I/]| +00000210 b4 99 d3 c3 fa b9 f5 83 aa 28 2e 9d ce af 72 7f |.........(....r.| +00000220 57 ea 81 f3 bf b5 d7 93 3a 1f a0 83 4d 8a 91 85 |W.......:...M...| +00000230 fe b7 a1 b3 cb 1d b1 85 9b bb 36 1b 12 9f ed 13 |..........6.....| +00000240 09 55 31 bd ee 61 06 57 b4 07 4d c6 1e fa b9 7f |.U1..a.W..M.....| +00000250 c7 b6 60 70 92 b7 9a ff 80 7d da 7f 2a 62 89 be |..`p.....}..*b..| +00000260 79 43 d3 ae 9c f1 00 6d 68 6c a3 f6 48 6e e0 48 |yC.....mhl..Hn.H| +00000270 97 0f 5c 44 43 9f a8 88 27 96 fc 53 a0 e1 f2 7a |..\DC...'..S...z| +00000280 a6 a7 d9 96 2e 3d c4 e0 d9 18 79 ec 83 c2 9b da |.....=....y.....| +00000290 0b d4 8b 87 c5 98 f5 8b e7 e3 d1 bd 2b 2b 42 e2 |............++B.| +000002a0 4b 3e 64 88 4b 72 d0 35 cc c3 e6 68 c6 f6 4f 23 |K>d.Kr.5...h..O#| +000002b0 39 a7 94 8d f3 e6 bd cd d5 e9 8c 53 83 a7 87 09 |9..........S....| +000002c0 15 fe ea eb 2e 56 da 6b d9 5b b7 b1 c5 c4 ba 65 |.....V.k.[.....e| +000002d0 39 89 16 f5 f6 4e e6 3a 63 34 1b 5d f5 fa 6b 8d |9....N.:c4.]..k.| +000002e0 c3 49 07 88 12 ca 18 c5 50 da 74 44 c0 c0 33 bd |.I......P.tD..3.| +000002f0 2e 45 94 af e1 40 90 00 11 2d 08 7b fc e4 3b f0 |.E...@...-.{..;.| +00000300 94 fd 5a 0c 3a f9 76 df 3b 5e a3 0d 0f e7 2d df |..Z.:.v.;^....-.| +00000310 fd e9 ce 45 5a 13 36 a6 18 ae 46 30 00 fc d5 e3 |...EZ.6...F0....| +00000320 17 03 03 00 99 0e 35 b6 91 ad cd a6 62 6e 79 12 |......5.....bny.| +00000330 53 d5 f0 78 72 c5 dd 94 00 e3 75 2c 11 a3 72 f6 |S..xr.....u,..r.| +00000340 b7 b3 5e d9 51 79 d5 a9 1e 21 2f df 0d 53 9a c8 |..^.Qy...!/..S..| +00000350 43 a9 58 e2 a9 3d 9a b4 b4 72 bb 62 65 4b 83 f8 |C.X..=...r.beK..| +00000360 cd 1b 58 e0 69 d9 87 3b 8d 05 42 e1 22 23 e9 5b |..X.i..;..B."#.[| +00000370 3a 5a 38 17 17 fb 3a 56 de fc 56 f8 77 12 31 4a |:Z8...:V..V.w.1J| +00000380 c5 38 ec 69 72 54 e5 63 2a a0 1e b4 7d 86 43 29 |.8.irT.c*...}.C)| +00000390 21 ba 56 c2 d9 1b 9f a4 c1 02 f3 83 c1 9a 56 69 |!.V...........Vi| +000003a0 5c 9e 5f ae 94 9d 6f 03 ec 75 7a 19 98 cd a9 dd |\._...o..uz.....| +000003b0 4a 01 41 72 2e 60 9f ca 4c d2 27 d9 0f 4f 17 03 |J.Ar.`..L.'..O..| +000003c0 03 00 35 5d 61 3c 07 70 2f 35 ba d0 93 44 16 bd |..5]a<.p/5...D..| +000003d0 73 4b a0 fb 05 52 6a cc 5a 2e f2 94 d6 77 98 03 |sK...Rj.Z....w..| +000003e0 c3 2e 8e a9 d1 38 14 d2 cd e6 e3 b6 ad ec d6 a0 |.....8..........| +000003f0 cf b0 58 5f 8f d3 43 4b |..X_..CK| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 3e e7 50 e1 d1 |..........5>.P..| -00000010 4d 9f 84 fe ca 83 c4 3b a6 86 45 c2 7e e7 af 00 |M......;..E.~...| -00000020 db e6 23 3c 06 b8 a3 1e 36 2e ab 45 7e d8 07 8c |..#<....6..E~...| -00000030 66 bf 5a 0f ff e6 3f 09 a4 d3 cf 74 1c d6 cf c7 |f.Z...?....t....| -00000040 17 03 03 00 17 4c db af a7 f3 73 b3 84 b9 a7 d1 |.....L....s.....| -00000050 1c 2f cb 27 d8 ba 2c c6 84 48 88 18 17 03 03 00 |./.'..,..H......| -00000060 13 a3 41 6f fb da f5 5a 4d 85 0c e0 ff 3a fb 91 |..Ao...ZM....:..| -00000070 e2 5e ab 96 |.^..| +00000000 14 03 03 00 01 01 17 03 03 00 35 3d 0a fd 33 39 |..........5=..39| +00000010 b6 94 43 53 ae ee 3f 4e c6 2d a2 3a f0 ef 94 7d |..CS..?N.-.:...}| +00000020 32 0a b6 90 cd a1 6f 29 88 ff 3c 91 c1 e5 e5 ae |2.....o)..<.....| +00000030 b7 a0 0b b3 c0 e6 37 9d 06 8b d8 ae 06 c0 0e 7b |......7........{| +00000040 17 03 03 00 17 c2 a1 82 db df fa 54 28 79 a0 0c |...........T(y..| +00000050 97 8c 82 ee 22 c9 b9 35 32 7a 21 4b 17 03 03 00 |...."..52z!K....| +00000060 13 87 2b f8 38 81 df fa e5 2e ff e2 d2 51 3e bc |..+.8........Q>.| +00000070 dd d3 e8 62 |...b| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv13-CHACHA20-SHA256 b/libgo/go/crypto/tls/testdata/Client-TLSv13-CHACHA20-SHA256 index 6d7b508..69749f0 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv13-CHACHA20-SHA256 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv13-CHACHA20-SHA256 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,75 +16,75 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 43 b1 e8 d9 c3 |....z...v..C....| -00000010 22 a0 a3 08 df 7f 37 34 7a fe 7a 47 98 ee ed 51 |".....74z.zG...Q| -00000020 c2 ae 5c c6 b1 43 3d ff f7 91 68 20 00 00 00 00 |..\..C=...h ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 39 b2 74 80 d8 |....z...v..9.t..| +00000010 49 72 79 63 9b 7b da d7 cf b4 29 20 f8 80 ed d9 |Iryc.{....) ....| +00000020 66 09 65 22 b6 27 16 c5 a7 6f 8b 20 00 00 00 00 |f.e".'...o. ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 63 |..+.....3.$... c| -00000060 0f 66 ec 2d fa 67 d4 eb 94 47 8d 88 0b eb ed ec |.f.-.g...G......| -00000070 5b ac 22 f7 46 85 c5 1c 2b 5e e8 57 e2 d3 6f 14 |[.".F...+^.W..o.| -00000080 03 03 00 01 01 17 03 03 00 17 d0 f8 1f 06 59 8d |..............Y.| -00000090 a0 40 21 8f 3e 36 3b 1d 6a 6e f7 77 44 fb b3 8e |.@!.>6;.jn.wD...| -000000a0 e2 17 03 03 02 6d 22 6b 63 ae 47 fd 66 f9 95 f6 |.....m"kc.G.f...| -000000b0 63 ea e8 16 61 a3 64 82 39 82 76 1c 2c 04 9b 29 |c...a.d.9.v.,..)| -000000c0 0f 8a ff 77 9b e6 2c ce 04 09 5f 91 f3 b6 2e 8d |...w..,..._.....| -000000d0 be 42 94 7e 5a 28 4b 9f e9 7b 38 0a 3c de 90 77 |.B.~Z(K..{8.<..w| -000000e0 c1 bf 97 bf 35 6c 77 98 4b 38 b4 8d 7f 1f 4b c0 |....5lw.K8....K.| -000000f0 23 c5 73 08 90 fa 21 5c cd cb 84 5b 0e 89 86 ce |#.s...!\...[....| -00000100 83 78 d5 1c 2b b9 b1 24 45 ad ab 9c 68 9f c2 28 |.x..+..$E...h..(| -00000110 40 d6 c2 ac a2 0c 86 cd 75 92 43 d5 22 3f 61 9d |@.......u.C."?a.| -00000120 e8 56 b8 7c 71 db 25 cc 2e 74 52 74 da 6b d4 a1 |.V.|q.%..tRt.k..| -00000130 2c 32 d2 d8 9c 74 41 9d 78 98 94 3b 87 99 8e 17 |,2...tA.x..;....| -00000140 df df d6 c3 6d ef 58 13 5c 1e 20 2d ed 77 bd 5c |....m.X.\. -.w.\| -00000150 d6 5c 9a 6d 0f 19 77 e1 4f 79 b0 ed 9d 0b f5 e8 |.\.m..w.Oy......| -00000160 42 d0 f4 90 88 97 a9 84 af 92 3c 41 fe fd 67 6e |B.........<A..gn| -00000170 33 77 8e 02 83 b4 6f c0 14 d2 ee 38 79 ca 45 61 |3w....o....8y.Ea| -00000180 59 05 3b 76 4b ef 55 b9 18 43 9f c4 42 02 31 8e |Y.;vK.U..C..B.1.| -00000190 88 c1 b6 0b 5d c4 20 59 91 57 f3 81 b9 d0 ec 25 |....]. Y.W.....%| -000001a0 26 72 37 e0 e0 c8 34 83 58 fe 15 bd aa 4d 49 f8 |&r7...4.X....MI.| -000001b0 ba 8f 1d 8d 37 9c 18 88 cd 69 23 00 93 0f 64 e0 |....7....i#...d.| -000001c0 ed 0d a7 a0 fc bd f3 7d 0b b0 50 6b cd e6 25 b8 |.......}..Pk..%.| -000001d0 50 3a bf 37 d7 18 60 a7 de ba c7 ff b7 26 8a 20 |P:.7..`......&. | -000001e0 ad d3 f9 5a 5f 61 37 2f b0 9b d6 2a 4c 39 08 34 |...Z_a7/...*L9.4| -000001f0 31 15 19 1e 72 d3 fc 72 63 0e d5 71 04 82 b3 80 |1...r..rc..q....| -00000200 ec aa 51 0f 73 5f 2c dd 42 fd 40 b8 e3 1d 9e 31 |..Q.s_,.B.@....1| -00000210 13 01 3b 6b 88 f2 52 17 fa 0b 9d 45 1e f2 f0 c1 |..;k..R....E....| -00000220 5b 3f 14 23 41 e7 a2 2e fa e4 9b 01 9b a4 99 43 |[?.#A..........C| -00000230 32 85 fc c9 30 2a 5d ca 2a fa c5 7f 81 89 31 02 |2...0*].*.....1.| -00000240 0a c6 89 f0 98 1b 92 08 96 d0 90 c7 18 b0 d4 e9 |................| -00000250 5d 29 71 3b c6 2f c5 ff 2c be db f8 ef 56 d6 e0 |])q;./..,....V..| -00000260 9b a6 21 b1 92 b1 58 26 e9 e2 3b 97 1b 95 b2 ba |..!...X&..;.....| -00000270 62 66 a5 df a1 a8 82 25 1e ae 85 98 94 d7 96 c5 |bf.....%........| -00000280 3b 30 4c bd 04 23 45 3d 86 c9 7e 0e 47 5b 5f 14 |;0L..#E=..~.G[_.| -00000290 b5 c5 29 31 1e cd a4 e0 6a b2 78 51 f0 7b b2 21 |..)1....j.xQ.{.!| -000002a0 1f 10 0d 0d 7f 01 f1 06 4a 87 7d 4a 90 63 59 f3 |........J.}J.cY.| -000002b0 6d 16 0f 07 9e 00 3a d2 c7 01 37 cc 39 6e 07 6e |m.....:...7.9n.n| -000002c0 9e 64 df 47 65 04 4c 72 59 ad 3b 3e 52 8e e4 b6 |.d.Ge.LrY.;>R...| -000002d0 fc ba 9c f0 82 13 ba 25 11 c7 5d 38 00 cf 83 14 |.......%..]8....| -000002e0 30 a9 72 48 d1 e8 4e 1b ed 04 ed cf b7 5b 2e 72 |0.rH..N......[.r| -000002f0 1c a2 03 ae 60 54 d6 cf 2f fb 11 a3 b1 8d d6 47 |....`T../......G| -00000300 e8 9f 96 08 90 ae 3c 3c c0 8c d8 c4 ef 30 18 ea |......<<.....0..| -00000310 2a 1a 15 17 03 03 00 99 85 b3 e4 18 6f 8d 34 c7 |*...........o.4.| -00000320 3d 66 49 b8 f6 f5 aa 7a e1 ca ba cb 48 53 15 bb |=fI....z....HS..| -00000330 e9 ec 74 91 c3 b5 d3 6b bc 84 81 d8 e1 a4 31 62 |..t....k......1b| -00000340 d5 19 6d 2f 15 4c f3 8a 3b ec 41 12 89 be d3 cc |..m/.L..;.A.....| -00000350 ab 08 59 a7 79 5d 77 14 ce b1 98 b4 ce 71 7b ad |..Y.y]w......q{.| -00000360 ba 41 3a 7f 9a f8 23 5c c6 fb b5 7b cc eb 0e 7a |.A:...#\...{...z| -00000370 ee af 3d ff 4d 03 ba c2 2a af ac fd b5 e8 5b 43 |..=.M...*.....[C| -00000380 3e 37 ef 84 3d 66 af 3c 8e 1d 0d 36 bd df 25 dc |>7..=f.<...6..%.| -00000390 74 89 9c e6 da 18 c4 c8 b5 6c 3c 4c a6 ac 10 28 |t........l<L...(| -000003a0 67 c0 a7 02 6c d4 8c a1 ca 66 ec 30 65 a6 af f7 |g...l....f.0e...| -000003b0 e3 17 03 03 00 35 46 33 9b 78 59 93 b5 3d 99 22 |.....5F3.xY..=."| -000003c0 56 3b 26 82 9c d4 08 36 5a 07 c6 d7 5b 4f c8 d9 |V;&....6Z...[O..| -000003d0 32 8b cd f1 e7 81 58 a8 98 b6 61 f6 9e 75 0c 52 |2.....X...a..u.R| -000003e0 5a a1 e8 b1 97 8c 94 52 82 5e e8 |Z......R.^.| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 42 |..+.....3.$... B| +00000060 80 fb 4a d3 49 53 a5 9f f6 da ca 64 f8 5d 2c f5 |..J.IS.....d.],.| +00000070 45 4d f1 a5 ec c3 c6 fc d2 ff 56 b1 63 53 1a 14 |EM........V.cS..| +00000080 03 03 00 01 01 17 03 03 00 17 f8 d8 e1 1a e0 c8 |................| +00000090 75 f9 40 90 da 16 a0 41 4f 8c 23 e7 47 43 89 cf |u.@....AO.#.GC..| +000000a0 d4 17 03 03 02 6d d6 23 1d c6 c0 d4 5e a3 fe 2b |.....m.#....^..+| +000000b0 03 04 6c 88 d1 4a ac 9b dd 90 e5 18 c5 35 9c 4a |..l..J.......5.J| +000000c0 f3 c4 64 e2 c2 40 62 fb 68 b3 22 37 9f f4 eb ae |..d..@b.h."7....| +000000d0 45 d9 a8 be f4 1e 89 16 88 b5 10 e3 5c 2e 42 15 |E...........\.B.| +000000e0 34 24 f3 bd dd 73 6d 6b d1 db 3e 69 b0 0a 54 e6 |4$...smk..>i..T.| +000000f0 b7 2c b7 80 86 93 91 d5 26 02 77 bf 10 38 ee 40 |.,......&.w..8.@| +00000100 22 4d 3f 67 02 6b f8 1c 4a ad 2b c7 f6 19 d4 36 |"M?g.k..J.+....6| +00000110 9b ff c4 08 73 e1 48 0a a6 e8 80 3b 88 8a c2 e8 |....s.H....;....| +00000120 c6 4a ae da a1 4f 3b 9e fb 80 3b 78 ca 80 42 00 |.J...O;...;x..B.| +00000130 a4 5c 9d a0 6c 63 a7 66 e6 26 b7 14 d8 8b ba 1a |.\..lc.f.&......| +00000140 4b 13 81 3c e4 76 4e ac 6c 2f b4 71 e9 dc c4 c8 |K..<.vN.l/.q....| +00000150 ef f0 61 22 f4 6b 83 ae d8 d0 a7 c6 d9 ea 95 85 |..a".k..........| +00000160 77 90 0f 22 a0 50 cb ff 50 a5 98 ee de e4 89 f3 |w..".P..P.......| +00000170 20 f2 63 a2 45 3a 48 33 d5 b9 ff 5e f8 7d c5 2d | .c.E:H3...^.}.-| +00000180 b9 9c b2 65 bf d5 13 36 46 a5 96 9f f4 de 7c 1c |...e...6F.....|.| +00000190 78 3f 1a 0a 62 14 13 8e 55 7e cd 47 87 1b 7e a8 |x?..b...U~.G..~.| +000001a0 7f 03 ec 1c d3 72 eb e5 94 d9 9d 95 d6 f5 ad 2c |.....r.........,| +000001b0 e9 7d 0f 2c ea 7b 1e 8e d7 b4 f1 5d 12 be d7 cf |.}.,.{.....]....| +000001c0 b7 43 89 65 e9 04 0e f8 b4 b4 4d 9c 9c 42 3c 50 |.C.e......M..B<P| +000001d0 a7 91 d0 7f c0 de fb 99 08 ce 5c fd 67 3a cb 1a |..........\.g:..| +000001e0 d3 1a 4c a2 2e 7d 73 01 2b 5f bb a2 86 7d 0e e0 |..L..}s.+_...}..| +000001f0 a1 c9 06 c0 4a 0a f6 c6 c4 b5 53 51 3e 2f f4 60 |....J.....SQ>/.`| +00000200 1d 41 55 9d c4 88 f3 76 4f 92 b5 03 98 23 6b c4 |.AU....vO....#k.| +00000210 c3 62 bd 12 dd 3a bc 37 d0 18 64 c6 e1 2c cb 62 |.b...:.7..d..,.b| +00000220 f6 d3 24 35 47 e7 cf 15 d3 53 9d ac 3f 97 48 c1 |..$5G....S..?.H.| +00000230 b8 d3 a3 2c 9f cd 2b 72 bc bd a6 8a b1 54 48 7b |...,..+r.....TH{| +00000240 e0 b7 a2 2e 46 04 cc e5 29 1d 73 c7 67 f8 f0 d8 |....F...).s.g...| +00000250 e0 88 f0 7b 11 ff e1 1d 95 6c 85 c4 08 72 3e 94 |...{.....l...r>.| +00000260 92 4b 8a 58 62 04 10 83 7c 5e 65 20 a7 5d 6d 16 |.K.Xb...|^e .]m.| +00000270 30 64 fc aa 7f 8f 06 ed 4e 3c 86 c8 10 92 fb 0d |0d......N<......| +00000280 7b 81 10 07 cf 30 7f 6b 11 63 60 2a 61 92 cb 74 |{....0.k.c`*a..t| +00000290 82 a4 04 cf 23 43 21 55 45 2a 29 93 42 0f 0c f6 |....#C!UE*).B...| +000002a0 9b 14 b5 96 09 25 1b bc b0 7b 72 e2 6f b8 55 74 |.....%...{r.o.Ut| +000002b0 00 bb 1c 7c b1 9b 58 63 97 bb 6d c5 fb a4 da 24 |...|..Xc..m....$| +000002c0 1e b2 97 18 75 ab 8b a2 77 50 38 4d f8 a0 39 58 |....u...wP8M..9X| +000002d0 8c 2d 3e ba 27 03 e9 51 87 0a 95 e0 08 40 5d e6 |.->.'..Q.....@].| +000002e0 6a dd 10 1d 6d 8c 32 88 a8 32 ee dd 44 9c 9b b0 |j...m.2..2..D...| +000002f0 6f f5 4b 08 60 9d 83 1e ab 83 c0 92 10 c7 aa 90 |o.K.`...........| +00000300 d2 b2 61 5e 12 b5 e8 ea a7 68 59 17 a4 f4 15 f7 |..a^.....hY.....| +00000310 dc 10 81 17 03 03 00 99 8a 61 79 8f 33 51 7b a9 |.........ay.3Q{.| +00000320 ce 3f 82 2b bb da 40 2e 73 c8 d9 6e 7d 72 ba 94 |.?.+..@.s..n}r..| +00000330 7d ad fb b7 ba 9c 74 00 0b c9 1d b6 8d 54 b9 48 |}.....t......T.H| +00000340 eb 49 78 c3 1a 75 b8 16 22 5d 50 f5 4a 81 59 d3 |.Ix..u.."]P.J.Y.| +00000350 38 79 38 c1 35 11 55 69 6b d2 86 3c 0f 12 26 57 |8y8.5.Uik..<..&W| +00000360 f5 84 d7 dd 74 61 6f b8 08 66 e9 3c f7 43 29 a5 |....tao..f.<.C).| +00000370 94 9e ab af 68 04 c1 6a ae 9d 12 2d 57 e9 ff 30 |....h..j...-W..0| +00000380 7d 80 35 65 cc df c8 65 0b a1 f9 6d 6b a5 0b df |}.5e...e...mk...| +00000390 0c 1a 04 0a 00 8f ac 2b 29 60 92 4e 91 d3 42 25 |.......+)`.N..B%| +000003a0 b4 a5 0a 1a 5f 83 ec 9a f0 0a 2c 6d 65 00 24 d3 |...._.....,me.$.| +000003b0 e1 17 03 03 00 35 e4 72 aa 9e 6c a8 93 7b e4 49 |.....5.r..l..{.I| +000003c0 1e 23 7c 50 18 59 00 08 3b f1 c1 5f 20 ba 51 56 |.#|P.Y..;.._ .QV| +000003d0 fe bb 93 99 52 e6 5e 6d 26 cc 60 11 c2 a1 c8 18 |....R.^m&.`.....| +000003e0 2e 72 bd ee 36 ca 41 25 73 f2 30 |.r..6.A%s.0| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 55 88 37 f3 ee |..........5U.7..| -00000010 c5 1b 20 ac fe bc a3 f8 c9 59 3f 5f c0 81 40 8f |.. ......Y?_..@.| -00000020 1e a9 44 c8 10 16 69 8a 76 45 17 51 06 9e f0 55 |..D...i.vE.Q...U| -00000030 a2 f2 56 98 7d a1 4d 95 5a c3 1f 51 cf 31 20 ca |..V.}.M.Z..Q.1 .| -00000040 17 03 03 00 17 81 2a 8e 32 29 ec 9b 92 c3 fd 98 |......*.2)......| -00000050 64 aa 47 2a a5 0c d6 77 7f b1 8f 12 17 03 03 00 |d.G*...w........| -00000060 13 60 8c fb 98 e1 03 b6 20 c8 45 4e d9 4b a8 17 |.`...... .EN.K..| -00000070 10 79 5f b6 |.y_.| +00000000 14 03 03 00 01 01 17 03 03 00 35 b6 c3 b9 b1 52 |..........5....R| +00000010 88 d2 78 2b ec 1c 63 e8 d5 08 0e 4e d6 51 b9 02 |..x+..c....N.Q..| +00000020 ba cc a8 ca b6 da 45 a9 7c 1a 18 39 47 84 db 34 |......E.|..9G..4| +00000030 d6 05 6f e5 16 19 57 6f 65 0b 7a e7 37 b5 d3 28 |..o...Woe.z.7..(| +00000040 17 03 03 00 17 dc b8 e2 1c aa b8 f5 cb b6 fd ba |................| +00000050 29 34 73 bb c6 e0 3a fc 3e fb d3 01 17 03 03 00 |)4s...:.>.......| +00000060 13 eb 66 ab 47 38 1b 01 96 6c 59 46 c2 ad bf 2d |..f.G8...lYF...-| +00000070 36 22 97 19 |6"..| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-ECDSA-RSA b/libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-ECDSA-RSA index c8e95c8..251e339 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-ECDSA-RSA +++ b/libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-ECDSA-RSA @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,124 +16,124 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 98 9a 92 3f c6 |....z...v.....?.| -00000010 67 f5 96 5b 2f 5e 70 89 2d f6 1e ce 6f 6a e5 91 |g..[/^p.-...oj..| -00000020 4b 4b 6f 98 cc f7 78 4a b1 54 4a 20 00 00 00 00 |KKo...xJ.TJ ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 ce 38 98 c9 b7 |....z...v...8...| +00000010 f8 67 af 0d 29 52 88 a4 d0 c2 a8 10 c4 8e 80 26 |.g..)R.........&| +00000020 43 84 0e 60 06 ce f0 b7 b1 cd 29 20 00 00 00 00 |C..`......) ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 01 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 58 |..+.....3.$... X| -00000060 96 37 c3 41 35 73 13 21 fc 31 e3 09 33 48 15 be |.7.A5s.!.1..3H..| -00000070 31 fb 57 61 b2 c9 60 31 2d 68 83 d5 7c d1 3a 14 |1.Wa..`1-h..|.:.| -00000080 03 03 00 01 01 17 03 03 00 17 1d ce 7d b7 ca e3 |............}...| -00000090 10 82 cb f6 1d 52 61 41 29 57 e3 7e e5 88 5c 47 |.....RaA)W.~..\G| -000000a0 16 17 03 03 00 42 1b 49 e1 4a d7 73 57 cd e9 b7 |.....B.I.J.sW...| -000000b0 e2 47 d3 74 21 6a 14 1d 1b 8d f5 aa 4c 1b f8 61 |.G.t!j......L..a| -000000c0 8c 3a e4 2e 9d ff 3f 7d b2 4d 79 6e 1d 02 05 ce |.:....?}.Myn....| -000000d0 c3 ad e6 f9 2b 2b dd 75 3b 6f 3e 0b 29 07 09 74 |....++.u;o>.)..t| -000000e0 d1 37 68 9b 8a b6 8d 2b 17 03 03 02 6d d1 1b 9f |.7h....+....m...| -000000f0 75 ba cf 2d 10 4b f0 4e 09 58 fa ff 06 e8 c9 d5 |u..-.K.N.X......| -00000100 a0 51 c8 d4 6f b2 c5 c1 d5 f3 ff 12 1f 43 d8 74 |.Q..o........C.t| -00000110 33 d9 9b e5 f3 34 26 0e 89 dc 00 54 67 17 d2 f3 |3....4&....Tg...| -00000120 c9 9e be f8 4c 77 8a 63 b1 64 5a b4 d7 57 d2 89 |....Lw.c.dZ..W..| -00000130 ce 68 d1 f7 93 01 6c 36 b7 c9 4d 50 d0 4b df 5e |.h....l6..MP.K.^| -00000140 8a bb 6c d9 54 57 9b b9 c9 ec d8 49 c7 51 3c e5 |..l.TW.....I.Q<.| -00000150 7b fb 48 0f fd 1b dd 0f 57 d3 a8 ee f6 51 ba 78 |{.H.....W....Q.x| -00000160 c0 60 f1 d9 c1 d2 65 b4 a7 98 99 fb 64 83 4c 2c |.`....e.....d.L,| -00000170 a6 e9 19 ef 0e 88 68 f8 21 a4 2b bd 95 e9 52 d5 |......h.!.+...R.| -00000180 fb 12 d3 36 06 a2 13 f9 e2 35 6a 06 dd 49 d9 42 |...6.....5j..I.B| -00000190 89 d9 f0 24 5c 36 b8 6d 95 35 21 b3 9c 3b ee 08 |...$\6.m.5!..;..| -000001a0 06 06 4d aa 74 eb fc 1b c1 fd cf 07 24 74 44 2d |..M.t.......$tD-| -000001b0 54 d5 c5 d3 4e c4 eb 09 6e 90 8f 3d c0 c5 1c 21 |T...N...n..=...!| -000001c0 7c 32 1b bc 4b 85 2b f0 b0 f5 cd 61 3d dd 31 03 ||2..K.+....a=.1.| -000001d0 5e e0 5e 06 1a 37 61 1a 58 fa ed e8 cf 0c 4f da |^.^..7a.X.....O.| -000001e0 73 69 42 3a f4 ed dc ad e5 e7 9b fd 54 16 77 85 |siB:........T.w.| -000001f0 ae 84 41 10 be 84 ad 28 ef e6 13 2a e9 9f 9f 2f |..A....(...*.../| -00000200 c5 d0 65 c6 f5 58 b3 39 9b 5e 07 ba 95 be 5e 75 |..e..X.9.^....^u| -00000210 68 17 ba 9d 2a 69 6d b8 ed d4 4b 6a ce 30 b1 82 |h...*im...Kj.0..| -00000220 ae ec 68 9a 26 13 6b 05 38 0f 38 c9 94 01 d0 0b |..h.&.k.8.8.....| -00000230 7b bb ca 70 86 6c e4 f1 eb 81 05 25 33 c0 3e e3 |{..p.l.....%3.>.| -00000240 2a 25 8e 32 eb d5 03 c7 c4 d8 22 22 ef 99 5a a3 |*%.2......""..Z.| -00000250 01 6a b5 65 9a 55 6e fb 84 83 aa 43 ae 4a 3e da |.j.e.Un....C.J>.| -00000260 40 7e 09 e1 3b 15 ad 33 66 5a 3d 30 62 72 86 54 |@~..;..3fZ=0br.T| -00000270 cd a2 6a bf 82 61 17 87 84 c5 3f f3 1e 86 a2 b1 |..j..a....?.....| -00000280 2c 1a f9 ba 8c a2 21 5b 93 b2 16 b4 81 ae 7d 98 |,.....![......}.| -00000290 d6 db 0a 56 14 c9 f7 48 c1 c7 3c 7e 63 8e bc 50 |...V...H..<~c..P| -000002a0 6a 64 e1 1d 04 ba d3 cc 6a 61 60 4b d2 97 d5 ba |jd......ja`K....| -000002b0 23 1a 69 76 86 db 96 39 04 f6 ec e9 96 79 6a 25 |#.iv...9.....yj%| -000002c0 ff 39 dd 19 08 34 4d c3 f6 7c 91 f2 6b 3a e1 0f |.9...4M..|..k:..| -000002d0 66 6d 14 5d 82 21 0b e3 e0 c3 f1 a1 70 e1 2c bc |fm.].!......p.,.| -000002e0 fb 54 aa 85 3c a0 7c 9a 35 00 e2 a1 4f 83 3e f1 |.T..<.|.5...O.>.| -000002f0 64 83 ab c5 e6 31 c7 00 eb 36 f1 bc 41 f3 eb d4 |d....1...6..A...| -00000300 97 30 4d 7f d2 d1 e7 1a 9e a2 53 31 35 6a 16 d1 |.0M.......S15j..| -00000310 65 be d7 d3 93 2a be d2 27 dc 1b 8c 09 16 30 d4 |e....*..'.....0.| -00000320 cb eb e0 bb 42 50 ff 59 c3 81 81 36 88 09 c2 23 |....BP.Y...6...#| -00000330 dc dd 80 63 bb 78 19 6b 6a 70 4b b5 17 bf ed 6c |...c.x.kjpK....l| -00000340 58 f1 15 a9 16 66 c8 45 f5 5f 99 05 b1 3b be e6 |X....f.E._...;..| -00000350 66 d7 45 df 19 16 9d c7 dd 4d 17 03 03 00 99 38 |f.E......M.....8| -00000360 70 9e 16 94 07 67 7c ce 90 67 99 46 5e d9 61 b5 |p....g|..g.F^.a.| -00000370 9b b8 31 fc cc 80 a3 07 30 c9 f5 f9 90 fb e2 0d |..1.....0.......| -00000380 dc 93 ab de 38 25 83 f8 77 0c 94 53 75 68 c7 71 |....8%..w..Suh.q| -00000390 72 6f 61 77 a7 d7 c7 ed 5c d3 08 18 9f 64 f4 6e |roaw....\....d.n| -000003a0 30 dc 05 b1 65 11 79 08 66 34 8c 06 99 a9 00 26 |0...e.y.f4.....&| -000003b0 86 2c e4 b5 6d cf db b1 03 f0 d0 c5 c0 f5 50 04 |.,..m.........P.| -000003c0 f7 27 97 3e 31 19 aa a8 58 c4 78 43 a9 e3 76 0d |.'.>1...X.xC..v.| -000003d0 98 88 20 07 11 4c d6 8a 66 31 72 2e ed 47 66 71 |.. ..L..f1r..Gfq| -000003e0 9a 3e 9c 0d 1c 17 df ab 6a 52 b4 43 a6 c2 64 30 |.>......jR.C..d0| -000003f0 45 08 b8 de 59 be 3a f9 17 03 03 00 35 94 9b 02 |E...Y.:.....5...| -00000400 47 a6 e3 55 9f 95 8a 8d 35 3b bb 56 ec 10 ab dd |G..U....5;.V....| -00000410 a3 ca fe ad bf 25 90 76 c4 15 a0 c0 73 d5 96 96 |.....%.v....s...| -00000420 44 bc ba e9 09 f5 8e e7 e7 7d db f2 e7 9f 99 d2 |D........}......| -00000430 dc e7 |..| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 aa |..+.....3.$... .| +00000060 00 03 6d 16 04 54 48 55 4d f9 04 e8 29 ca 9c 5d |..m..THUM...)..]| +00000070 14 94 a2 7a 2e 0a 4e 75 12 2d 63 cf 19 81 21 14 |...z..Nu.-c...!.| +00000080 03 03 00 01 01 17 03 03 00 17 7b 90 e1 af 77 ca |..........{...w.| +00000090 a1 3b a6 e0 9f ea 4b f6 3f 45 a0 78 1c fb af 51 |.;....K.?E.x...Q| +000000a0 30 17 03 03 00 42 ff 27 8b 9c fd 65 d7 b1 d4 43 |0....B.'...e...C| +000000b0 eb 8f c3 ca b4 57 be 35 35 75 35 cf 43 73 d6 14 |.....W.55u5.Cs..| +000000c0 7e 2d b4 f8 31 60 1b 35 2a 38 91 32 40 8b f0 ab |~-..1`.5*8.2@...| +000000d0 a8 b0 dc 2b db b9 63 92 28 dc f2 c2 95 d3 4a 63 |...+..c.(.....Jc| +000000e0 69 e7 58 0c e5 9c d5 22 17 03 03 02 6d 7c 70 9b |i.X...."....m|p.| +000000f0 e1 81 3a 0d 6e 7f 5c 30 2e 09 1d 82 ac 48 a6 7e |..:.n.\0.....H.~| +00000100 03 ce d0 ce e2 e8 9e 8b 2b ee af 1a b1 6a 3a 27 |........+....j:'| +00000110 04 53 73 d2 d4 28 68 19 96 3a 3d 89 df 2c e3 2b |.Ss..(h..:=..,.+| +00000120 45 c8 5e 60 42 b0 4d f2 9c 8a 8d 83 f6 97 e0 b0 |E.^`B.M.........| +00000130 02 39 37 46 2b 07 28 8b e8 d8 c2 e3 ba 58 9b dc |.97F+.(......X..| +00000140 62 c4 e6 cb b4 97 f0 67 2b b3 40 4b 64 3e 73 3f |b......g+.@Kd>s?| +00000150 a1 1f 6e fe 7f ba af 7d bd c4 7c 37 60 c0 94 d6 |..n....}..|7`...| +00000160 bc 14 70 a9 95 a6 b7 88 9d 50 cf 9f 36 0c 38 c4 |..p......P..6.8.| +00000170 97 ba ea 43 16 e8 fd 72 22 3c 09 4a 97 1c 97 70 |...C...r"<.J...p| +00000180 88 6d d4 f3 9d b9 5a f3 67 f5 7b da 3e ed 1a 66 |.m....Z.g.{.>..f| +00000190 4c 62 50 ff cd 92 08 d8 5c 2e 11 de ea 44 16 91 |LbP.....\....D..| +000001a0 3e 44 d7 8c dd 2a b4 c7 2b 4d 40 a2 f9 7e 49 a9 |>D...*..+M@..~I.| +000001b0 d8 51 a1 27 b3 34 75 59 04 04 cd 52 d6 37 34 e6 |.Q.'.4uY...R.74.| +000001c0 41 32 36 45 c0 65 fb 5c e2 21 77 7f 35 db 9d 34 |A26E.e.\.!w.5..4| +000001d0 0d 6e 9d a7 9e 00 ec e3 3e 9c 50 50 13 5b ad b9 |.n......>.PP.[..| +000001e0 b3 47 44 f8 9b 12 ab 50 7f a7 df 35 c5 d6 78 3c |.GD....P...5..x<| +000001f0 c1 04 41 db 99 18 cd 8c 05 3f 08 ae 2b 41 c9 46 |..A......?..+A.F| +00000200 16 9a e3 a9 5b d3 9c 00 56 0e e2 d1 da 6d 6b 20 |....[...V....mk | +00000210 65 1b 55 1f 4f b1 eb 94 c6 48 e3 50 d6 14 c5 62 |e.U.O....H.P...b| +00000220 5e fc d2 cf df f4 68 90 c9 bb 80 54 f3 f3 a3 78 |^.....h....T...x| +00000230 af 1f 6f ef e1 d5 64 24 04 e5 d4 59 bc 4d 7b a0 |..o...d$...Y.M{.| +00000240 1a 23 e1 81 b7 c4 bb 52 86 f4 2a 85 d2 d0 7a ed |.#.....R..*...z.| +00000250 c0 5d 27 07 4b df 52 c4 ea c8 c9 9c f0 48 35 71 |.]'.K.R......H5q| +00000260 bd 04 65 65 47 e3 21 88 ff 08 6c 6a f3 6c dd 81 |..eeG.!...lj.l..| +00000270 3f 50 21 66 34 49 07 a0 e0 6d 80 54 77 8b 27 81 |?P!f4I...m.Tw.'.| +00000280 4f b9 59 60 0a b0 c7 00 6a 7b 26 33 f6 5e ad 37 |O.Y`....j{&3.^.7| +00000290 bf ea 87 e4 3c e7 b8 20 b0 89 88 ac 5a a4 af f7 |....<.. ....Z...| +000002a0 23 3c 0a d0 ab 74 fc 49 d2 e5 51 a7 a5 4e 21 5f |#<...t.I..Q..N!_| +000002b0 90 9a 65 36 9f e1 e3 9e 3d 67 d6 93 f1 b8 f0 4b |..e6....=g.....K| +000002c0 c6 d8 ca 50 fb cc 92 ab 47 b5 8c 21 02 4a ee 42 |...P....G..!.J.B| +000002d0 35 a3 52 41 04 94 19 cd 23 c6 33 b0 84 0d 88 97 |5.RA....#.3.....| +000002e0 5a e0 3e 4c 6d 99 ec 6d 11 3f 19 e7 77 60 3b de |Z.>Lm..m.?..w`;.| +000002f0 6d 04 b8 ab bc 83 4f 51 a5 ba 56 56 d6 e3 ff 0e |m.....OQ..VV....| +00000300 d5 4b 75 29 6a f9 4b c6 ef fd 62 25 89 76 f1 fd |.Ku)j.K...b%.v..| +00000310 84 3f e9 93 63 cf eb 47 85 b1 aa a2 4c 94 6b 99 |.?..c..G....L.k.| +00000320 98 6e 1a 19 85 0b 90 d2 9f 0f ec d4 36 1e 22 a0 |.n..........6.".| +00000330 4e 7f a1 ae 90 15 68 8a 48 c5 06 01 aa b9 56 cb |N.....h.H.....V.| +00000340 e0 62 53 d8 96 56 61 1d 81 96 b8 66 ae 94 c8 5f |.bS..Va....f..._| +00000350 86 47 fe ca 27 8d 7f 8e f8 74 17 03 03 00 99 ac |.G..'....t......| +00000360 2b 09 0b 44 a5 33 27 19 86 59 ca 75 5c df 59 fc |+..D.3'..Y.u\.Y.| +00000370 34 57 08 11 4f d8 1a c6 7c 76 d5 0a 36 91 f2 3a |4W..O...|v..6..:| +00000380 d1 96 58 64 29 3a d1 05 e3 cb 6f ea 92 4a f6 3b |..Xd):....o..J.;| +00000390 54 4c 16 41 99 6e 0f e9 c3 9a ac a3 59 ee fa c9 |TL.A.n......Y...| +000003a0 4d 58 ae 23 58 58 b5 b5 d6 6a dd b4 0c 24 bf e1 |MX.#XX...j...$..| +000003b0 d4 16 53 f2 2d e1 78 d0 ea 70 59 ac a3 e4 e4 6f |..S.-.x..pY....o| +000003c0 65 93 28 ad e1 64 83 11 05 42 a3 a0 11 d5 f2 af |e.(..d...B......| +000003d0 7e 03 93 80 82 48 e0 84 2e 1c 50 98 65 22 49 f1 |~....H....P.e"I.| +000003e0 df 41 03 83 b2 5c 1c 56 cb b7 f3 72 04 d6 09 cf |.A...\.V...r....| +000003f0 f9 3a 5d e8 35 80 b6 a2 17 03 03 00 35 b4 b5 c3 |.:].5.......5...| +00000400 43 78 3d e8 eb 66 7d 1c 36 8e a1 9f 26 ab 5a aa |Cx=..f}.6...&.Z.| +00000410 63 b6 2f 7a a5 f6 7d 89 1e 5d c5 a1 bf b4 3b 4a |c./z..}..]....;J| +00000420 89 1f 96 74 e3 c4 d8 72 57 a5 c7 99 a9 f3 77 16 |...t...rW.....w.| +00000430 f3 25 |.%| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 02 1e 64 ba 97 ba 8d |...........d....| -00000010 3f 1b d5 5b c5 2e e5 b9 10 01 37 c9 5c e5 ed 39 |?..[......7.\..9| -00000020 7f 9c 8b f8 ef 50 64 5e 30 05 16 ac 80 51 96 78 |.....Pd^0....Q.x| -00000030 2a 50 0f 1e d8 76 ab fd bd 7f 3b 17 7e 1d e9 f5 |*P...v....;.~...| -00000040 03 76 1b 66 3d 15 dc f3 65 a2 aa a9 23 89 09 e9 |.v.f=...e...#...| -00000050 dc de a6 27 fc 21 d9 97 d4 08 05 9a 1c 49 8c ee |...'.!.......I..| -00000060 fc bd f1 9f e2 4e 3a e3 ee 07 39 d0 34 05 cb 18 |.....N:...9.4...| -00000070 83 2b 68 45 df 84 4b b2 c3 79 42 73 b9 f1 1c f2 |.+hE..K..yBs....| -00000080 5f d9 5c f5 7c 4e 86 5e 97 78 ea 0a fa e7 60 68 |_.\.|N.^.x....`h| -00000090 80 c3 17 5f e7 92 9d 6e 9a 92 37 84 92 4b 83 9c |..._...n..7..K..| -000000a0 fa 4c 2a 82 23 eb 67 d0 b2 cc 9e 59 8f 2c e7 bc |.L*.#.g....Y.,..| -000000b0 b3 4f 2a 0c 93 bf 17 b8 48 70 5e 0a 85 92 6d 2a |.O*.....Hp^...m*| -000000c0 ac 81 9e cd 2c 59 fc a7 e3 5b 82 d5 e3 f5 cd c2 |....,Y...[......| -000000d0 8a 68 b8 e9 36 e2 08 0b f7 09 9c 17 95 a3 5e 3d |.h..6.........^=| -000000e0 ef 7c c6 5c fe 32 9e 9d 31 c9 b7 76 5a 71 c3 d7 |.|.\.2..1..vZq..| -000000f0 cd e3 c6 70 e5 2f 07 df 1d b4 34 56 0b ed 52 13 |...p./....4V..R.| -00000100 bc b2 ac 66 0c 84 b0 2e 32 93 08 f2 04 91 8e e3 |...f....2.......| -00000110 7b 7f 22 2a a9 04 50 5c 78 f1 06 c5 fd 2c 4c 77 |{."*..P\x....,Lw| -00000120 a9 17 b5 a8 42 6d f2 0e 87 32 d3 7f be 9e 1d 09 |....Bm...2......| -00000130 50 10 25 9d f1 a5 25 c3 c2 be 0d 8d 8e 96 5e 1c |P.%...%.......^.| -00000140 83 06 45 bc f0 5b 6f b5 0a 02 2a cc ce ac 7e 62 |..E..[o...*...~b| -00000150 f0 b1 89 25 30 bc 12 d2 da f9 1d d0 46 55 97 4c |...%0.......FU.L| -00000160 09 39 e1 a5 1f 4d e1 aa bd 6f 1f 0d 79 4a aa 49 |.9...M...o..yJ.I| -00000170 73 25 dc a5 bd f7 2b 64 3c 84 ed b0 ef 13 c5 6c |s%....+d<......l| -00000180 16 8b 27 bf a5 3d 15 f2 4a 3b 53 ad ba e9 9e 2a |..'..=..J;S....*| -00000190 6d f2 44 5c 66 69 04 94 27 99 08 8e c2 7e c6 69 |m.D\fi..'....~.i| -000001a0 f7 65 1d 0b a5 8c 35 52 0b f1 bd 59 ca d1 bf 44 |.e....5R...Y...D| -000001b0 47 b0 7b f8 3b a0 84 55 73 c2 83 bb 9d e0 bc ed |G.{.;..Us.......| -000001c0 60 07 32 ce 71 b3 60 12 ef ca 28 bb 6c fb bb c7 |`.2.q.`...(.l...| -000001d0 3e eb 05 65 a5 26 1a 6c 40 c8 b4 4e 31 12 a0 96 |>..e.&.l@..N1...| -000001e0 19 66 86 f5 1e f8 bd 6d f4 2e 98 60 fe ff 22 1e |.f.....m...`..".| -000001f0 a9 27 49 87 77 7d b4 5d ea f8 bc 3a 10 15 84 8c |.'I.w}.]...:....| -00000200 cd aa 2c e8 94 93 a5 ee db 7a d8 96 e9 d5 68 e9 |..,......z....h.| -00000210 34 68 40 5b dd 18 dc f0 ef b7 17 72 fd 06 70 d1 |4h@[.......r..p.| -00000220 b6 89 ae 66 40 40 f7 61 0b 17 03 03 00 a4 26 c1 |...f@@.a......&.| -00000230 3c d9 6c 83 52 e3 5e 64 46 7f 12 1d 3d c7 7d 0f |<.l.R.^dF...=.}.| -00000240 a9 8f d3 45 f5 81 46 16 24 c6 c3 7e 5f e4 25 be |...E..F.$..~_.%.| -00000250 00 33 7a 1c 35 d4 5c 64 54 56 08 66 4d 2f 68 15 |.3z.5.\dTV.fM/h.| -00000260 1b 71 d9 aa c9 9e e0 cc d2 73 a9 99 41 9b 08 1f |.q.......s..A...| -00000270 d4 41 de e5 4f 1f 30 65 61 02 8e 6f 79 d7 47 86 |.A..O.0ea..oy.G.| -00000280 2f e6 0e 65 9e 06 e8 98 d1 fe bc 89 b4 bc f4 9b |/..e............| -00000290 70 02 06 e4 9d 37 dd 1b 63 b6 06 62 1a c7 45 30 |p....7..c..b..E0| -000002a0 9d 08 64 35 8b 96 88 9a 1e 58 2f d0 ef 44 39 04 |..d5.....X/..D9.| -000002b0 3c bf e2 e6 c4 73 de f9 b0 10 ed 56 eb 04 bd 4e |<....s.....V...N| -000002c0 89 38 50 3b e7 e5 12 7c 8e 74 b2 a5 79 2d 88 7b |.8P;...|.t..y-.{| -000002d0 e5 1b 17 03 03 00 35 42 b2 61 24 4c 38 b5 d1 42 |......5B.a$L8..B| -000002e0 93 12 66 c5 be 3c f0 b1 b2 6b 86 07 99 7d f3 e4 |..f..<...k...}..| -000002f0 74 2b 43 98 38 df 70 7a e5 f7 67 cf c3 08 23 19 |t+C.8.pz..g...#.| -00000300 4a cf 06 26 fe 56 4a 97 4a 82 70 09 17 03 03 00 |J..&.VJ.J.p.....| -00000310 17 9b 3f bb 09 7d 4f c9 05 42 f7 d1 a7 59 0c a7 |..?..}O..B...Y..| -00000320 c6 9b 36 e1 46 ad 9b 89 17 03 03 00 13 ae a5 51 |..6.F..........Q| -00000330 76 d8 3a 77 a8 a0 38 70 bf be c8 fb ff fe 53 09 |v.:w..8p......S.| +00000000 14 03 03 00 01 01 17 03 03 02 1e 2e 1c 18 ac 6e |...............n| +00000010 bd d7 35 f8 21 6f 36 d7 13 94 53 3b 56 5d 03 8e |..5.!o6...S;V]..| +00000020 2d 92 fa cb 17 d3 75 55 13 84 9c aa be f7 34 9e |-.....uU......4.| +00000030 35 67 9b 90 bc 76 5d 65 c0 23 b0 04 d0 ba 15 b5 |5g...v]e.#......| +00000040 30 70 4d 8d d2 38 73 0a 3a 58 c3 bc da a4 f5 ae |0pM..8s.:X......| +00000050 05 ee 0c 06 bd 06 fe ab 1b 31 cf 4d 46 63 cc ee |.........1.MFc..| +00000060 8f 8a 0d e9 32 50 4d a0 f6 f2 ce c5 be 41 c2 16 |....2PM......A..| +00000070 a7 c3 b3 8a 5c 27 4a fd 37 2d 32 d9 76 25 27 12 |....\'J.7-2.v%'.| +00000080 03 b9 e7 ef bc c8 59 e1 16 80 dc b2 16 ae 05 b6 |......Y.........| +00000090 cf 8e 99 0d f8 ed 5a b1 bb c1 05 d5 35 fe fd 2d |......Z.....5..-| +000000a0 97 c6 19 d8 2d 1a a9 30 d1 4a 6d 27 45 93 5f 5d |....-..0.Jm'E._]| +000000b0 45 f4 98 a8 d8 88 27 8f f2 ad 1e 24 6e c8 8f 12 |E.....'....$n...| +000000c0 f7 32 b5 3d 3c e3 e0 32 56 4e 80 a8 5f 27 f0 d0 |.2.=<..2VN.._'..| +000000d0 a1 c2 d0 22 2d 3a 36 0f bd 7b 94 9f ca 8d c1 ea |..."-:6..{......| +000000e0 c6 1f d8 87 4a 75 bd 3e 0f ae 2f e1 78 ae 3f 00 |....Ju.>../.x.?.| +000000f0 f4 3a 82 dd ec 3f 61 43 bf 4b f8 01 a3 32 df 13 |.:...?aC.K...2..| +00000100 61 45 ca bb e0 9a 17 85 45 90 c6 fb 5d 79 1b 58 |aE......E...]y.X| +00000110 54 ca 84 e9 a9 11 c4 74 82 f7 da e4 b3 4f 05 a1 |T......t.....O..| +00000120 23 72 9f 63 b8 4c 55 e6 da 33 b9 1c b0 fe 28 72 |#r.c.LU..3....(r| +00000130 f0 02 b6 ec 70 ae 27 d4 21 51 32 56 32 4e e7 7d |....p.'.!Q2V2N.}| +00000140 b8 0d 75 25 45 5c 68 83 4f e3 3e 8a 87 7c 06 81 |..u%E\h.O.>..|..| +00000150 ac ff 23 44 0e bd e7 0a 76 64 45 c4 04 df 35 db |..#D....vdE...5.| +00000160 ab 8a 38 87 f5 e5 35 75 7a 92 85 3d 14 9e aa 19 |..8...5uz..=....| +00000170 4d 94 25 8f c0 c3 37 ca 63 f3 dd 48 4a 6a 6b f5 |M.%...7.c..HJjk.| +00000180 fa 52 67 30 ab ff 56 9f 58 bd cd 66 d4 83 85 d8 |.Rg0..V.X..f....| +00000190 85 6c 6d 3c 56 e5 17 75 fc dc a7 3d ed 18 a1 3b |.lm<V..u...=...;| +000001a0 6c e6 54 95 75 38 77 77 90 34 81 cb 1c cb e9 04 |l.T.u8ww.4......| +000001b0 c8 d2 12 04 36 a8 9b f6 9b 6a 81 8d f5 b1 e2 ca |....6....j......| +000001c0 31 37 27 f2 84 bd 5c 3a 1c 6c 64 83 35 94 89 ee |17'...\:.ld.5...| +000001d0 08 42 1d 05 52 67 e6 4d 7f bb d2 21 82 8c 15 6b |.B..Rg.M...!...k| +000001e0 e9 f9 6d bc b3 1f 5a df b8 55 aa 9d f6 aa d2 7c |..m...Z..U.....|| +000001f0 41 76 3b 1b b2 f5 b8 49 32 be bb f8 0e d3 74 be |Av;....I2.....t.| +00000200 eb 0d 9b e2 57 b6 ec e5 61 d7 09 80 a8 63 b4 cf |....W...a....c..| +00000210 bb 0a 14 9d 39 1c 08 58 22 c4 ae d5 4f 42 97 14 |....9..X"...OB..| +00000220 71 e1 c0 a5 5e 8e 2f 89 27 17 03 03 00 a3 f0 96 |q...^./.'.......| +00000230 d3 9e 8c 19 84 9a 42 d3 84 64 a6 89 40 6f d6 c9 |......B..d..@o..| +00000240 50 90 bb 9d 16 90 9d fb aa 85 28 ab 25 63 78 a9 |P.........(.%cx.| +00000250 dd dc 35 03 73 08 26 2b 30 53 84 f8 74 66 f2 6f |..5.s.&+0S..tf.o| +00000260 d7 0a f0 e2 c4 10 a4 46 cf 77 ea cb b7 b7 a9 81 |.......F.w......| +00000270 5f 09 4a 6a a5 16 a4 79 dc b0 c9 ae 5a ff 2a 7b |_.Jj...y....Z.*{| +00000280 3f bd 7a 15 b3 02 ad 3e 90 37 46 51 71 fc 6d d0 |?.z....>.7FQq.m.| +00000290 9f 38 42 95 1a 88 ac 5f 83 a1 8a 59 59 62 cc 4a |.8B...._...YYb.J| +000002a0 57 d2 3e 1e 7e 1d c0 4d 41 23 85 5f 92 f4 63 16 |W.>.~..MA#._..c.| +000002b0 df df 6e 3d d7 c1 e6 21 22 0f e1 13 82 29 a6 e3 |..n=...!"....)..| +000002c0 f8 8c a4 a3 72 1d 61 c1 2a 9d a8 2d 13 8a 4f 87 |....r.a.*..-..O.| +000002d0 91 17 03 03 00 35 9d 35 c8 ac 1e c6 46 8d e1 42 |.....5.5....F..B| +000002e0 68 e5 79 77 64 15 e2 13 c0 70 1a 47 59 d0 1e c3 |h.ywd....p.GY...| +000002f0 68 f7 5a fe 11 a2 3d e4 6e 2c b5 7d ea 98 e7 75 |h.Z...=.n,.}...u| +00000300 7c 54 a4 35 9b 1f c9 ba 72 b1 94 17 03 03 00 17 ||T.5....r.......| +00000310 a3 81 17 ac 97 a9 f0 91 b5 7a 04 38 ff fd 8e d3 |.........z.8....| +00000320 d8 7b c4 40 7e d3 ea 17 03 03 00 13 a8 b1 06 94 |.{.@~...........| +00000330 90 83 62 d5 be a8 23 d5 8b af 77 0d 90 13 98 |..b...#...w....| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-Ed25519 b/libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-Ed25519 index 26f76bc..689c287 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-Ed25519 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-Ed25519 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,107 +16,107 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 a5 5b a0 2c f5 |....z...v...[.,.| -00000010 57 cc 49 88 64 7d ea 7c ee 61 cf fc 94 9f d4 5c |W.I.d}.|.a.....\| -00000020 bb 83 80 5a f5 7c a3 fc 0a c8 61 20 00 00 00 00 |...Z.|....a ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 4e 4c 01 f1 4e |....z...v..NL..N| +00000010 49 97 ec eb df ce 50 4d 1c 9c d0 35 92 10 97 0a |I.....PM...5....| +00000020 dd fb a8 4f 39 c6 14 21 d6 42 ac 20 00 00 00 00 |...O9..!.B. ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 01 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 fe |..+.....3.$... .| -00000060 e1 43 bd 10 b3 f6 3b 4d 7c 46 8f a3 bc 7d 08 08 |.C....;M|F...}..| -00000070 22 ed aa 9b 7b 89 f3 87 13 7e fe 6c b0 db 3f 14 |"...{....~.l..?.| -00000080 03 03 00 01 01 17 03 03 00 17 2b ce 52 22 34 c5 |..........+.R"4.| -00000090 d9 2c ae d0 23 4d 0c 6e b4 f0 c8 58 11 22 54 bb |.,..#M.n...X."T.| -000000a0 15 17 03 03 00 42 96 b4 72 be f0 6b d3 b0 82 7c |.....B..r..k...|| -000000b0 dc d2 67 69 2c d4 40 a1 7a 3d 9a 39 a5 29 ca 64 |..gi,.@.z=.9.).d| -000000c0 c5 0b d2 ba 7c c3 73 e2 93 0d 44 e3 64 ce ec b2 |....|.s...D.d...| -000000d0 90 ae e2 df 18 f8 f5 93 5f 91 80 c2 b4 00 e7 de |........_.......| -000000e0 f5 3f 4d c8 de 4c 5f f0 17 03 03 02 6d c6 df 33 |.?M..L_.....m..3| -000000f0 1e 12 40 02 7f 46 67 d8 4b 98 d7 5e f7 0a bf dc |..@..Fg.K..^....| -00000100 fe 3c 7f 00 2d 74 31 cb 10 35 e2 eb 16 11 d1 2f |.<..-t1..5...../| -00000110 10 bf 8c 4d 37 c7 1b f6 23 a3 3e 68 87 1a 50 53 |...M7...#.>h..PS| -00000120 64 7c 0d fd 0d 06 32 93 17 85 da e0 d4 86 2c 5f |d|....2.......,_| -00000130 0a 91 9a fd 00 87 f1 f4 fc 18 22 a1 2e 21 44 7d |.........."..!D}| -00000140 6c ca 2c 0d f2 38 15 d1 9d 86 9b 67 b6 b4 06 6d |l.,..8.....g...m| -00000150 30 07 a8 b1 b8 7a 5d 1d 17 d0 c5 1a 40 a3 42 b5 |0....z].....@.B.| -00000160 dc 56 c8 ec c3 c3 4e ff 5f 7c ce 27 fa a6 82 2a |.V....N._|.'...*| -00000170 b9 85 47 4e 0b d1 84 17 92 a6 42 86 9a 65 1c a9 |..GN......B..e..| -00000180 45 be af a7 95 03 0b db 84 fa 5d 1b 7e 57 72 40 |E.........].~Wr@| -00000190 ab a3 9e 46 50 3f c7 03 94 9a 4a 02 bd 9a 90 1c |...FP?....J.....| -000001a0 42 c9 98 e9 81 cd e8 73 a6 82 42 20 24 89 d5 8d |B......s..B $...| -000001b0 48 20 df d4 f4 d2 15 e4 c0 28 ee d8 2a 1b ad b8 |H .......(..*...| -000001c0 1d a4 86 e1 b4 89 97 e8 36 63 aa 9c f4 7e 65 c6 |........6c...~e.| -000001d0 12 86 41 54 b3 4a 79 9f 48 33 fc fc 0d f5 14 47 |..AT.Jy.H3.....G| -000001e0 ba ae d3 20 64 37 f1 cd 9e 1b cc b2 27 68 e6 f2 |... d7......'h..| -000001f0 95 0c 29 59 f2 15 2e 97 60 f3 8d 1b b1 65 cd 4f |..)Y....`....e.O| -00000200 0d a5 0a 34 59 63 20 f0 71 e6 d5 13 f2 4e dc 73 |...4Yc .q....N.s| -00000210 5b 1a 36 d7 6a aa b0 30 f4 ff 68 ad f5 5e f0 12 |[.6.j..0..h..^..| -00000220 0c 34 a8 4d 91 03 8e 4a 30 07 23 49 41 7a fe 19 |.4.M...J0.#IAz..| -00000230 62 5b 6a a0 4d d5 54 a1 1f 45 91 86 b3 a1 c3 32 |b[j.M.T..E.....2| -00000240 62 79 a8 93 b3 d4 43 0c a8 12 10 4f f5 53 c3 3b |by....C....O.S.;| -00000250 d9 73 ef 42 be 1d f5 70 fd 9f ca 54 20 3a 33 c9 |.s.B...p...T :3.| -00000260 f6 e8 55 13 b3 ab 45 c8 bb 5c 6b b9 39 a9 04 ac |..U...E..\k.9...| -00000270 1c 3c 5a aa b7 91 2c 0c f6 74 ea 6b 2d e2 9a 3c |.<Z...,..t.k-..<| -00000280 d0 30 d8 14 e5 8c bf 06 2c d3 89 2e 0d ad df c5 |.0......,.......| -00000290 5b 6d fa 8f 0c 64 cc 40 04 12 97 ab ab ff be d8 |[m...d.@........| -000002a0 a6 fc 78 1d d4 18 90 bf b4 8e ce 09 40 8c dd 8a |..x.........@...| -000002b0 a8 cc 86 ce 6d a8 0c f8 79 66 f6 0b 46 2b 0d 4c |....m...yf..F+.L| -000002c0 73 14 dd cd 2c 56 77 f7 1f 4d 85 d0 1c 16 da 26 |s...,Vw..M.....&| -000002d0 b0 65 39 31 b5 cd f3 7a 80 52 96 6d 81 1e 65 98 |.e91...z.R.m..e.| -000002e0 b2 a3 12 22 52 68 c5 59 19 a1 9a be 80 5c 25 57 |..."Rh.Y.....\%W| -000002f0 9b 60 e9 95 28 4b 77 a0 70 ce 4b 5b 70 37 0a e3 |.`..(Kw.p.K[p7..| -00000300 7e 2c c7 0e 1c 6b 3a 54 2c 0d b3 53 0c f4 12 66 |~,...k:T,..S...f| -00000310 c6 17 04 88 f5 12 58 d8 2c 70 54 85 2b 71 ee 98 |......X.,pT.+q..| -00000320 75 8d e4 57 7c 96 a2 44 12 77 f0 6d 8a 12 89 b3 |u..W|..D.w.m....| -00000330 8b 85 bf 33 d9 ee de 24 b5 7d d5 cb 0d d4 9b bf |...3...$.}......| -00000340 c6 e3 27 44 f2 35 35 09 00 86 eb 8b 34 c4 c4 6a |..'D.55.....4..j| -00000350 fe 95 e9 80 58 4f 3e 99 24 f8 17 03 03 00 99 de |....XO>.$.......| -00000360 1b f5 7a dc 63 8d 5e 75 de 72 cf 41 ca 75 ab d9 |..z.c.^u.r.A.u..| -00000370 55 b0 b5 81 a9 6c a9 f6 1d ea 66 dd dd 86 f5 03 |U....l....f.....| -00000380 12 08 9d b4 07 48 eb 8b 45 f1 35 b1 31 bd 5d f3 |.....H..E.5.1.].| -00000390 e2 34 73 9a e5 87 b7 8b 0b 8b ab 7e 05 db 56 db |.4s........~..V.| -000003a0 4f 4c 52 1a 3b 5d 4c 53 b1 49 40 81 5e 73 af 26 |OLR.;]LS.I@.^s.&| -000003b0 21 e6 e3 5c 4a a6 f6 07 56 de f5 76 5c 67 d8 d5 |!..\J...V..v\g..| -000003c0 eb f3 6a fb 6d b7 00 bc 6b 28 c9 63 4d 58 76 97 |..j.m...k(.cMXv.| -000003d0 aa 51 2b f3 03 9c 70 3b 3e b2 a4 16 a0 a0 e0 43 |.Q+...p;>......C| -000003e0 77 da 88 2d 48 3b 07 e2 8d a6 e2 80 85 68 ac dc |w..-H;.......h..| -000003f0 ce 66 2f 97 20 9e 4e 33 17 03 03 00 35 f6 ce 98 |.f/. .N3....5...| -00000400 8b 01 f5 75 8e 98 42 02 b1 b8 90 f3 08 96 e8 5a |...u..B........Z| -00000410 d4 7c ef d1 62 1e b3 36 39 d9 b2 59 1f 1f cc 74 |.|..b..69..Y...t| -00000420 f2 a8 62 11 00 28 31 fa d9 5a 27 10 7b 93 ff de |..b..(1..Z'.{...| -00000430 a0 ec |..| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 c1 |..+.....3.$... .| +00000060 c2 ca 32 aa 48 d8 52 bc c8 23 6d 98 18 3e 15 b6 |..2.H.R..#m..>..| +00000070 0b 25 db f9 6f a7 e1 75 95 a1 46 d3 47 4a 0e 14 |.%..o..u..F.GJ..| +00000080 03 03 00 01 01 17 03 03 00 17 87 10 92 da b4 9a |................| +00000090 03 a5 0f 73 e6 93 cb 71 1d 58 6e 5d 27 eb ee b6 |...s...q.Xn]'...| +000000a0 c7 17 03 03 00 42 89 8d 57 16 95 5b f0 98 ad c7 |.....B..W..[....| +000000b0 d7 94 ba 4d 7e 88 b9 8d 13 26 a6 6c 81 90 a6 1e |...M~....&.l....| +000000c0 2b 4e 91 70 e2 da 9d a2 0d 6f 9b 5b ee 69 58 a1 |+N.p.....o.[.iX.| +000000d0 4c c3 59 57 28 62 b3 ed 26 15 79 db 01 8c 88 e3 |L.YW(b..&.y.....| +000000e0 63 1f bc b0 01 c9 82 ca 17 03 03 02 6d e5 d6 77 |c...........m..w| +000000f0 4e d3 af c3 5e 01 e9 1b 31 63 a4 84 d3 cc 2d f8 |N...^...1c....-.| +00000100 5d 73 f9 3e 83 03 c5 c5 cd 95 00 7b f2 b5 79 fa |]s.>.......{..y.| +00000110 47 e5 07 89 a9 22 49 7a 7e 7e 6e d2 3b 68 e8 9c |G...."Iz~~n.;h..| +00000120 40 1c 86 2a 48 ee 59 8e 1c 04 8b 91 20 68 65 31 |@..*H.Y..... he1| +00000130 e7 76 dc 6c 5a ce cb 32 d3 e8 71 7f 93 08 b5 01 |.v.lZ..2..q.....| +00000140 84 0a b4 ec 80 68 69 9b b3 4a 4a 4d 56 16 eb 42 |.....hi..JJMV..B| +00000150 29 93 4d b4 76 f6 e0 15 fe 25 b1 cb 5a da 22 4b |).M.v....%..Z."K| +00000160 88 4c ec 66 48 09 e1 d1 0f 3e 3a ad 65 d7 d7 85 |.L.fH....>:.e...| +00000170 1d cb 35 2c 84 60 ec a1 6d f1 60 cf c6 c7 82 1a |..5,.`..m.`.....| +00000180 7c 91 40 2e 3e 88 1f ff 79 2e 6e 97 c5 45 9f e1 ||.@.>...y.n..E..| +00000190 bf 33 ad 65 df f3 ce 1a d7 57 7e db f2 28 79 a9 |.3.e.....W~..(y.| +000001a0 9e 4f 9e 8a ce 02 5a 18 bb f1 ac 72 5b 3f 4c 6b |.O....Z....r[?Lk| +000001b0 97 14 14 f9 82 8a 4f 99 21 98 db af 3e 08 ab 4f |......O.!...>..O| +000001c0 d8 3f f6 cc da 76 77 eb 02 39 0a 00 23 a5 e0 92 |.?...vw..9..#...| +000001d0 01 10 3f 76 ab 1a 38 8e f9 a1 d0 25 c3 9d 50 a4 |..?v..8....%..P.| +000001e0 ef a5 8c f8 5d bc d9 fd dd 25 cd 42 38 52 d1 cd |....]....%.B8R..| +000001f0 d2 1b fc ba 7d 8b bd 82 05 23 c3 9d 02 ff 1b 4e |....}....#.....N| +00000200 08 e1 f3 7c 35 15 0f e8 0e b7 8a e5 4a 2b da 45 |...|5.......J+.E| +00000210 4a 72 9a 32 7e 55 52 65 d2 a8 32 90 53 bf 25 29 |Jr.2~URe..2.S.%)| +00000220 1e 8d d7 a3 22 d6 40 19 95 58 a8 37 af a8 52 e7 |....".@..X.7..R.| +00000230 79 b9 4e 61 d8 f0 7d d2 69 25 99 28 3f 31 f6 b2 |y.Na..}.i%.(?1..| +00000240 44 65 1f 9c 41 08 17 c9 01 5d 20 ea ab fe 06 64 |De..A....] ....d| +00000250 9a f4 d0 24 e0 b5 88 0a 2b 96 e9 71 11 a8 49 b4 |...$....+..q..I.| +00000260 40 62 1b 45 15 47 cb a5 fc 4f 07 58 2b ef d4 5d |@b.E.G...O.X+..]| +00000270 df 40 38 6c 6e ca 63 c5 95 2d 79 26 86 ff 33 02 |.@8ln.c..-y&..3.| +00000280 da 5a 85 0c 8f 7f 58 ba ea 88 cf bc 51 92 12 86 |.Z....X.....Q...| +00000290 f1 c1 f9 0a d0 6e cc b4 2b 16 98 ad f8 11 ad 63 |.....n..+......c| +000002a0 82 d7 4e ea a5 ee 78 a2 9a 35 b6 b3 d9 24 cf 66 |..N...x..5...$.f| +000002b0 03 d2 25 1f 15 37 c7 b5 8e bb 0a 40 0f 28 c2 16 |..%..7.....@.(..| +000002c0 90 a4 61 9e dd fd b5 ad 97 39 0d 66 e7 fa 5b e2 |..a......9.f..[.| +000002d0 c2 ef 44 5d 44 07 d6 c3 ed e2 89 6e 4c ed 79 42 |..D]D......nL.yB| +000002e0 86 3b f4 94 0c 82 5e 52 ce 00 ab 5c 20 b4 18 db |.;....^R...\ ...| +000002f0 c9 fe 8b be 8d da e9 86 13 62 6b 8d 0d 57 c8 fe |.........bk..W..| +00000300 a6 4b 82 52 d5 d8 05 18 2f a0 43 d6 c8 89 fb e7 |.K.R..../.C.....| +00000310 72 17 61 89 36 5b e0 aa 4d 6c 20 ee 68 db 32 e4 |r.a.6[..Ml .h.2.| +00000320 97 9f 18 26 7c 1a cd e8 b9 05 ae fd 86 bf 0e 47 |...&|..........G| +00000330 09 06 bd de 2d b9 50 6a 0c a6 27 04 5e aa e0 ce |....-.Pj..'.^...| +00000340 e7 cf 98 f9 7e 7d b9 4d 77 9a 88 3a d4 41 07 cc |....~}.Mw..:.A..| +00000350 87 b6 41 53 8b 8c 79 8e 07 b9 17 03 03 00 99 0b |..AS..y.........| +00000360 63 4e d8 79 d7 11 f2 46 00 6c 5d d2 9e 49 df 7e |cN.y...F.l]..I.~| +00000370 f2 96 1a 68 9d 6a 05 dc 61 45 47 a4 18 5c 65 04 |...h.j..aEG..\e.| +00000380 00 38 d1 25 0c ff a3 a2 c0 c2 82 7f b1 1b a1 c6 |.8.%............| +00000390 7b ac fb 71 48 b6 e4 e2 7b c4 d0 44 8e 22 d6 91 |{..qH...{..D."..| +000003a0 99 87 a2 88 3d bb b4 80 13 57 2a 6a b0 2d 52 16 |....=....W*j.-R.| +000003b0 d3 f2 e4 cd d0 79 9a 31 ce 68 65 b3 61 67 a0 b9 |.....y.1.he.ag..| +000003c0 1e 6b 9f 73 dc 46 be 5e df d7 c2 30 d5 60 b5 e5 |.k.s.F.^...0.`..| +000003d0 60 cc 10 ae 9a f9 b6 9a fd 14 b9 1e b7 3c 1d 3e |`............<.>| +000003e0 34 a6 49 d2 48 f7 24 56 29 c9 98 f1 33 b1 e5 5e |4.I.H.$V)...3..^| +000003f0 2c 7b bb 5f b6 53 6a c8 17 03 03 00 35 d9 af 32 |,{._.Sj.....5..2| +00000400 1f a5 09 3f 8a 10 df a7 34 9b f8 ec 07 81 80 73 |...?....4......s| +00000410 dc ba 09 fc 40 e4 1e df f6 de 02 54 3c 7d ea 49 |....@......T<}.I| +00000420 91 16 72 70 8e 1a 21 76 c6 00 0e 03 9f 0a 82 fe |..rp..!v........| +00000430 4c 18 |L.| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 01 50 57 2a 94 d7 c1 |..........PW*...| -00000010 40 42 d3 aa e3 d8 b3 e4 13 ff 51 ee 8a 52 9d 9c |@B........Q..R..| -00000020 c4 a4 40 91 72 0f c9 4e fe 56 22 89 ea fb 6d 05 |..@.r..N.V"...m.| -00000030 a2 96 97 4b fa ef ec 13 b6 13 3b 69 6c 65 c0 74 |...K......;ile.t| -00000040 e5 54 df a4 97 50 f7 85 a1 c7 fb 52 84 56 98 16 |.T...P.....R.V..| -00000050 52 b6 eb 5a d0 72 6e 65 98 81 bb f5 2a 4c ed 1a |R..Z.rne....*L..| -00000060 90 e1 01 a6 2b eb e0 1d 06 ba 8a d4 47 45 90 f0 |....+.......GE..| -00000070 91 bd c4 d7 54 ba 44 30 78 42 15 42 74 59 1c c7 |....T.D0xB.BtY..| -00000080 56 34 39 64 8e f8 0a 0f 2b 35 0f 06 97 34 3e 5e |V49d....+5...4>^| -00000090 00 00 5a f0 07 0a f5 66 46 86 94 8c 0b 62 1c fd |..Z....fF....b..| -000000a0 cc cf fd 5d 06 96 1e 21 9e 20 d5 07 5f 5a 00 9f |...]...!. .._Z..| -000000b0 6f 80 36 5e aa 56 d0 07 00 20 08 55 48 fe 6c a1 |o.6^.V... .UH.l.| -000000c0 b1 22 f3 94 54 7e 7e d5 e9 f0 71 69 01 fc bd 14 |."..T~~...qi....| -000000d0 a1 de 38 e4 b4 02 88 3e 66 77 3b f7 aa cd 57 a3 |..8....>fw;...W.| -000000e0 cf 6a 40 7d 93 75 79 3b 95 07 33 69 b2 8d 2a 37 |.j@}.uy;..3i..*7| -000000f0 94 d3 8d d5 b5 8a f0 94 8d 1e b4 9e 02 4f 7d 83 |.............O}.| -00000100 05 c6 c7 c8 a0 74 f1 88 f7 68 bf 4b e4 18 3b 6f |.....t...h.K..;o| -00000110 0c 6c a6 e7 75 50 b9 f6 68 2e 05 67 a3 47 df 22 |.l..uP..h..g.G."| -00000120 fa ae c1 4f a8 3d f3 bb dc 66 c3 b6 98 b7 8c 5b |...O.=...f.....[| -00000130 48 51 57 d7 43 b2 13 25 9e d5 82 6c 70 5c 42 53 |HQW.C..%...lp\BS| -00000140 a9 e8 8a 12 26 cd 3a f8 f8 e5 97 84 55 89 09 d4 |....&.:.....U...| -00000150 d4 20 40 d7 2d 6f 66 36 63 f6 53 17 03 03 00 59 |. @.-of6c.S....Y| -00000160 2f f6 22 ce f3 86 f8 ee b1 f6 49 de c8 bf 91 9c |/.".......I.....| -00000170 bc 2f fa 75 af 51 bc ee b7 a5 a9 82 35 3b 83 9d |./.u.Q......5;..| -00000180 3d 9f 57 10 07 4b af 01 66 f0 39 dd f0 4a a7 90 |=.W..K..f.9..J..| -00000190 f3 6c 28 97 80 0d a5 74 2d 22 a3 81 cd 64 2b 1a |.l(....t-"...d+.| -000001a0 d1 4e 2d 9e 8e 69 38 f8 11 9c 17 1f e6 c9 01 4e |.N-..i8........N| -000001b0 48 1f 80 43 26 d4 5a 82 30 17 03 03 00 35 e9 25 |H..C&.Z.0....5.%| -000001c0 b9 01 8e 0d 51 be 9d d1 b4 2b 0a ee 36 69 85 1a |....Q....+..6i..| -000001d0 10 a8 ff 36 e7 21 b7 f2 54 75 ca 07 52 88 48 d0 |...6.!..Tu..R.H.| -000001e0 ad 67 0b 92 52 70 fa 14 bc 7e 1d 43 f0 a2 7b df |.g..Rp...~.C..{.| -000001f0 ac 0c 19 17 03 03 00 17 98 76 d7 52 06 90 ef 00 |.........v.R....| -00000200 21 5e ec ed 0e 35 77 ef 5c f1 32 58 33 0f 06 17 |!^...5w.\.2X3...| -00000210 03 03 00 13 05 fb b3 c3 4d b5 a4 9c 52 ea bc d2 |........M...R...| -00000220 86 08 26 b8 df 5c 4c |..&..\L| +00000000 14 03 03 00 01 01 17 03 03 01 50 1d 6e 16 0d 4e |..........P.n..N| +00000010 c0 a2 41 c3 a2 84 c9 80 c0 f0 ef c0 5d 3a 3b f2 |..A.........]:;.| +00000020 bf 1c 9e 79 d7 d3 94 0b 41 2d bc 50 eb 0f 60 f4 |...y....A-.P..`.| +00000030 bd cd f6 03 22 7b 68 68 44 34 c9 0f 23 ca 76 6f |...."{hhD4..#.vo| +00000040 f2 97 38 07 43 56 7e b7 ce 67 68 67 37 34 d0 f7 |..8.CV~..ghg74..| +00000050 c5 92 fd 65 98 b8 7e 5f 48 a8 a3 aa a8 96 65 b5 |...e..~_H.....e.| +00000060 48 be 91 99 67 0a 37 c7 31 b4 43 ba 26 bb 87 98 |H...g.7.1.C.&...| +00000070 3c 55 e4 63 b0 33 ca ee 0a a5 fe 36 88 ef cf f0 |<U.c.3.....6....| +00000080 ab 6b 7d e8 f6 1f 14 12 49 f7 14 b7 12 bb d8 1e |.k}.....I.......| +00000090 e0 be ed 56 75 b9 ab 8a 20 75 d9 6f 45 2d 71 b3 |...Vu... u.oE-q.| +000000a0 2f b7 cd 9c c5 16 ed 37 0e 08 15 a5 49 18 7c 13 |/......7....I.|.| +000000b0 8e 0b 66 01 b1 8c 1d 89 d4 91 9e 5a 6b 94 f6 fa |..f........Zk...| +000000c0 7b a8 14 1c a7 20 55 c5 e4 0e 9d e0 5b d6 d4 b7 |{.... U.....[...| +000000d0 1d 93 2b 7c 25 46 28 11 06 57 a3 cb 2f 4b 39 cf |..+|%F(..W../K9.| +000000e0 61 be 60 9a fd f1 6e e1 a2 a7 20 f2 fd 50 a2 d2 |a.`...n... ..P..| +000000f0 17 db 16 4f 3f 8c 20 e4 4d 56 37 3b c2 42 17 cc |...O?. .MV7;.B..| +00000100 5d 99 06 fc 18 0d 1a 88 e8 f9 6f cf 7d 2e 57 73 |].........o.}.Ws| +00000110 85 47 ed d0 2d b3 9a 05 cf 0c 7d e6 ed 29 95 f4 |.G..-.....}..)..| +00000120 d5 e0 96 6a 1d 67 3e 5f 43 9f b5 f6 66 f5 84 63 |...j.g>_C...f..c| +00000130 bd 42 a6 f8 ef 38 42 8a d8 28 dc 55 e5 88 03 76 |.B...8B..(.U...v| +00000140 96 ba 89 35 63 7e 6c da 39 d8 9a 27 04 ab d5 0e |...5c~l.9..'....| +00000150 48 89 cc 81 25 44 61 16 2c b2 69 17 03 03 00 59 |H...%Da.,.i....Y| +00000160 81 8f 94 30 8d fc 47 13 7e 84 06 9b 4a 85 2c bb |...0..G.~...J.,.| +00000170 b3 a0 0d 4f 50 6a cb 0b 9b 40 ef cc 84 70 1f 69 |...OPj...@...p.i| +00000180 b9 3e a6 c4 ba 66 eb a9 6f 78 83 7f d4 1f d8 c4 |.>...f..ox......| +00000190 b0 f6 9b 03 29 7f b1 f8 60 40 0b 28 91 32 2c 03 |....)...`@.(.2,.| +000001a0 aa 9e 7b fb 99 c2 11 51 1f a7 81 69 16 39 f4 52 |..{....Q...i.9.R| +000001b0 ca d8 d0 f3 87 6f 58 ab 9a 17 03 03 00 35 de 03 |.....oX......5..| +000001c0 88 61 50 5c 08 88 77 28 6a 1d 28 44 3d 49 8b 79 |.aP\..w(j.(D=I.y| +000001d0 d1 a2 13 67 95 0f 7c 18 fe e2 e0 07 f1 ce b9 be |...g..|.........| +000001e0 79 aa 40 d6 cf 66 53 ac 15 ae 2a 14 a9 63 98 55 |y.@..fS...*..c.U| +000001f0 96 16 6f 17 03 03 00 17 a8 ac 17 c5 eb d9 8e 77 |..o............w| +00000200 9e 4b e0 20 c6 0c 34 b6 c3 ab c4 b6 8b b2 77 17 |.K. ..4.......w.| +00000210 03 03 00 13 58 d4 7b 8f ca 20 41 e3 3f d1 ae cf |....X.{.. A.?...| +00000220 3d e1 86 91 c0 a1 08 |=......| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-ECDSA b/libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-ECDSA index 09de5cc..8e361ea 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-ECDSA +++ b/libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-ECDSA @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,119 +16,119 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 cc a2 2d 09 42 |....z...v....-.B| -00000010 f0 11 87 04 64 83 e4 d8 80 a5 0f 88 69 ae f1 d2 |....d.......i...| -00000020 12 05 d2 08 75 15 86 b7 d8 69 e7 20 00 00 00 00 |....u....i. ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 30 0a c5 df b0 |....z...v..0....| +00000010 90 3a 48 4b 20 f1 89 62 be 1f 1b 64 c2 7e 69 25 |.:HK ..b...d.~i%| +00000020 9f b7 f9 2c 86 e7 40 e7 e8 10 fa 20 00 00 00 00 |...,..@.... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 01 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 c9 |..+.....3.$... .| -00000060 b4 93 8b 5b b0 ae 93 4a 01 26 0c fb db 3f 53 0b |...[...J.&...?S.| -00000070 04 ca 65 63 3f d7 d9 f9 fc ca ea 4c f2 08 3c 14 |..ec?......L..<.| -00000080 03 03 00 01 01 17 03 03 00 17 85 f6 ff f8 58 7f |..............X.| -00000090 2a d9 e0 12 82 d6 31 64 29 70 05 24 0f 17 1e 9f |*.....1d)p.$....| -000000a0 dc 17 03 03 00 42 16 7b d5 fa a6 30 94 8e a0 a7 |.....B.{...0....| -000000b0 24 59 b9 3d 85 b0 2f d9 25 c6 5a b5 7f 51 ca 54 |$Y.=../.%.Z..Q.T| -000000c0 4a f7 f0 72 bb dd 5e 70 14 6d 46 3f b3 86 6f c1 |J..r..^p.mF?..o.| -000000d0 a4 5f 6d ba 97 f3 38 c0 24 4a 9f de 7b b9 49 12 |._m...8.$J..{.I.| -000000e0 71 02 f8 bc bc 65 5a ea 17 03 03 02 22 f9 92 7e |q....eZ....."..~| -000000f0 34 eb b3 a4 03 8e ec 48 30 a0 9b ac a6 7b b3 a5 |4......H0....{..| -00000100 d0 4a 89 2c 92 6a c6 04 de b2 86 72 0a f1 97 61 |.J.,.j.....r...a| -00000110 da 70 ef 25 5a a3 f1 b3 3d 78 f1 ec 2b 8f 34 2b |.p.%Z...=x..+.4+| -00000120 c9 94 e7 d2 9e 2f 09 5d 7a e3 2e fc 6e e1 ef 80 |...../.]z...n...| -00000130 e6 0c e9 3e 07 bb b7 0e 74 0c e8 19 fe 7f d8 d0 |...>....t.......| -00000140 fa 70 03 c1 31 c2 76 51 c3 d0 ed a6 a1 0d 20 74 |.p..1.vQ...... t| -00000150 86 15 99 51 71 f8 3d 8e 1c 8c a8 19 0a 9c ac 4a |...Qq.=........J| -00000160 ab 0e e6 cc 52 a0 a8 ca d9 71 54 aa 2c 8b 6f 5b |....R....qT.,.o[| -00000170 f9 46 07 0d 86 40 d9 54 33 8e de 54 a5 c2 6e 36 |.F...@.T3..T..n6| -00000180 14 0e e3 52 78 05 56 90 98 2c e1 ec 26 f6 bd 6a |...Rx.V..,..&..j| -00000190 e5 0b 31 e1 a4 2a 2a 96 1b d6 57 87 ac a8 07 71 |..1..**...W....q| -000001a0 83 d9 70 1e 5e 63 9b d1 01 83 e7 c9 c8 1c 5a 34 |..p.^c........Z4| -000001b0 05 c0 7b da 1c ca 5f 99 49 9a 04 da c9 1c 9b ed |..{..._.I.......| -000001c0 b4 af 9d ff 36 71 1b 3a 00 e8 6a c4 6e 47 d9 4a |....6q.:..j.nG.J| -000001d0 64 f5 c1 07 ab 19 c8 65 a3 33 26 99 be 53 c3 86 |d......e.3&..S..| -000001e0 97 10 ef c1 54 8e 69 6c b1 29 aa 7d c1 63 67 ba |....T.il.).}.cg.| -000001f0 d7 72 7c 74 83 58 bd 5a a8 a8 5f 49 38 ee 1e 34 |.r|t.X.Z.._I8..4| -00000200 c8 98 19 73 97 2d 76 e6 d7 0d 15 75 a0 98 1f 15 |...s.-v....u....| -00000210 c9 b8 3d 3f cb 92 a1 39 4b 91 ca e0 d2 0e 38 c2 |..=?...9K.....8.| -00000220 20 eb f2 b5 04 64 fa d8 e2 d7 2f ba 88 7e f4 37 | ....d..../..~.7| -00000230 c1 68 c4 2f c9 54 a1 21 5d 4b e7 67 3b 2e 6a 06 |.h./.T.!]K.g;.j.| -00000240 55 ba d4 8d fe 0e b1 b7 2d cf c2 82 ed 27 3d 5b |U.......-....'=[| -00000250 9b 3b 28 a9 d4 c4 3c a0 45 b1 77 37 8b f8 7e f0 |.;(...<.E.w7..~.| -00000260 51 90 fe 7a 74 14 ac f7 59 8b ed be 79 b0 4b 89 |Q..zt...Y...y.K.| -00000270 d9 0c 39 fe 45 9d 15 0c a6 96 26 0d b2 29 b0 a4 |..9.E.....&..)..| -00000280 29 62 df 4b c0 a0 05 f1 e8 8b 16 af ea 42 8b 58 |)b.K.........B.X| -00000290 5a ae f6 28 d8 40 09 d1 1e 21 b3 c7 a8 e2 30 4a |Z..(.@...!....0J| -000002a0 27 e6 c4 ba ff 62 91 7b ab 64 18 65 02 e2 10 68 |'....b.{.d.e...h| -000002b0 87 35 c2 09 5b 23 a4 eb 96 19 a7 1e 75 85 6e 17 |.5..[#......u.n.| -000002c0 0e bc 11 1a f5 49 05 92 f7 0e e4 c7 85 da 4e 26 |.....I........N&| -000002d0 5b de f2 dc 36 fb dc dd c6 42 23 0c a7 de 8d ad |[...6....B#.....| -000002e0 f5 2a 8b ff b4 5d c6 ca ec e3 83 a4 1e 23 3a 2d |.*...].......#:-| -000002f0 1a 52 51 11 f5 3b 93 47 89 c8 fc 21 b0 a3 4f b3 |.RQ..;.G...!..O.| -00000300 6e d2 83 ca 20 75 fc 43 43 e5 1d 5d 57 c9 7c 17 |n... u.CC..]W.|.| -00000310 03 03 00 a4 dc 79 73 47 d4 f5 72 c9 12 46 ed 3c |.....ysG..r..F.<| -00000320 d0 61 20 81 a9 ad 64 f3 f1 77 7f f1 74 09 67 80 |.a ...d..w..t.g.| -00000330 c1 08 07 9c 50 b8 7d f5 70 f5 c6 a1 5f ba 37 78 |....P.}.p..._.7x| -00000340 58 37 e3 f4 3f 03 1d 69 6f af 2f 2b 8b 10 95 5a |X7..?..io./+...Z| -00000350 be a1 5c b8 42 61 65 5a 27 35 f6 b4 57 3d 3a 6b |..\.BaeZ'5..W=:k| -00000360 f4 e9 90 88 7b e3 7c bf be 51 19 0e 51 53 cd 10 |....{.|..Q..QS..| -00000370 2c 70 76 9e d1 32 28 8f c4 6c 01 2c 46 8f 4d 14 |,pv..2(..l.,F.M.| -00000380 21 a2 63 39 44 b3 03 0d a3 9d a0 c8 f4 cf 5d 7e |!.c9D.........]~| -00000390 d2 17 05 ee 9c 5c 1a 2e 43 dc 3f 6d d9 f2 54 5d |.....\..C.?m..T]| -000003a0 64 ff d2 1c 21 73 66 b1 2c 21 9d 3f bf fe f8 a5 |d...!sf.,!.?....| -000003b0 79 54 fe 8a d5 3d 5f f6 17 03 03 00 35 0f 01 eb |yT...=_.....5...| -000003c0 f8 46 f8 07 7a 06 69 45 e2 47 4d b0 eb 9c 82 8b |.F..z.iE.GM.....| -000003d0 5d d0 59 66 d1 b5 a2 7b b2 f0 72 6f 34 8b 2c 05 |].Yf...{..ro4.,.| -000003e0 84 53 1c 7b 24 d8 f0 cd a3 46 d1 ed 08 22 bb e6 |.S.{$....F..."..| -000003f0 38 98 |8.| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 94 |..+.....3.$... .| +00000060 e8 ab 87 65 c8 dd 6f ee b4 d6 0b bb fd 18 9a 2d |...e..o........-| +00000070 e4 bc c6 20 98 09 71 65 7d 54 35 73 22 99 1b 14 |... ..qe}T5s"...| +00000080 03 03 00 01 01 17 03 03 00 17 37 b7 eb eb a2 9f |..........7.....| +00000090 7f 00 8c 9d a9 50 7c 0c 15 31 63 71 45 7a 3d ee |.....P|..1cqEz=.| +000000a0 5e 17 03 03 00 42 9f 23 07 cf d0 bc e8 bb 95 01 |^....B.#........| +000000b0 37 94 18 2e 05 02 8a eb 0a 37 10 79 51 a9 d4 43 |7........7.yQ..C| +000000c0 18 18 e6 00 9d 68 ff 74 f3 9c 19 bf 5e 51 0c 47 |.....h.t....^Q.G| +000000d0 61 35 8c b2 58 5f 32 bc 88 c4 fb 5a 22 61 14 98 |a5..X_2....Z"a..| +000000e0 28 26 8c 75 9d 1d 19 05 17 03 03 02 22 d2 2c 1a |(&.u........".,.| +000000f0 e5 58 0d d7 0b c4 66 b2 06 90 bc 92 0f 05 34 5d |.X....f.......4]| +00000100 2b 20 26 02 cc ac 90 40 a0 f1 5f 0e b9 99 7c 0f |+ &....@.._...|.| +00000110 c9 3e 60 0b 39 ec 6c 94 3a d4 f7 b7 49 5e c7 6e |.>`.9.l.:...I^.n| +00000120 df 3b cc 33 cb 32 41 53 dd 09 8e 91 97 d2 e0 06 |.;.3.2AS........| +00000130 5e 0c 4c 49 46 18 83 fc ac b4 f8 76 2d 18 ee 0b |^.LIF......v-...| +00000140 b6 4a b9 aa eb ee db 7a aa 6d 04 84 ed 8e 15 bc |.J.....z.m......| +00000150 bf 6f a1 29 bc 0b 9f ba 05 a5 42 82 fd 1c 30 c9 |.o.)......B...0.| +00000160 20 df 8e ba 28 ab 0b a2 42 09 5e e8 c1 61 d2 25 | ...(...B.^..a.%| +00000170 fc 05 53 62 91 45 29 54 60 31 b8 4f 01 9c 7b 6a |..Sb.E)T`1.O..{j| +00000180 04 27 df bc e0 a0 3d b3 80 73 22 ca 9b 41 be b6 |.'....=..s"..A..| +00000190 09 22 67 1e 54 52 ce 14 b5 56 7a ca 3f a8 3e 01 |."g.TR...Vz.?.>.| +000001a0 d2 e4 36 18 87 f6 08 19 55 d2 ba 3c a3 c5 11 84 |..6.....U..<....| +000001b0 62 2a 09 c6 67 de cd ab 66 12 dd 0a 23 77 18 b7 |b*..g...f...#w..| +000001c0 73 c1 29 61 52 32 95 eb a0 db 72 ae b7 ff 2a b2 |s.)aR2....r...*.| +000001d0 08 f6 d7 69 32 c2 f8 8b e1 40 a9 d0 fe 11 64 a2 |...i2....@....d.| +000001e0 a2 dd a7 e6 a6 dd 5d 79 49 df bb c0 83 da 56 7a |......]yI.....Vz| +000001f0 a5 22 8e 60 df 89 48 e0 e2 e9 5f d5 fe dd ba 34 |.".`..H..._....4| +00000200 ad 91 52 d8 2f 7e a4 73 50 e8 b7 83 e2 d9 5e 05 |..R./~.sP.....^.| +00000210 96 08 e4 d4 bb 01 39 99 aa 1d fd 74 1b dc ca c2 |......9....t....| +00000220 8f bb b8 bf c4 eb 00 6f cc 70 eb 7c c7 29 e4 64 |.......o.p.|.).d| +00000230 8c 76 a7 b5 79 ea b6 96 fe eb 8f e7 81 9b d1 d0 |.v..y...........| +00000240 41 16 db ef 9e 55 2a 77 6c 34 54 22 48 6a ca 78 |A....U*wl4T"Hj.x| +00000250 31 6e d2 00 7f 54 93 65 ec 28 42 66 7b 74 4d 58 |1n...T.e.(Bf{tMX| +00000260 fe 25 74 bd 9f a4 ff f2 45 06 c6 63 1f 11 68 a4 |.%t.....E..c..h.| +00000270 fb fe 62 2b f8 19 e3 32 2c cc 5d 71 37 21 05 82 |..b+...2,.]q7!..| +00000280 c9 c7 30 c7 74 64 d9 f9 6b c2 ae d8 15 2b 2a 79 |..0.td..k....+*y| +00000290 a0 2d a3 18 1f d7 20 99 96 86 52 32 cf 84 bd 73 |.-.... ...R2...s| +000002a0 63 85 82 a3 64 fb e3 ea 1b 31 f5 df 1c 74 06 48 |c...d....1...t.H| +000002b0 69 8a e3 f0 72 8c 59 8b de 0b 06 02 47 54 4c 2d |i...r.Y.....GTL-| +000002c0 46 ac d4 f5 4d 5c fe 0d bf af d0 37 58 82 3e d2 |F...M\.....7X.>.| +000002d0 4e c1 7e 0f b0 21 f7 8e 2c 88 db 83 43 ed ad 5b |N.~..!..,...C..[| +000002e0 0f a2 ce 47 e4 3f dd 1b 71 fe f0 a7 a1 8d 8c dc |...G.?..q.......| +000002f0 75 e0 7a 89 f7 14 5b 37 9d 35 f6 23 91 a8 d2 1a |u.z...[7.5.#....| +00000300 96 07 1b 5b 9c 35 27 b8 b9 0c 92 1e cf 1b 3c 17 |...[.5'.......<.| +00000310 03 03 00 a4 f0 59 e1 1d 62 39 69 c5 53 ae 66 85 |.....Y..b9i.S.f.| +00000320 df ea 32 73 ca 94 e2 b5 14 d4 30 07 dd fd 2f 9a |..2s......0.../.| +00000330 16 fc e9 71 4a 20 b8 d2 7e 17 26 ff a9 55 56 24 |...qJ ..~.&..UV$| +00000340 31 85 bc ea 19 1c 37 b7 fe 8b 47 5f a3 99 0f 5d |1.....7...G_...]| +00000350 17 92 4b 2a 4c b5 6c db 8f bb 46 ee 89 31 53 79 |..K*L.l...F..1Sy| +00000360 aa 34 9d 9b e8 9b e7 82 55 a3 92 f6 53 53 d3 72 |.4......U...SS.r| +00000370 17 23 33 01 e8 75 7e 8d 63 91 a0 67 8f a5 f0 15 |.#3..u~.c..g....| +00000380 8c f5 81 e2 c4 08 ff 14 1d 96 cf ef 4e 09 18 a1 |............N...| +00000390 2c 38 0a f7 33 f0 1d ef 9d 12 4d 8c 25 f0 80 a2 |,8..3.....M.%...| +000003a0 aa a7 cf e4 7c e6 44 58 6d 30 70 48 55 3b b5 79 |....|.DXm0pHU;.y| +000003b0 55 aa 03 ed 14 ea e5 ee 17 03 03 00 35 72 1a ca |U...........5r..| +000003c0 5c 3d 3b 75 29 cc a9 09 85 67 89 37 18 91 c0 af |\=;u)....g.7....| +000003d0 28 d2 0c c9 8b 05 94 04 3a 68 38 f0 c3 db 95 89 |(.......:h8.....| +000003e0 c8 28 fc 07 4b 49 7d b6 25 36 05 53 96 e0 d9 35 |.(..KI}.%6.S...5| +000003f0 e5 7c |.|| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 02 11 ce 65 5f 9d 1a |............e_..| -00000010 c6 5f 48 ea da 02 77 1d 79 b2 82 1a da c4 75 aa |._H...w.y.....u.| -00000020 11 af ae 1f e4 7e d7 6f ed 75 48 56 de c8 36 05 |.....~.o.uHV..6.| -00000030 6a 97 5e 49 49 55 25 6f ef 3e ed 40 3f 91 9a ae |j.^IIU%o.>.@?...| -00000040 f4 a1 d3 02 d3 15 60 23 1b 7a 80 ef ef 60 bb 62 |......`#.z...`.b| -00000050 a3 8d 6b 24 1a 11 7d 8e 00 76 54 69 f1 b5 df 77 |..k$..}..vTi...w| -00000060 c0 3a a3 8d 9d a3 56 e7 4d 2d 68 fe 38 49 6d 42 |.:....V.M-h.8ImB| -00000070 3d 2c 69 fd 8c 53 44 af 13 8b 1d cb dc 04 16 6e |=,i..SD........n| -00000080 5a ab 0a 00 19 cf a0 8a ee bd 71 24 68 ee 18 2a |Z.........q$h..*| -00000090 ec 04 fe 0f 12 15 8e 09 e0 87 de 4e c4 2a a1 a5 |...........N.*..| -000000a0 6d be 79 6e 25 15 11 64 8c 35 71 97 fa a4 43 e2 |m.yn%..d.5q...C.| -000000b0 dd cd a1 da b3 75 5d d5 36 fb b4 6b 12 30 a7 f6 |.....u].6..k.0..| -000000c0 d7 7c 72 e1 f8 6a 8b 3e 38 13 9c da ee 07 3d 6a |.|r..j.>8.....=j| -000000d0 f5 1b 26 73 ff 24 03 1f ea dc f3 ed 6b c2 0d fe |..&s.$......k...| -000000e0 3e 03 c4 22 93 c9 9b fe 22 5c 1e fb 07 2b 1b 7f |>.."...."\...+..| -000000f0 34 ff c6 1b 24 32 4b b1 ee 4c 0b 08 b6 3b 1e aa |4...$2K..L...;..| -00000100 49 f3 04 b7 9a 42 e5 42 5a df a2 92 d3 2f 62 54 |I....B.BZ..../bT| -00000110 e1 21 08 ee ce 64 80 48 d3 6a 15 67 8c 5e d1 ac |.!...d.H.j.g.^..| -00000120 a2 64 f9 10 67 2c 27 7e 10 11 d7 09 13 2f 61 a7 |.d..g,'~...../a.| -00000130 d7 9d 2a 18 0f a8 93 c6 fc 75 5c 31 68 42 22 e6 |..*......u\1hB".| -00000140 5c e8 4d 7d 82 73 ba 97 5c d7 6a a2 14 37 85 93 |\.M}.s..\.j..7..| -00000150 48 a7 50 9c fc 66 7b 82 a8 b6 99 0f 8c 9e 40 b5 |H.P..f{.......@.| -00000160 e4 4f 98 01 db 56 03 44 f9 9f 52 a3 33 ac 77 2a |.O...V.D..R.3.w*| -00000170 b6 0a de d5 68 a5 df 67 41 8d 4c 53 9d c4 8d b7 |....h..gA.LS....| -00000180 2e 3d 1f 93 1c 23 e3 81 76 5a 99 7c 90 60 d8 4d |.=...#..vZ.|.`.M| -00000190 e4 a5 00 7d f9 2c c5 19 bc 3c a3 73 c3 83 ff 31 |...}.,...<.s...1| -000001a0 6a 67 88 32 d3 90 7f ab 20 19 1f 55 72 e4 08 bc |jg.2.... ..Ur...| -000001b0 c4 d6 24 e6 00 2d 85 be d4 9b 2c e5 7b ee 26 6b |..$..-....,.{.&k| -000001c0 49 ed 94 3d d6 ee fd 9d da 39 be 02 23 aa b9 78 |I..=.....9..#..x| -000001d0 f2 41 97 0a d9 66 15 1e e1 a2 49 f3 09 f0 25 91 |.A...f....I...%.| -000001e0 8a ea f5 38 87 ea 66 ae dc d2 04 d1 02 92 ab 6c |...8..f........l| -000001f0 a4 1a cc 1b ba 48 d5 8e 27 c4 c5 34 08 8f c2 c8 |.....H..'..4....| -00000200 e1 e6 a8 98 48 9c 43 6c f1 34 ba c0 ff 8e 22 14 |....H.Cl.4....".| -00000210 f7 f9 93 38 96 1e 73 57 28 5b 25 3e 17 03 03 00 |...8..sW([%>....| -00000220 99 c7 8d 1d 62 23 f3 c1 31 3d 45 bc d5 59 ff 47 |....b#..1=E..Y.G| -00000230 8e 34 3d 1d 06 cc e0 05 ea 38 87 f0 fd c3 84 53 |.4=......8.....S| -00000240 47 6b fb 7b 9b c2 a4 f2 1f e0 61 ab 17 32 d0 57 |Gk.{......a..2.W| -00000250 34 dd fb 42 9b ad 4c d7 20 ff b1 58 34 e0 0c b1 |4..B..L. ..X4...| -00000260 44 0c cf d3 05 be 3b 8e a2 d5 39 44 c8 22 64 ad |D.....;...9D."d.| -00000270 61 80 df 5d fd 40 0e c0 c2 41 4f a7 e5 4f b3 7f |a..].@...AO..O..| -00000280 0b db d6 ac fe ba c0 8b 24 8e e8 b2 d6 93 3d 12 |........$.....=.| -00000290 75 41 85 1d b5 4a e2 e0 f8 a1 23 8f 13 24 c6 b6 |uA...J....#..$..| -000002a0 e5 db 06 3f d8 d5 2f b5 e5 24 59 76 53 dd aa 0a |...?../..$YvS...| -000002b0 26 ba 72 23 63 ac 4d 5c 92 13 17 03 03 00 35 47 |&.r#c.M\......5G| -000002c0 59 18 68 11 0a 9a 0b 66 d3 c0 26 72 da 51 0e 00 |Y.h....f..&r.Q..| -000002d0 b0 78 8b 6a ef df 75 94 94 b0 aa 9b 77 e3 9c d8 |.x.j..u.....w...| -000002e0 23 9d 74 ce 85 55 c0 30 4c 96 5b 59 7a f6 03 2e |#.t..U.0L.[Yz...| -000002f0 d8 9c 0e 11 17 03 03 00 17 74 ed 13 0b 6a 15 18 |.........t...j..| -00000300 5e d4 5e 8a c6 e6 5c 0b 3c d0 1b 3d 68 86 2a 07 |^.^...\.<..=h.*.| -00000310 17 03 03 00 13 6f e2 fe a0 b8 95 d4 aa fd 11 2b |.....o.........+| -00000320 e8 6d 42 28 d1 ca 1c 5e |.mB(...^| +00000000 14 03 03 00 01 01 17 03 03 02 11 6a 55 c4 ff 7a |...........jU..z| +00000010 5b c4 b7 cb 8d ad ae 53 53 3d 41 3a fc 16 44 fd |[......SS=A:..D.| +00000020 c8 5f 39 c3 5e 6b ee 7d ea 88 9c a9 78 f9 dc 51 |._9.^k.}....x..Q| +00000030 b2 90 68 7d ae 2c b7 90 6e 79 cf f4 97 50 95 87 |..h}.,..ny...P..| +00000040 f1 f6 2c 14 bc 2b a3 68 0d e6 c8 66 2f 3b 89 72 |..,..+.h...f/;.r| +00000050 67 4d d8 e9 8d 6a 89 2a f9 e4 c1 b5 c0 92 16 25 |gM...j.*.......%| +00000060 61 a6 98 ec b6 6b 52 8b a5 80 5a 9e 6d 03 ad 42 |a....kR...Z.m..B| +00000070 a9 46 2f d8 e5 67 c9 8d 89 f7 34 93 82 7c a3 bb |.F/..g....4..|..| +00000080 48 62 06 90 5c 5a aa fd 7c 71 88 24 22 f9 6a 2c |Hb..\Z..|q.$".j,| +00000090 d1 d9 7e 0a 4c 39 11 e8 c0 17 1d 83 64 f2 2b c6 |..~.L9......d.+.| +000000a0 c0 81 8c 6a 39 a9 09 aa 1e 58 eb 30 88 59 4d f2 |...j9....X.0.YM.| +000000b0 d2 64 9f 4c 90 29 c0 66 94 e3 df 12 9c 75 33 24 |.d.L.).f.....u3$| +000000c0 fb 14 bc 70 e1 b5 de 54 28 b0 3f 01 2c 2e 5f 35 |...p...T(.?.,._5| +000000d0 e3 01 59 2a 3f ce ca 11 bb 29 97 03 f6 f4 30 b9 |..Y*?....)....0.| +000000e0 66 db 3c f7 06 41 7b e8 f8 af 3e 03 65 2f 5f 88 |f.<..A{...>.e/_.| +000000f0 fd 30 45 7a c9 b4 9f bf 03 eb c9 dd 06 ac 82 06 |.0Ez............| +00000100 e8 81 8e ea 29 45 78 5c 0f 8e 21 8a fb 0b 95 c1 |....)Ex\..!.....| +00000110 63 e9 18 c1 9a a4 c6 7d 56 4b 9a de 96 dd 37 54 |c......}VK....7T| +00000120 92 ef 71 42 a8 66 e7 df e7 ea ec 4e 3c b3 8e 7d |..qB.f.....N<..}| +00000130 ed 92 da 86 e5 fa 51 f8 e4 b0 09 f3 06 4d 38 f1 |......Q......M8.| +00000140 d5 5f d2 72 1e 5f c3 1e 1d fd 96 70 e7 9c ae ea |._.r._.....p....| +00000150 62 ce e4 a9 31 34 47 bc f0 9f 1c c7 b6 66 f0 70 |b...14G......f.p| +00000160 7a e1 c5 a9 76 64 d4 25 0f 56 cd 36 17 67 bd 4d |z...vd.%.V.6.g.M| +00000170 c7 78 d8 23 46 4b ac 46 34 1a d2 2d c5 e6 67 55 |.x.#FK.F4..-..gU| +00000180 11 ec 8c f0 67 84 bf 89 ce 3c 71 4e 3a ab ff 22 |....g....<qN:.."| +00000190 59 23 00 54 4b b6 9e c4 01 a1 9f e1 46 a6 a6 f3 |Y#.TK.......F...| +000001a0 24 58 0c b4 6e 85 4c c1 8a d6 f8 02 c9 54 fb 85 |$X..n.L......T..| +000001b0 c7 63 9b 47 28 10 a0 2d b6 c2 83 16 71 ae a7 c2 |.c.G(..-....q...| +000001c0 e0 dc 8b 6d 57 e0 4b a2 a8 5d 4d 8b ed 72 31 d6 |...mW.K..]M..r1.| +000001d0 54 33 78 df bb 4a f9 58 9f 8c 2b 11 36 29 a0 f0 |T3x..J.X..+.6)..| +000001e0 8a 95 20 d8 f1 8c 08 e1 54 0a 81 79 33 20 23 de |.. .....T..y3 #.| +000001f0 34 c8 2b 45 3a 59 c5 78 39 65 ea 70 e2 fe 59 4c |4.+E:Y.x9e.p..YL| +00000200 ed 7f 07 07 25 a7 ff fa c9 c3 1f 33 55 c4 16 bb |....%......3U...| +00000210 c9 b9 e0 2e ff 94 7c de 84 30 60 d6 17 03 03 00 |......|..0`.....| +00000220 99 53 44 d2 12 38 c4 a7 7e f5 f5 67 b3 79 cf 8a |.SD..8..~..g.y..| +00000230 34 0f 5d 49 0f bb 5f 30 c8 36 13 61 8d b5 b1 b0 |4.]I.._0.6.a....| +00000240 dc 73 2f 1a 51 2f d4 8e 25 71 e1 46 af 11 96 19 |.s/.Q/..%q.F....| +00000250 f7 fe 09 d9 6e 70 d5 fc b9 5b 1c ae ed 06 37 af |....np...[....7.| +00000260 a1 bf 35 c6 6b 30 33 a2 c4 f6 c8 d4 73 34 73 8e |..5.k03.....s4s.| +00000270 69 08 be 91 2c 8d 01 52 30 14 b3 d3 a0 7d 8a 9d |i...,..R0....}..| +00000280 e9 af b2 77 64 eb 16 c1 8e 19 72 ad 4a fd d4 c9 |...wd.....r.J...| +00000290 08 d0 54 6c f1 06 8c 70 2f e6 ef 23 23 67 96 db |..Tl...p/..##g..| +000002a0 5f aa 81 6c 41 17 6b f4 30 ce 00 d6 a2 d8 28 f8 |_..lA.k.0.....(.| +000002b0 be 9f 04 94 fa e3 fa 76 d0 30 17 03 03 00 35 9b |.......v.0....5.| +000002c0 43 c4 8f dc b7 a1 44 4e 00 66 0a 95 a6 d7 46 79 |C.....DN.f....Fy| +000002d0 30 2d 57 51 4e 21 a7 ed 43 e7 22 2d eb 07 9b 7d |0-WQN!..C."-...}| +000002e0 ea a4 ff 14 5d 97 1f d5 e8 f1 3d 8d e3 13 b6 79 |....].....=....y| +000002f0 36 ce 83 e8 17 03 03 00 17 d5 98 a6 a3 b7 40 2b |6.............@+| +00000300 26 87 2f 4f 64 95 f1 2d e0 7b e3 98 c2 81 dc 7b |&./Od..-.{.....{| +00000310 17 03 03 00 13 5b ab 65 e4 b1 d0 bd e9 c6 b2 3a |.....[.e.......:| +00000320 4b 66 ce eb 25 0c bc 7d |Kf..%..}| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-RSAPSS b/libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-RSAPSS index 9488dd6..2367a39 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-RSAPSS +++ b/libgo/go/crypto/tls/testdata/Client-TLSv13-ClientCert-RSA-RSAPSS @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,128 +16,128 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 6d 36 ae 02 a9 |....z...v..m6...| -00000010 74 ad e5 4d 55 b6 4a 70 c6 f5 cf d5 68 d9 2a 5f |t..MU.Jp....h.*_| -00000020 9b 4b 23 ce 38 9b f3 da 44 72 7d 20 00 00 00 00 |.K#.8...Dr} ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 a9 f1 13 c3 3c |....z...v......<| +00000010 1c dd c9 3a a1 ad 92 92 f1 f4 16 39 be 14 64 9c |...:.......9..d.| +00000020 66 d8 28 cd b7 bb 40 43 ec f4 67 20 00 00 00 00 |f.(...@C..g ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 01 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 ba |..+.....3.$... .| -00000060 2a 76 cb fb 6c 6b bb 30 fb ef 87 6f e5 06 5c 6f |*v..lk.0...o..\o| -00000070 78 a7 44 41 93 c0 33 89 be 32 8c 0f fa 5c 43 14 |x.DA..3..2...\C.| -00000080 03 03 00 01 01 17 03 03 00 17 ac 3e 8a 31 22 16 |...........>.1".| -00000090 d3 69 bf 1d b5 2e 18 23 b3 21 00 17 23 a4 3f 9a |.i.....#.!..#.?.| -000000a0 0b 17 03 03 00 20 aa f0 51 64 b5 44 f0 28 ab 56 |..... ..Qd.D.(.V| -000000b0 da 34 2d 62 77 4d 88 07 b6 82 ad 64 df e6 59 c9 |.4-bwM.....d..Y.| -000000c0 91 e5 f8 f2 67 88 17 03 03 02 7a cf 2d 71 db 3f |....g.....z.-q.?| -000000d0 05 45 b8 68 18 1c b9 66 b6 00 f8 dc 9d ae e5 d2 |.E.h...f........| -000000e0 a3 a8 02 5f ac e4 95 a6 fc 96 78 7b fd 0a 21 62 |..._......x{..!b| -000000f0 ff 7c 15 2c fb f1 21 15 1e 8d 9e f9 71 62 43 e4 |.|.,..!.....qbC.| -00000100 c9 69 e4 fe 87 f0 9d 9e aa a4 5c d8 4e ae 3c 38 |.i........\.N.<8| -00000110 e5 76 21 7b 03 a8 70 6f e8 96 39 34 e7 3c b9 51 |.v!{..po..94.<.Q| -00000120 b4 ef ce 7d 0b 1e 57 7d 62 de 47 6a 0a b0 97 6d |...}..W}b.Gj...m| -00000130 49 fe ae 6f c9 d6 e4 4a 54 60 3d 55 53 06 aa 28 |I..o...JT`=US..(| -00000140 7a 3e 7b e0 d1 8a 60 45 87 81 bf fc 98 13 1e de |z>{...`E........| -00000150 7a 90 73 81 13 91 3a c4 da 71 74 e0 1d d5 30 55 |z.s...:..qt...0U| -00000160 46 6a 48 c2 0c 18 91 a3 79 8e c2 b9 5b 24 88 76 |FjH.....y...[$.v| -00000170 5f e6 8f 24 91 95 5b 0d 38 39 5b a4 f6 0e 1a b8 |_..$..[.89[.....| -00000180 e8 2b 0d ac a8 56 10 23 54 a5 78 c9 2a cb ed 24 |.+...V.#T.x.*..$| -00000190 58 16 1a 2f 1c b7 72 fc da ab 56 f6 27 d1 98 39 |X../..r...V.'..9| -000001a0 1f f9 dd e0 1f 1f 23 1a ff 6b af e1 17 9d ec 35 |......#..k.....5| -000001b0 de 0b 4d a4 46 5a fd 07 56 ce 72 19 76 dc 0c 06 |..M.FZ..V.r.v...| -000001c0 99 38 ce 58 3b 9f 13 9a d5 b7 d6 08 a6 05 4d e1 |.8.X;.........M.| -000001d0 75 da 59 4d ab d9 28 e8 af c4 50 f0 b1 49 f8 fd |u.YM..(...P..I..| -000001e0 c9 11 b8 01 70 bb 49 e2 0f 26 1b cb ee c2 7b bd |....p.I..&....{.| -000001f0 2f 72 78 be a1 67 1d 0c d0 bb 4e e7 40 b3 bd 8c |/rx..g....N.@...| -00000200 e2 f4 4f b2 c5 4c 82 49 51 00 44 17 c6 82 72 f5 |..O..L.IQ.D...r.| -00000210 cd 55 c1 43 28 52 85 2b 5d 91 33 9c 15 34 6e ae |.U.C(R.+].3..4n.| -00000220 77 4e 08 0c 9c d2 ae 7f e8 83 af 60 96 10 ae dc |wN.........`....| -00000230 58 6a 3b ae 15 e5 9c a8 25 f3 69 71 f7 94 9c 75 |Xj;.....%.iq...u| -00000240 e0 b5 05 16 ae ce f4 23 20 30 aa 74 a3 63 68 76 |.......# 0.t.chv| -00000250 f6 ec 64 e1 3d f6 0e b6 c4 7d a8 08 44 a9 96 1d |..d.=....}..D...| -00000260 7d c8 22 a8 df 04 2c ad 65 f1 4c 99 7d a1 cb bd |}."...,.e.L.}...| -00000270 b7 d4 d7 b5 ee 88 bd 15 2e 75 76 e2 72 bb 7d e6 |.........uv.r.}.| -00000280 5b eb fc f7 96 96 f0 3c aa b6 a8 58 92 e9 29 f6 |[......<...X..).| -00000290 40 bf 8e 14 23 7c 45 da e9 17 4b 32 16 11 ec 74 |@...#|E...K2...t| -000002a0 78 d5 8c 5a 06 46 e4 dc 90 b9 44 8e d6 8a 4e 43 |x..Z.F....D...NC| -000002b0 7f f9 60 9e a1 46 fa 16 88 ab 3c f1 1e d0 2e 00 |..`..F....<.....| -000002c0 5d 01 e6 a7 b1 27 f7 40 26 17 f3 da fb cd 06 d1 |]....'.@&.......| -000002d0 4e 27 75 9a 6f 0b 63 82 9c 40 07 4c 6e 0d d8 4b |N'u.o.c..@.Ln..K| -000002e0 f1 e6 d5 1c 41 55 72 b5 43 24 53 1e 0e a4 08 d7 |....AUr.C$S.....| -000002f0 44 93 00 c9 8b 49 ba 7a 32 0c d8 e6 46 87 5d 62 |D....I.z2...F.]b| -00000300 9d 4a 11 04 67 21 19 42 50 ad ad ab dd 62 0f f7 |.J..g!.BP....b..| -00000310 0f 57 78 82 71 f6 09 9f 41 bc 8e 34 24 7c b5 d2 |.Wx.q...A..4$|..| -00000320 5d 0c 18 fb d8 f6 62 dc 57 6a 78 2c 21 35 d8 eb |].....b.Wjx,!5..| -00000330 bb f8 7e 01 63 50 c1 98 88 a4 b5 63 1e c0 68 3c |..~.cP.....c..h<| -00000340 41 3c b8 6e 48 17 03 03 00 99 b6 09 37 a6 c2 d9 |A<.nH.......7...| -00000350 5f 39 69 e1 0b ca 40 d8 31 5b 4b 4f c1 33 bf 1f |_9i...@.1[KO.3..| -00000360 db c2 8c 9c d2 14 26 96 4e aa b2 63 30 40 fa 49 |......&.N..c0@.I| -00000370 fb 2d 66 59 70 cb c7 f8 fe 59 19 8b eb d5 5c 6c |.-fYp....Y....\l| -00000380 5c a0 c9 ba e6 4d d9 c3 e0 fe 00 c4 fb ab 8a f1 |\....M..........| -00000390 2b ab 53 86 a7 86 57 01 b8 ae c4 a6 12 6b 7d f8 |+.S...W......k}.| -000003a0 ea 2d df 37 04 01 eb 14 f4 9a d0 e7 67 46 ec 9f |.-.7........gF..| -000003b0 35 f8 d4 2e c6 95 91 10 0e dc 01 60 9a d6 f8 d8 |5..........`....| -000003c0 9e c1 fd f8 2e e2 51 8a e9 2f c3 4a 4f 01 31 52 |......Q../.JO.1R| -000003d0 af cb 4b 52 96 4c 90 57 83 1f 11 97 d6 d6 16 74 |..KR.L.W.......t| -000003e0 77 f8 c4 17 03 03 00 35 b0 61 57 8f 52 7e 93 b1 |w......5.aW.R~..| -000003f0 f0 90 a1 23 09 6e 11 ff a5 6c 38 f3 31 11 be 03 |...#.n...l8.1...| -00000400 ad 59 65 57 1b 60 2b fc 41 98 e0 79 6d 14 26 c8 |.YeW.`+.A..ym.&.| -00000410 fb d6 5f 00 e0 cc 70 46 a3 81 e4 3c ff |.._...pF...<.| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 ff |..+.....3.$... .| +00000060 53 ac b3 b0 48 47 d0 1e b1 70 eb dd 02 e5 e8 07 |S...HG...p......| +00000070 ce c7 e0 af d7 e0 46 c7 ff f5 97 30 e5 80 5b 14 |......F....0..[.| +00000080 03 03 00 01 01 17 03 03 00 17 0b 12 ef 6d ea 5e |.............m.^| +00000090 71 41 83 d6 35 9f 39 2c f0 ab 01 e9 03 54 c6 9e |qA..5.9,.....T..| +000000a0 37 17 03 03 00 20 15 7a 35 f4 a6 6e 65 89 10 ae |7.... .z5..ne...| +000000b0 18 31 c0 0c 15 1c b8 c5 5d f3 54 0c 98 32 a4 5e |.1......].T..2.^| +000000c0 91 f7 03 8a 80 b9 17 03 03 02 7a fa 93 7f c6 d1 |..........z.....| +000000d0 2f 7e 2d d6 1b b7 ff fd 96 6e a1 f7 0e 98 dc 77 |/~-......n.....w| +000000e0 cc 6a 4e 91 3d c1 ad 4b 5c 28 ee ea a7 0a ce 8f |.jN.=..K\(......| +000000f0 51 dd 89 fd 5a 81 6d 21 d6 0d 35 70 84 73 8c fa |Q...Z.m!..5p.s..| +00000100 2e 7a e0 af ab 79 79 aa 67 2b 80 a8 b3 a8 fb 0d |.z...yy.g+......| +00000110 eb 87 66 d5 be 33 0b f0 80 b8 5e 21 84 be 25 fe |..f..3....^!..%.| +00000120 47 98 5a 26 5d c3 96 2e c5 b8 da 9f a6 d4 ca bb |G.Z&]...........| +00000130 de 7f 2c 0a 28 a8 f3 41 bc a2 2e 70 f2 b3 6f a3 |..,.(..A...p..o.| +00000140 10 0e 1f 11 af 11 50 2b 22 84 97 d7 80 f5 62 77 |......P+".....bw| +00000150 a6 94 47 22 ef 24 c6 0e dc 5c f5 40 08 f7 21 78 |..G".$...\.@..!x| +00000160 ae 11 f3 d8 a5 d8 20 ac 90 73 d7 a2 e3 f0 08 57 |...... ..s.....W| +00000170 fc 74 70 66 fd 3d 49 c7 99 37 98 5e b1 1c c4 38 |.tpf.=I..7.^...8| +00000180 64 09 e6 70 b6 8b 00 72 2d 5b b4 70 39 d6 e9 d5 |d..p...r-[.p9...| +00000190 dc cd 8e 01 eb 5f 34 61 d0 97 62 0b 4f 81 ed 30 |....._4a..b.O..0| +000001a0 64 56 f2 6e 31 5e 24 e8 56 2b d6 31 54 c4 48 47 |dV.n1^$.V+.1T.HG| +000001b0 16 00 a7 65 c1 fa ea 12 30 78 41 e7 30 2d 71 cf |...e....0xA.0-q.| +000001c0 b0 e9 be e4 a2 33 38 87 2d 37 14 2d 03 cf ae 87 |.....38.-7.-....| +000001d0 9a 09 f2 ed f3 44 66 c3 8a 56 8e e4 c4 aa e9 f7 |.....Df..V......| +000001e0 cd 75 52 1b d9 ed 66 04 13 dd dd cf 0f 44 cd 18 |.uR...f......D..| +000001f0 68 c5 2c 4c f9 e3 d3 02 12 78 38 5c f6 96 d7 80 |h.,L.....x8\....| +00000200 f0 83 03 fe 7a e0 35 7e a3 ad 99 52 ec fc ee 74 |....z.5~...R...t| +00000210 f5 09 0f ca 69 f0 fb d0 40 90 1b 46 9e 2d 62 c9 |....i...@..F.-b.| +00000220 0f 59 b2 cc a0 4a 9b 84 14 3a 1b 51 fc e7 e8 a1 |.Y...J...:.Q....| +00000230 26 fd 20 8c 88 6f 87 11 ae 97 76 f8 4b cc 67 1a |&. ..o....v.K.g.| +00000240 3e 58 65 77 77 82 06 c0 d4 41 4e 66 d2 5a 83 b1 |>Xeww....ANf.Z..| +00000250 ee 19 5d 7b 99 34 d3 2f 6c bd 30 a3 8c 75 89 ec |..]{.4./l.0..u..| +00000260 cb 90 8b 89 05 b8 e4 6e 3b 60 5d 0e 19 8f d6 c7 |.......n;`].....| +00000270 86 f0 a9 2b c7 12 4a 4c d8 a5 e8 64 49 1d 49 99 |...+..JL...dI.I.| +00000280 a7 80 01 f0 77 57 4a 78 3c ac 38 40 bb d2 10 24 |....wWJx<.8@...$| +00000290 9d e2 29 b2 1e 4b 50 66 64 07 79 80 c7 81 9d e2 |..)..KPfd.y.....| +000002a0 f5 a9 10 9a 8d 3b de 0e 21 85 13 ac 26 30 f9 e4 |.....;..!...&0..| +000002b0 a6 f9 8f e0 3c c1 69 7e 11 4c d1 a8 4e 88 30 fc |....<.i~.L..N.0.| +000002c0 52 6e b0 4f b6 7e 15 9e a5 8a 46 ca 1f ac 8e 2a |Rn.O.~....F....*| +000002d0 07 34 d7 c2 14 c6 c1 ed a1 f9 1e 59 b4 b4 86 3e |.4.........Y...>| +000002e0 d3 d0 78 a6 07 62 d3 88 80 54 a8 2a e9 38 2e 58 |..x..b...T.*.8.X| +000002f0 43 94 cc ed f0 46 f6 cc 4b 7a b8 f5 a2 d6 a8 36 |C....F..Kz.....6| +00000300 e2 8e 11 fb e7 21 19 c5 fa c9 90 98 72 43 88 ac |.....!......rC..| +00000310 c0 56 84 9e cd b7 e5 26 d6 49 19 88 a5 12 ac 49 |.V.....&.I.....I| +00000320 5d 77 37 2a ff 38 5a 7a 5b c8 74 5d 74 fc 22 7f |]w7*.8Zz[.t]t.".| +00000330 46 97 2b 34 32 fb 83 65 75 b6 8b 5c 8a b1 d4 a2 |F.+42..eu..\....| +00000340 14 7f 46 0d 63 17 03 03 00 99 c7 79 bb 4f 88 a0 |..F.c......y.O..| +00000350 78 be 04 ca 39 1f 1f a8 82 59 b5 dd 96 93 0d c4 |x...9....Y......| +00000360 30 f4 22 4c e2 52 51 d4 33 b8 35 7b ed 01 19 25 |0."L.RQ.3.5{...%| +00000370 b5 31 36 25 23 a2 51 d9 7a a9 00 72 05 34 81 62 |.16%#.Q.z..r.4.b| +00000380 d0 df 8b 3a 65 98 4e 87 e2 29 9b 44 77 8c dd c9 |...:e.N..).Dw...| +00000390 4c a5 de 14 97 e0 f1 2c e8 5d 0e 8f d0 fd f6 77 |L......,.].....w| +000003a0 c1 1f ac 79 4d 32 19 09 98 a8 f0 2f 3e d5 7e f7 |...yM2...../>.~.| +000003b0 aa c1 f0 36 b1 8e c7 0b ce 09 00 ac 28 64 c0 33 |...6........(d.3| +000003c0 58 cc 48 3a 15 a4 77 24 50 67 f2 39 53 4d 63 23 |X.H:..w$Pg.9SMc#| +000003d0 48 74 bd 0a c8 02 17 be e4 64 af 6e 02 a9 22 92 |Ht.......d.n..".| +000003e0 65 04 c6 17 03 03 00 35 e0 4e 15 4b 9d 53 57 c6 |e......5.N.K.SW.| +000003f0 97 b4 9d 1a 03 39 26 b9 ca 5b 04 50 af db 52 99 |.....9&..[.P..R.| +00000400 d9 13 40 6a 89 23 99 42 9a 91 1d d1 6c 07 a0 aa |..@j.#.B....l...| +00000410 05 6e 60 0b fd e7 de 32 c3 97 18 0d 9b |.n`....2.....| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 02 7a 22 a3 3d 18 f8 |..........z".=..| -00000010 a2 c7 8e 62 c3 07 99 b4 e6 bd 94 79 12 82 e9 e0 |...b.......y....| -00000020 96 ff 5f c3 ec 34 02 2f 8d 95 2f 40 80 99 19 a3 |.._..4./../@....| -00000030 bd 64 fd e4 0e b3 81 ad 4c 2e d9 72 d2 a3 bd 00 |.d......L..r....| -00000040 81 42 78 5d f3 70 c3 78 0b fa cd b8 96 17 5e e7 |.Bx].p.x......^.| -00000050 6e 03 b8 c6 ab 2b 2e 63 45 c7 b1 c9 98 71 c9 1d |n....+.cE....q..| -00000060 bb 7b 6e 6d c7 d5 90 b8 b2 4e 62 1a 8f cf 7d 99 |.{nm.....Nb...}.| -00000070 52 3d 70 40 0f 0f 96 1c ee a7 ff 29 2a 53 de d4 |R=p@.......)*S..| -00000080 34 f9 d9 b2 33 2c 69 5e 2d f2 a7 62 dd ec 77 b1 |4...3,i^-..b..w.| -00000090 6c 0f 61 86 8a bc 11 1f 91 ad f4 94 de 96 dd ef |l.a.............| -000000a0 d8 be 5e 45 50 fe af 1a 03 54 20 f6 05 8e a3 b0 |..^EP....T .....| -000000b0 f7 31 93 f3 78 59 4d 54 50 99 a5 a1 53 81 1b 5d |.1..xYMTP...S..]| -000000c0 6d ea 32 e9 52 ab 83 d6 18 3f 2f 43 cd 64 ac 3f |m.2.R....?/C.d.?| -000000d0 11 6c 91 0d fa 86 f8 a5 12 eb 41 ac 24 2d 79 5b |.l........A.$-y[| -000000e0 ee 8e 02 46 f0 37 0a b1 19 c7 97 ed 97 d1 11 18 |...F.7..........| -000000f0 df 80 8f f3 d7 61 a4 fe 6c ec b0 80 4e bc e4 52 |.....a..l...N..R| -00000100 10 2f b1 6f 3f d4 39 08 81 f6 01 4b b4 d4 d5 20 |./.o?.9....K... | -00000110 6b a1 be e6 cf c7 0e 95 e9 d7 00 07 63 25 1b 64 |k...........c%.d| -00000120 4b b7 c4 79 29 84 45 45 5d 0d fe 72 2a 7e c6 bf |K..y).EE]..r*~..| -00000130 5a 98 ec e2 16 26 82 57 eb a6 dc ff 73 b6 e8 4c |Z....&.W....s..L| -00000140 87 52 e5 0a c1 6a 6f 02 69 17 17 ea e0 1c c1 07 |.R...jo.i.......| -00000150 b4 f4 78 a7 99 39 8b 63 61 c2 7e 99 f4 64 16 d6 |..x..9.ca.~..d..| -00000160 0a 84 9a 0f d4 f4 bd 4d d4 4f 16 ec 19 30 a7 34 |.......M.O...0.4| -00000170 f9 b9 60 10 39 25 ee 9d bd 99 37 52 e6 32 a1 c9 |..`.9%....7R.2..| -00000180 68 9b a2 4e 16 91 0e 54 54 d5 c5 77 bb 01 ba af |h..N...TT..w....| -00000190 97 be ea 09 85 91 69 84 4f 2c 04 f0 38 50 93 49 |......i.O,..8P.I| -000001a0 e7 41 cb c1 d6 b6 77 59 09 7c 1e 0a 58 93 1e b4 |.A....wY.|..X...| -000001b0 cf ed 32 85 b0 cd 6f 86 c7 94 8c 30 9d 83 a2 a0 |..2...o....0....| -000001c0 4a de ad 8c b9 d8 58 d3 8c 34 6b 12 54 f1 28 66 |J.....X..4k.T.(f| -000001d0 ea 55 d9 95 d0 b6 b3 aa 68 c3 31 e1 8f 1b f8 43 |.U......h.1....C| -000001e0 51 b9 06 fc 53 69 9b 1c e6 2c f8 b7 f0 47 4a 5a |Q...Si...,...GJZ| -000001f0 82 ca 27 df 0f 3d f8 79 90 8d c2 bd 27 85 74 6b |..'..=.y....'.tk| -00000200 9e 8b eb 74 a8 28 ba 6a 25 16 01 2c 56 3b c0 fa |...t.(.j%..,V;..| -00000210 91 ac af a7 c5 39 8d 2c b1 f3 a2 c9 a5 72 c6 ff |.....9.,.....r..| -00000220 49 a0 78 14 5c 8c d2 71 de b9 4f 55 3a ca b6 a5 |I.x.\..q..OU:...| -00000230 df ce bb f7 c2 d5 af 2c c0 97 08 82 cc b4 02 26 |.......,.......&| -00000240 c3 0c 99 39 4a df 6c d6 59 14 c4 d6 04 9d a4 92 |...9J.l.Y.......| -00000250 d2 53 42 16 56 99 5f c2 82 a0 a8 5a 92 53 e6 b1 |.SB.V._....Z.S..| -00000260 cd fc bc 9a b9 55 0b ae 2c 50 ce a3 bf d2 7d d2 |.....U..,P....}.| -00000270 2b 58 ba 87 65 33 09 cf 74 51 0f 4b 4f a9 53 0d |+X..e3..tQ.KO.S.| -00000280 fa 60 1e ba e6 17 03 03 00 99 aa 43 d9 e2 e4 91 |.`.........C....| -00000290 cf 65 fa 35 0e b0 21 51 9d c4 33 f5 7c 09 ff e5 |.e.5..!Q..3.|...| -000002a0 db fd 6e 96 6d 13 7c 4c ec 90 72 bd 54 6a 3f d8 |..n.m.|L..r.Tj?.| -000002b0 1a a3 e2 a2 01 6b d6 50 a0 b1 d5 67 34 44 42 30 |.....k.P...g4DB0| -000002c0 97 2e 82 07 46 04 56 0a 43 4b 9d 8c 81 64 bb 0b |....F.V.CK...d..| -000002d0 21 62 ea 23 0b 1c a0 c4 b2 cc 2f 51 b5 a2 9a a3 |!b.#....../Q....| -000002e0 37 d3 0c 57 80 85 77 3b 8d 17 f1 a9 d5 ae 72 f9 |7..W..w;......r.| -000002f0 cd 8c c4 2c fb c7 e0 f0 3a 5c d5 6a f7 8f 7e 53 |...,....:\.j..~S| -00000300 c1 d0 7a b0 8d c9 b3 17 7c 99 df 54 d6 43 13 d5 |..z.....|..T.C..| -00000310 78 9c 34 7e c9 11 4e e7 1c 8c f4 0f 82 89 94 61 |x.4~..N........a| -00000320 80 d2 49 17 03 03 00 35 aa cd 97 5a a2 d3 27 78 |..I....5...Z..'x| -00000330 d4 79 28 a7 57 dc 4f b1 2d b8 bd 3c ae ec e6 be |.y(.W.O.-..<....| -00000340 33 be b9 20 3b 69 22 03 31 34 7a 8d 68 39 c7 d5 |3.. ;i".14z.h9..| -00000350 a1 a0 aa 46 15 94 93 d7 54 41 5b 6b 20 17 03 03 |...F....TA[k ...| -00000360 00 17 f2 60 ff 91 c2 85 55 ed ab 39 6f 5d 0f 22 |...`....U..9o]."| -00000370 45 3e 61 07 14 a3 05 f4 94 17 03 03 00 13 01 ea |E>a.............| -00000380 95 52 29 1c 63 71 3a 2d 73 a7 29 31 2c d0 ce 9f |.R).cq:-s.)1,...| -00000390 2b |+| +00000000 14 03 03 00 01 01 17 03 03 02 7a 94 78 2d 5d 5a |..........z.x-]Z| +00000010 3e 96 7f 19 29 51 99 f3 6e d3 a4 d5 3c 9a 3d d5 |>...)Q..n...<.=.| +00000020 37 bc 3b 71 b3 54 83 d9 5e 9d 64 76 f9 74 7a 24 |7.;q.T..^.dv.tz$| +00000030 e3 cb ea aa 17 f4 44 41 73 71 39 d6 9b d5 a6 a2 |......DAsq9.....| +00000040 6a 1e 1c 02 a1 d5 e3 e8 f5 f7 07 9d 3b ea f8 6d |j...........;..m| +00000050 80 cf 6b 14 71 b8 bd c4 8a 07 49 31 e7 bd d5 91 |..k.q.....I1....| +00000060 ac 80 70 25 5e f4 db 07 ed 36 c2 3a 1d ad 86 6e |..p%^....6.:...n| +00000070 68 1a ca 4f a1 ba c3 2f de 49 01 fa a9 39 a6 51 |h..O.../.I...9.Q| +00000080 3a e6 9f cf 6b 02 4e 1e 70 dd f2 10 c2 62 9b 1f |:...k.N.p....b..| +00000090 83 10 fa 85 52 a8 a7 08 37 9c 92 b0 9c fe 00 78 |....R...7......x| +000000a0 0b a4 7b b5 f9 9f 87 d2 d3 07 72 b2 ab 96 9e 73 |..{.......r....s| +000000b0 55 3c 1e 65 99 89 36 78 7e 42 8f 05 de b6 fb fc |U<.e..6x~B......| +000000c0 1b 34 18 e6 4d 15 6c d1 2f 2c b0 ef 00 e9 07 89 |.4..M.l./,......| +000000d0 ca 91 d9 c1 73 bf 8f a5 a4 7d 7e cc f5 85 fb af |....s....}~.....| +000000e0 57 70 35 63 71 d6 78 57 13 48 27 ba a4 42 22 c2 |Wp5cq.xW.H'..B".| +000000f0 56 f4 ae 38 39 a0 1f 57 44 57 c4 8a 70 90 30 70 |V..89..WDW..p.0p| +00000100 ba 4a 98 29 0f aa e2 33 27 24 ee d9 e9 02 80 68 |.J.)...3'$.....h| +00000110 4c 55 08 fb 3d 25 d6 d4 9d 83 ea 14 99 c2 77 94 |LU..=%........w.| +00000120 f9 70 34 a8 ed 35 e6 4f c2 75 50 63 d5 9d 9a 89 |.p4..5.O.uPc....| +00000130 8f 2e 5b ca 6b b3 ad e7 a2 c6 f7 0c 45 08 b7 f4 |..[.k.......E...| +00000140 58 d3 d5 54 c2 67 f3 76 fb fc 9d fe 42 43 ea 90 |X..T.g.v....BC..| +00000150 2b 29 e7 10 2f d7 9c 04 c4 cc 89 8f a9 36 14 f6 |+)../........6..| +00000160 fc f1 25 6c 90 12 bf c6 cd ad 46 ce 17 3b 26 fb |..%l......F..;&.| +00000170 c6 98 cb 6c f2 2c fd b9 2f 52 3e 56 42 78 0b 92 |...l.,../R>VBx..| +00000180 a5 27 56 18 3d d6 26 3f e4 a1 6f ce c8 f1 f1 7a |.'V.=.&?..o....z| +00000190 1f 84 66 c9 d9 8a 5c 0e 34 80 ba 58 b3 8b 7f f3 |..f...\.4..X....| +000001a0 8a c9 6b c4 99 94 2c b7 e8 e8 9a a5 43 75 f8 e0 |..k...,.....Cu..| +000001b0 29 1f 70 77 c7 4a 9f de ca 92 88 7c 37 12 d9 ef |).pw.J.....|7...| +000001c0 2f 94 de ea d1 d9 69 6a 93 06 36 e0 68 02 53 ae |/.....ij..6.h.S.| +000001d0 0e 00 cd ad d3 10 a7 89 2c 53 a7 03 d9 07 3c e9 |........,S....<.| +000001e0 0b b0 18 2e 03 88 03 5c f4 b2 7e 59 f4 22 8c f7 |.......\..~Y."..| +000001f0 5e d7 c7 ea ac 0f bc f7 3e 3f 75 fd 6d 9c 4c 3c |^.......>?u.m.L<| +00000200 41 8d f5 30 17 20 83 c3 27 83 ce 84 6a e3 75 2b |A..0. ..'...j.u+| +00000210 9d 7d de 2a bf 5a fb e1 2f 80 74 74 f6 09 bc 1f |.}.*.Z../.tt....| +00000220 be f0 59 9e ce a1 62 46 54 a4 9a 25 97 b7 cd 1a |..Y...bFT..%....| +00000230 0a d0 44 f6 ea a4 ed 63 e7 49 9a 4b f4 1a 39 91 |..D....c.I.K..9.| +00000240 e6 34 e1 7b dd e7 53 ab 83 56 57 b2 89 3f 90 1f |.4.{..S..VW..?..| +00000250 98 c4 64 27 b5 f5 f6 57 16 ca d9 0a 33 de 24 c3 |..d'...W....3.$.| +00000260 f3 7c 23 37 94 93 c5 1a 42 da 18 6b 24 dd 37 54 |.|#7....B..k$.7T| +00000270 ae f3 8a 3e 10 42 20 6e 49 23 1a 0f bd 65 7e 45 |...>.B nI#...e~E| +00000280 12 7a 64 9a 30 17 03 03 00 99 af 41 cf 95 21 1f |.zd.0......A..!.| +00000290 34 df 1c c7 a8 b6 ee 31 8d b3 9e 5a 59 8e c4 37 |4......1...ZY..7| +000002a0 79 a4 d8 75 22 da 12 21 e5 de d4 ad 98 17 e2 ae |y..u"..!........| +000002b0 ae 9f f6 e8 29 66 d0 ac b4 08 16 24 40 67 9d d5 |....)f.....$@g..| +000002c0 bf a4 64 91 a1 17 82 c0 e7 77 b6 20 26 4a 70 1d |..d......w. &Jp.| +000002d0 c8 f8 ec 18 b7 c6 3c 81 b9 c6 04 9c 0d 37 a6 39 |......<......7.9| +000002e0 fd 2d 99 d7 ba 41 a4 91 60 f1 1f d2 76 76 aa 47 |.-...A..`...vv.G| +000002f0 89 0a d1 97 0b 91 20 a9 43 c9 ce 2c 84 ba 81 7a |...... .C..,...z| +00000300 39 91 7d 12 75 05 8e 87 b1 3f 80 8d 12 ca 8f 91 |9.}.u....?......| +00000310 23 84 28 11 c3 81 ed 09 05 16 6e 50 57 76 ad 5c |#.(.......nPWv.\| +00000320 c5 92 77 17 03 03 00 35 5a d9 15 29 1f a3 f0 cf |..w....5Z..)....| +00000330 74 c4 1d 0c c3 fa 54 59 1e 54 06 0d 1b ce 07 00 |t.....TY.T......| +00000340 f9 66 3d e1 75 10 cf de cb 7d 0d d6 d1 4d 87 81 |.f=.u....}...M..| +00000350 13 ec 2c 28 13 a5 b3 01 c7 86 3a 84 65 17 03 03 |..,(......:.e...| +00000360 00 17 b4 e4 18 61 62 04 b3 ca 98 36 93 42 a2 be |.....ab....6.B..| +00000370 2c f5 18 11 bd 7d 64 70 bc 17 03 03 00 13 32 65 |,....}dp......2e| +00000380 fa 07 3e 3c ed 9d 85 31 ba 8e 92 ea de 17 59 cd |..><...1......Y.| +00000390 db |.| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv13-ECDSA b/libgo/go/crypto/tls/testdata/Client-TLSv13-ECDSA index 098f3ab..dac9ef7 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv13-ECDSA +++ b/libgo/go/crypto/tls/testdata/Client-TLSv13-ECDSA @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,71 +16,71 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 e8 ec ee 61 3e |....z...v.....a>| -00000010 c1 43 87 6d f1 61 ed d2 41 1f 7d d7 b7 c0 92 fd |.C.m.a..A.}.....| -00000020 34 17 85 7b c7 ff c4 56 dd 90 bd 20 00 00 00 00 |4..{...V... ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 e3 21 e8 24 fb |....z...v...!.$.| +00000010 e8 fe 46 e2 54 a7 db 98 ae a4 b2 fc f8 17 99 b4 |..F.T...........| +00000020 ed 6a aa 9c f9 ce e2 0f f8 88 05 20 00 00 00 00 |.j......... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 01 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 3f |..+.....3.$... ?| -00000060 be 50 e7 f1 b0 30 60 dc 92 50 b8 01 4a d1 3e ff |.P...0`..P..J.>.| -00000070 6e f0 bd e1 17 44 d8 19 1b c6 63 43 e5 c1 58 14 |n....D....cC..X.| -00000080 03 03 00 01 01 17 03 03 00 17 c0 b7 da 01 3e 64 |..............>d| -00000090 6b 57 ba 21 12 79 42 8c 63 1f 45 d1 f2 10 fe 98 |kW.!.yB.c.E.....| -000000a0 b6 17 03 03 02 22 90 87 e6 c3 ba 92 41 a2 96 00 |....."......A...| -000000b0 c7 92 97 ab 4b 80 02 bb 02 83 19 f3 f6 36 d5 23 |....K........6.#| -000000c0 3c c7 bd fb 97 67 86 cb 70 4c 60 9e 6c d4 7a f3 |<....g..pL`.l.z.| -000000d0 03 a5 f1 09 d5 7e 07 74 f3 c8 e4 b8 da 44 a3 94 |.....~.t.....D..| -000000e0 ee 4e 4a 7b ab 4e 92 03 49 04 4e cf 1b b3 0d 91 |.NJ{.N..I.N.....| -000000f0 0f 98 51 5c 56 4d d3 a8 75 4b e0 96 d9 9e dd c8 |..Q\VM..uK......| -00000100 81 c4 37 a0 c6 c9 ec 0f e0 f1 ed 29 ff 5a a2 d4 |..7........).Z..| -00000110 af 61 f7 b1 d5 ee e7 1d 7a e1 7f 33 8d 75 e6 9d |.a......z..3.u..| -00000120 bc 78 56 eb c5 89 d3 19 86 81 09 e1 ee 10 03 7c |.xV............|| -00000130 a4 1b 78 17 51 a3 53 b4 67 5d 29 49 21 b2 51 7b |..x.Q.S.g])I!.Q{| -00000140 f5 dc fd 60 11 ee 8f 50 ea 28 b5 db 57 04 7e 3b |...`...P.(..W.~;| -00000150 ad 6f 29 d4 22 f3 a1 4b 52 ac b8 2b 30 0c 67 16 |.o)."..KR..+0.g.| -00000160 e3 e0 7d a3 03 66 c4 39 70 8e c7 06 cf d2 6f 98 |..}..f.9p.....o.| -00000170 c1 c9 f6 a9 6a 89 b4 3e 38 97 ae e4 f2 97 a4 6f |....j..>8......o| -00000180 e2 05 f8 e9 53 c9 ae f7 87 c3 0f 68 75 9e 07 e9 |....S......hu...| -00000190 45 e9 0d 03 7e c8 79 56 30 77 e3 ea db 92 a2 f8 |E...~.yV0w......| -000001a0 5e 5b ab 77 0d 9b bc 5f 51 40 6c 1b 0d ef b4 cf |^[.w..._Q@l.....| -000001b0 4a 3d a6 8c b6 ab ce 4f 6c 08 0e 23 f0 2a 56 07 |J=.....Ol..#.*V.| -000001c0 f5 88 68 c3 0c fd 63 9b e4 56 12 a6 f5 0a ed 54 |..h...c..V.....T| -000001d0 40 30 ee 36 72 5d ca bb 5a 52 d3 84 14 c1 7e e4 |@0.6r]..ZR....~.| -000001e0 f8 fb e9 c8 10 16 54 16 1f 72 99 8c 7a 69 87 ca |......T..r..zi..| -000001f0 62 53 dc cb a4 26 73 90 fb 11 3c 3c 9f 94 65 cb |bS...&s...<<..e.| -00000200 28 94 65 ca 56 45 a8 c1 ec 08 31 dd eb bc 17 71 |(.e.VE....1....q| -00000210 cd 65 04 95 2e e7 e0 fb 73 fe 70 db 70 31 93 90 |.e......s.p.p1..| -00000220 cf 47 07 ec 92 98 c1 da fc 13 f8 8a 28 4e e8 80 |.G..........(N..| -00000230 a8 96 c2 e2 a6 cd df d4 7f 46 4a 3b e9 dd cf a5 |.........FJ;....| -00000240 75 d5 cc 67 35 81 d5 2e e4 68 c4 56 1a 46 33 5a |u..g5....h.V.F3Z| -00000250 f2 79 32 6b 4e a0 6b 76 53 53 04 73 86 fd bd e2 |.y2kN.kvSS.s....| -00000260 f7 f8 14 0f 0a a8 10 6d a1 bf f8 d0 27 8d cb e8 |.......m....'...| -00000270 a5 51 16 4b 11 a2 8a 6f 22 c5 7c bc c5 7a 0b df |.Q.K...o".|..z..| -00000280 70 1d c4 93 ec 87 78 12 77 e3 85 5a 3c 29 d8 f7 |p.....x.w..Z<)..| -00000290 ab a4 c6 10 50 ed d5 2a 3f b1 84 73 1e 7f 99 eb |....P..*?..s....| -000002a0 31 9c 2c d2 6a 80 4a 5e 7c aa 64 e7 83 df a9 17 |1.,.j.J^|.d.....| -000002b0 c3 4c 13 c8 c1 d7 1b f5 be c9 00 cf ec 7e a5 ab |.L...........~..| -000002c0 89 9c b0 72 fd f0 cb 54 17 03 03 00 a4 28 34 92 |...r...T.....(4.| -000002d0 a7 52 92 5d a0 99 6b e6 22 c5 f6 76 86 1b 0b d6 |.R.]..k."..v....| -000002e0 b7 a8 67 c1 04 b8 1c ac 7b 02 f5 0a 20 41 dd 43 |..g.....{... A.C| -000002f0 25 cc 01 f9 dc 6e c7 f7 4f 67 dd b3 54 81 80 d5 |%....n..Og..T...| -00000300 6d 45 00 42 d0 49 23 d5 12 33 e4 5f fd 58 79 81 |mE.B.I#..3._.Xy.| -00000310 e3 df 67 6d 03 44 58 0f 76 38 c3 de ed 26 90 29 |..gm.DX.v8...&.)| -00000320 45 92 ce 3b fa ea 98 da ea a2 d2 cc c6 0e a8 38 |E..;...........8| -00000330 c1 2d 92 8c 48 79 58 25 75 fd 2d 6d ef 06 32 1a |.-..HyX%u.-m..2.| -00000340 bb 09 fa 66 bc 06 9d c5 fb 46 94 5e b1 73 8d 05 |...f.....F.^.s..| -00000350 e1 90 24 c3 eb 72 7f a8 b7 12 a3 3c 11 29 ea 80 |..$..r.....<.)..| -00000360 10 4e 19 40 25 0b c9 34 70 99 e9 1a 60 17 bb 5b |.N.@%..4p...`..[| -00000370 1a 17 03 03 00 35 91 4b 45 15 d5 2e 33 a7 ba 9b |.....5.KE...3...| -00000380 64 20 bb 72 28 06 27 37 2f ac c9 c0 9e b9 d8 f3 |d .r(.'7/.......| -00000390 86 36 d2 7d df c2 4d 95 a5 a4 4b 64 5f 1a 83 67 |.6.}..M...Kd_..g| -000003a0 f6 6a 21 ff d0 b4 1c 65 23 62 ac |.j!....e#b.| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 a9 |..+.....3.$... .| +00000060 5a 5c e9 b1 71 e8 a8 64 97 65 02 6b 3d 25 6f 6f |Z\..q..d.e.k=%oo| +00000070 9a 47 cb 4a 81 ac 89 23 22 c1 f4 3d db 77 1e 14 |.G.J...#"..=.w..| +00000080 03 03 00 01 01 17 03 03 00 17 12 15 75 15 9f 10 |............u...| +00000090 90 07 34 9c eb 05 d0 a1 4b 36 5b 4c 7b 26 2a 00 |..4.....K6[L{&*.| +000000a0 29 17 03 03 02 22 85 a0 67 d7 72 57 83 19 79 12 |)...."..g.rW..y.| +000000b0 b7 bd 37 ed ab 49 5d 15 49 2b 4f a1 b2 25 08 22 |..7..I].I+O..%."| +000000c0 88 83 70 07 bc 8f 69 45 1b 21 36 99 f4 99 40 f8 |..p...iE.!6...@.| +000000d0 0d 30 13 87 70 68 f6 9d ce c7 9e 25 2c 1e 7a b5 |.0..ph.....%,.z.| +000000e0 52 ed f8 0f f7 d9 e5 15 fc a3 47 83 0d 18 c4 de |R.........G.....| +000000f0 a1 a6 24 35 aa 56 d1 8b 95 07 5f 0f ba 1f 96 c3 |..$5.V...._.....| +00000100 5b 36 cc d2 15 e6 b4 88 8f e3 7f 79 c2 24 d5 f3 |[6.........y.$..| +00000110 a7 35 69 4e d2 2a f7 5c 08 8a c0 26 dd b9 77 5b |.5iN.*.\...&..w[| +00000120 96 1b 5f 03 89 07 a0 6a b1 14 1d 02 46 08 eb 80 |.._....j....F...| +00000130 d5 4c dc 69 63 8f 14 a1 e5 02 95 05 8a 8b c8 68 |.L.ic..........h| +00000140 c3 d8 75 56 47 94 32 ba 67 71 ed 4b b4 62 ba 6a |..uVG.2.gq.K.b.j| +00000150 31 20 a7 d6 f8 8c a0 e9 e8 d2 1a 6b 85 6b b7 ee |1 .........k.k..| +00000160 78 e1 2e 4c 14 f0 b3 3e b8 dc 7d af f0 9d 29 f3 |x..L...>..}...).| +00000170 54 1d 9d dc 9e a3 9f 29 5b 33 1d f7 00 98 85 bd |T......)[3......| +00000180 42 39 85 75 cf fa dc f3 7e 80 14 4e a5 90 80 b6 |B9.u....~..N....| +00000190 e3 37 d3 27 c6 7b b9 ee 32 61 a5 72 e5 2f a6 ab |.7.'.{..2a.r./..| +000001a0 cb 8e ac 53 4b 86 24 92 4b 77 d6 8d aa b4 37 d5 |...SK.$.Kw....7.| +000001b0 2b b2 2f 07 23 37 4a d9 1f cc 6c 72 c6 21 5b 38 |+./.#7J...lr.![8| +000001c0 a3 33 5c 86 50 69 34 8f 5a b8 cc 5e 82 7d 5b b2 |.3\.Pi4.Z..^.}[.| +000001d0 5b f5 58 7f 2c 61 08 4b 3d 8b 67 09 19 01 d2 4f |[.X.,a.K=.g....O| +000001e0 06 62 17 4e d4 bf 88 89 bb c4 6e 14 2b 3a 50 c9 |.b.N......n.+:P.| +000001f0 56 8a c1 0a 45 e6 67 32 f3 96 37 4b ba c2 2a 2b |V...E.g2..7K..*+| +00000200 84 e1 ff bb e0 ea 68 9b 98 fc 78 26 25 f6 50 25 |......h...x&%.P%| +00000210 52 57 83 94 39 b9 a7 8d 38 43 70 a8 b7 61 a6 cf |RW..9...8Cp..a..| +00000220 09 77 db 3d 64 94 63 73 5b a1 6d f4 06 c1 b3 fb |.w.=d.cs[.m.....| +00000230 c6 9a 0b ea 9f 8e 6d 58 53 0e 13 e0 a6 21 69 7a |......mXS....!iz| +00000240 d3 57 32 d4 c6 32 ef 02 8e 54 1d 72 2d d6 a7 dc |.W2..2...T.r-...| +00000250 59 54 be 69 3f 5c 53 23 a9 f7 3e a9 e6 e7 e0 98 |YT.i?\S#..>.....| +00000260 65 f6 74 f4 49 1c 77 0f 92 34 87 81 29 85 d1 e0 |e.t.I.w..4..)...| +00000270 1e 4d b4 eb c2 44 43 a7 10 51 7c 5e 8e a4 b6 37 |.M...DC..Q|^...7| +00000280 78 e8 35 02 07 3d 60 a5 01 75 01 25 f3 ff 32 ff |x.5..=`..u.%..2.| +00000290 34 ab a4 c3 4c ad 21 b8 91 0a d6 54 4b 7d cf c5 |4...L.!....TK}..| +000002a0 ec 0f e5 4a 4d 75 4c ec fc 37 2b 26 5a 73 93 70 |...JMuL..7+&Zs.p| +000002b0 88 c7 9c cf 32 f9 ee a7 27 6e 1d 9e 36 a2 31 9e |....2...'n..6.1.| +000002c0 cd 0e c2 89 ef 2b 40 1a 17 03 03 00 a4 ad 19 05 |.....+@.........| +000002d0 e6 40 5e b1 ec 69 6b 47 ef 5d d3 ee a6 94 51 85 |.@^..ikG.]....Q.| +000002e0 d8 28 d9 df 8b d0 df 23 7e bd 98 6c 33 26 45 fa |.(.....#~..l3&E.| +000002f0 60 71 8b f5 71 5c 22 4e b3 a7 01 fe 17 39 89 67 |`q..q\"N.....9.g| +00000300 0b 70 ff 52 b9 10 9c e9 02 c0 1c 56 9d c8 45 51 |.p.R.......V..EQ| +00000310 5a dd 86 79 6d a7 7d eb 16 c2 1a 5f 6a 3b 93 42 |Z..ym.}...._j;.B| +00000320 13 f3 3d 8a 39 21 5f a9 7f cf 4b 1e 22 f1 a3 f8 |..=.9!_...K."...| +00000330 5c 35 41 2a e2 91 72 4f 59 61 1c 15 be 27 6a bd |\5A*..rOYa...'j.| +00000340 b7 16 1f 63 97 51 d6 96 dd 81 f9 e7 fd 97 33 6e |...c.Q........3n| +00000350 da 5a 61 77 57 6e 3b 65 24 db b3 3a 18 7b dc f4 |.ZawWn;e$..:.{..| +00000360 7c ff ab 43 7f 1b ae ae b8 73 71 9e be 91 d6 56 ||..C.....sq....V| +00000370 13 17 03 03 00 35 39 61 a3 b7 e5 1d 3d 87 92 84 |.....59a....=...| +00000380 11 39 7d f4 ce 29 b9 4b fd 3c 0c 5a b6 3a fa e2 |.9}..).K.<.Z.:..| +00000390 a8 5b e6 d2 e5 7e e3 a6 33 59 e4 a8 59 95 5d b9 |.[...~..3Y..Y.].| +000003a0 31 6d 51 90 22 be c0 3f 6e 43 f2 |1mQ."..?nC.| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 10 bd 5d 23 36 |..........5..]#6| -00000010 58 43 f4 bb 5e 4e ee 43 fd 0e a1 d9 de 81 99 54 |XC..^N.C.......T| -00000020 de 6e 82 33 71 8a 45 a7 35 f1 cd fb 5f bf 46 20 |.n.3q.E.5..._.F | -00000030 a5 79 d6 87 aa f4 29 51 02 f5 4e 69 ef a5 d7 d6 |.y....)Q..Ni....| -00000040 17 03 03 00 17 21 1f 90 0b 01 63 89 6a af 53 72 |.....!....c.j.Sr| -00000050 51 c0 11 01 7b 09 dd 40 82 dd e1 32 17 03 03 00 |Q...{..@...2....| -00000060 13 93 5d c1 19 16 5c 17 1a 7b 92 a0 9b f5 14 57 |..]...\..{.....W| -00000070 85 39 4a ac |.9J.| +00000000 14 03 03 00 01 01 17 03 03 00 35 50 4f ce ae a5 |..........5PO...| +00000010 f7 b0 7e 2b 91 86 72 da 90 65 fd 1b a5 46 c6 98 |..~+..r..e...F..| +00000020 47 90 5a f2 b8 5a 1f 18 44 19 bd ca dd 2a 15 e7 |G.Z..Z..D....*..| +00000030 53 f5 17 e8 7d 9b f1 9a 63 ac b0 b0 df c3 0e 4c |S...}...c......L| +00000040 17 03 03 00 17 8b bd fb bc fd f7 af 53 9b 8b 1a |............S...| +00000050 a3 e5 f6 e9 87 bd 4a 8a 1b 0e c9 d9 17 03 03 00 |......J.........| +00000060 13 8e c6 d3 6e 04 8f 3b d4 76 a4 c7 c8 63 a8 a8 |....n..;.v...c..| +00000070 9e ba e7 fd |....| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv13-Ed25519 b/libgo/go/crypto/tls/testdata/Client-TLSv13-Ed25519 index 0b4a17a..d284740 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv13-Ed25519 +++ b/libgo/go/crypto/tls/testdata/Client-TLSv13-Ed25519 @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,53 +16,53 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 a8 21 4e 51 6a |....z...v...!NQj| -00000010 ce ba 17 cc 2d 25 b3 31 59 6a 3f 81 eb e6 ac a0 |....-%.1Yj?.....| -00000020 91 d9 ef 76 a1 5f bb 63 ab 2c 6b 20 00 00 00 00 |...v._.c.,k ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 6f b6 d3 79 9b |....z...v..o..y.| +00000010 00 17 a8 46 3f e4 bc fc 08 1e 56 6c d8 63 86 f3 |...F?.....Vl.c..| +00000020 83 1b d8 26 6d 86 d6 4c f3 4f e1 20 00 00 00 00 |...&m..L.O. ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 01 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 81 |..+.....3.$... .| -00000060 4c a8 07 aa 6b 4a f9 44 77 78 a9 57 d0 07 55 07 |L...kJ.Dwx.W..U.| -00000070 9a c2 8e 33 bf c4 09 ee 49 51 5c fe f1 7b 30 14 |...3....IQ\..{0.| -00000080 03 03 00 01 01 17 03 03 00 17 5a 22 a1 07 01 ea |..........Z"....| -00000090 97 bd 5a 59 3a 21 de 9c 45 0c 41 ff 34 45 35 ab |..ZY:!..E.A.4E5.| -000000a0 25 17 03 03 01 50 a1 8c 19 e7 0c 69 d3 e0 f6 53 |%....P.....i...S| -000000b0 95 15 13 4c e3 c3 3f 35 d9 73 c9 fe 24 b0 14 5f |...L..?5.s..$.._| -000000c0 b6 9e 94 20 cf 80 f7 88 7c 0f be 4c 70 16 00 2a |... ....|..Lp..*| -000000d0 55 02 aa a9 4b 7f a7 a5 b8 46 09 9e 18 78 78 66 |U...K....F...xxf| -000000e0 22 c2 31 19 12 f7 e4 7e f3 26 39 7d cd 5e 74 24 |".1....~.&9}.^t$| -000000f0 fb 75 7d b7 2c b5 fb e0 49 bd da 96 e1 c3 63 8f |.u}.,...I.....c.| -00000100 e3 28 43 bb 32 a7 fd 9c ab 54 ba ce 07 4a 23 35 |.(C.2....T...J#5| -00000110 a4 3a ff 43 40 19 ef 38 07 02 ba d6 c4 f0 bf 63 |.:.C@..8.......c| -00000120 aa b3 ea 55 d0 e1 a9 f3 cb 04 6b 1b 8d 35 3a f8 |...U......k..5:.| -00000130 0b 1c 40 99 fe b0 04 5f d1 5b 3f 4b be fe b5 96 |..@...._.[?K....| -00000140 f0 49 3d bf a5 92 f3 bd a6 4c 47 24 f8 b5 7c 45 |.I=......LG$..|E| -00000150 47 85 9b 08 a1 da 51 7a ce 3f 32 66 de 89 c0 c3 |G.....Qz.?2f....| -00000160 ac da 73 0d 15 14 18 e6 a0 7d 07 26 44 df 55 b7 |..s......}.&D.U.| -00000170 6e 4e fa c0 f5 5e 42 3a d9 29 d3 1d e6 cf 3c 8c |nN...^B:.)....<.| -00000180 6d c1 d9 f9 04 f0 57 dc 47 4e d1 e2 a1 f1 a1 c9 |m.....W.GN......| -00000190 2e da 97 4d 65 65 04 54 e7 80 f1 88 b2 34 26 61 |...Mee.T.....4&a| -000001a0 77 8a 1f bb 82 7f 4b ce b3 5a 55 60 e1 3a ef 95 |w.....K..ZU`.:..| -000001b0 bd 34 fc ef 2b 18 4b bb 8a cf ba 3a 69 43 f4 59 |.4..+.K....:iC.Y| -000001c0 98 a1 95 a3 22 f6 b5 1a 84 83 cf cb 90 eb 28 29 |....".........()| -000001d0 b3 84 e1 0d 37 9e 98 96 91 73 f1 7f d7 9b 71 38 |....7....s....q8| -000001e0 6e bc 2e 60 2d 27 0c 18 fd 2a b8 76 01 33 2f 95 |n..`-'...*.v.3/.| -000001f0 6e 0b bf 2b 26 5e 17 03 03 00 59 ed 43 2f e8 df |n..+&^....Y.C/..| -00000200 f3 2f 91 f3 dc 1b aa ff d3 3b 28 1f 78 21 fb e2 |./.......;(.x!..| -00000210 7d 6e 03 09 98 c1 23 09 d7 45 da b8 e0 5a e5 27 |}n....#..E...Z.'| -00000220 38 9a 2f da 9b d3 04 35 f5 b9 31 b0 c0 1f 8a 1e |8./....5..1.....| -00000230 d8 8a 19 f1 38 af a6 74 ac e5 b4 0d 45 83 b4 59 |....8..t....E..Y| -00000240 83 42 97 14 23 55 71 ef 66 8c 35 69 3f 2c 88 63 |.B..#Uq.f.5i?,.c| -00000250 8d 3b 05 fe 17 03 03 00 35 47 82 ec 22 f4 86 6a |.;......5G.."..j| -00000260 b7 c1 d8 64 3b 42 f4 ca 5c 3d ba a3 6a ea 77 6a |...d;B..\=..j.wj| -00000270 d6 52 e3 b0 42 fb c2 f1 2c b1 ef 44 ed 11 29 6d |.R..B...,..D..)m| -00000280 2b 6f 13 0f 42 48 a0 2e 5b ba a1 93 6b de |+o..BH..[...k.| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 5b |..+.....3.$... [| +00000060 8f 4f 5a a9 95 6b 04 07 31 d3 ed 91 8b 25 b4 7b |.OZ..k..1....%.{| +00000070 5c a1 0a a6 26 09 92 9b b0 72 26 f9 0d 09 60 14 |\...&....r&...`.| +00000080 03 03 00 01 01 17 03 03 00 17 a8 99 d3 76 1f 12 |.............v..| +00000090 19 18 15 8e 4c 59 43 92 11 4a aa 50 98 7e 4c d9 |....LYC..J.P.~L.| +000000a0 63 17 03 03 01 50 66 f5 d6 ce 35 0f 10 e5 ab 34 |c....Pf...5....4| +000000b0 78 17 c6 b6 60 40 eb 53 34 9f ce 02 c4 36 51 18 |x...`@.S4....6Q.| +000000c0 c2 b3 fb f3 98 92 d0 f2 b7 be 28 f5 c7 2d fa 1f |..........(..-..| +000000d0 9b 8b aa e5 45 54 6b 0e ed 6b 44 cb d4 4d 62 b2 |....ETk..kD..Mb.| +000000e0 30 c9 df ac cf a3 7e 43 58 1e bf 6e 5b 69 4e 48 |0.....~CX..n[iNH| +000000f0 1c 39 49 eb 8a 0c 22 f3 70 4a 80 50 39 d6 68 29 |.9I...".pJ.P9.h)| +00000100 d0 6d 08 20 26 39 6d 37 5a 9f 79 e9 16 e3 7e 94 |.m. &9m7Z.y...~.| +00000110 8f 5f 9b 97 2d e1 b1 48 e4 a3 36 63 40 5a 80 93 |._..-..H..6c@Z..| +00000120 06 27 3b 93 d9 ed 2d b1 3e 74 ed bc 38 a1 cb 17 |.';...-.>t..8...| +00000130 06 4a 9b c1 c1 d7 7a 1c ca ff 4d ee 91 6d d0 3c |.J....z...M..m.<| +00000140 c2 4b cc 33 c6 7c 76 8e db a2 e0 fe 15 e2 ec db |.K.3.|v.........| +00000150 1f 5d 05 c8 5e 0e 7f 2c 7a 95 08 34 68 a2 2c 7c |.]..^..,z..4h.,|| +00000160 04 16 92 7a c8 ec 52 2d 1a c4 7a ea 12 cd 0f b9 |...z..R-..z.....| +00000170 7c 00 51 55 02 5b 02 7d ec 89 af f5 6d 76 89 0e ||.QU.[.}....mv..| +00000180 67 42 f0 e4 67 4d 3f 70 ff 2c 64 81 1c 4a 92 1f |gB..gM?p.,d..J..| +00000190 26 8b a4 4f 15 18 b5 11 4a 61 df 45 53 74 fd 8d |&..O....Ja.ESt..| +000001a0 ff 22 32 91 af c7 7f a4 7b 62 c3 3b 30 51 b6 34 |."2.....{b.;0Q.4| +000001b0 b6 01 21 f9 86 74 be 62 27 1a 41 1f f0 0d 8b 5c |..!..t.b'.A....\| +000001c0 4b 82 ea 76 23 9c 36 af 25 1f f6 2d 5f 9c 28 bd |K..v#.6.%..-_.(.| +000001d0 b6 d5 1e 26 8b c1 dc ac ed 6d 10 ff 13 ed fc 08 |...&.....m......| +000001e0 08 0a 74 1c b1 5b f8 45 e4 83 44 f2 be ce 8d ac |..t..[.E..D.....| +000001f0 ee ae e6 21 da c7 17 03 03 00 59 d9 b3 95 0a f7 |...!......Y.....| +00000200 1a 1a 54 fa ab 09 38 6d 6d 53 0a ef 11 73 bc a2 |..T...8mmS...s..| +00000210 20 03 31 48 e2 0a d1 af 56 6c ca dd 88 ba 72 3a | .1H....Vl....r:| +00000220 c1 e0 c5 60 44 74 d6 c9 18 23 96 2c e7 88 c8 3e |...`Dt...#.,...>| +00000230 02 73 c0 38 d4 bd 85 a4 bb 78 a0 ba d3 fd f1 c4 |.s.8.....x......| +00000240 27 08 05 fb 2c 26 20 b7 1a 41 87 a6 b7 97 19 26 |'...,& ..A.....&| +00000250 50 ed 9a e4 17 03 03 00 35 68 36 c7 78 c3 5e ff |P.......5h6.x.^.| +00000260 b3 92 a7 25 31 2a a2 fa 24 d9 da 69 16 03 8b db |...%1*..$..i....| +00000270 fe b2 3f 63 88 49 f1 14 63 7a 58 a9 6f c5 64 92 |..?c.I..czX.o.d.| +00000280 21 84 82 d8 49 98 fb f3 f1 fd 52 83 32 97 |!...I.....R.2.| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 11 45 8f b2 e0 |..........5.E...| -00000010 87 3d 09 94 93 16 19 04 3d 84 6c e5 14 5e c6 8b |.=......=.l..^..| -00000020 73 1a 53 4c d0 f4 11 27 0c 0d 05 c7 9d ba d0 04 |s.SL...'........| -00000030 37 ed 8b 8a 65 34 54 b1 07 36 92 8c 8c a8 30 b7 |7...e4T..6....0.| -00000040 17 03 03 00 17 ea fc b8 84 8d f0 9d 8e 1c 2c 65 |..............,e| -00000050 10 a8 69 7f dd 3c a4 80 45 5d c3 38 17 03 03 00 |..i..<..E].8....| -00000060 13 15 4b b7 23 2f 55 b0 ae d3 3f f6 68 c9 b2 ef |..K.#/U...?.h...| -00000070 d7 e2 18 49 |...I| +00000000 14 03 03 00 01 01 17 03 03 00 35 07 7b a2 7a 4f |..........5.{.zO| +00000010 40 e9 a2 94 9f b7 2d 91 87 1e 37 b0 ca b7 ea 91 |@.....-...7.....| +00000020 53 f1 bf 7d 56 6a 0c 6a 9d 07 ac 93 9c db ca ac |S..}Vj.j........| +00000030 43 7b eb 56 9d 6c 79 f2 72 f8 0b 8d 15 08 84 d5 |C{.V.ly.r.......| +00000040 17 03 03 00 17 07 b3 7d a9 56 c4 76 e5 12 97 29 |.......}.V.v...)| +00000050 b7 99 e6 3e 08 79 2d fb 1a 5b eb 7a 17 03 03 00 |...>.y-..[.z....| +00000060 13 66 b7 65 57 0d 54 7b 6a 34 98 a1 4e 29 d5 92 |.f.eW.T{j4..N)..| +00000070 1e b6 52 bc |..R.| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv13-ExportKeyingMaterial b/libgo/go/crypto/tls/testdata/Client-TLSv13-ExportKeyingMaterial index b306411..a0ede61 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv13-ExportKeyingMaterial +++ b/libgo/go/crypto/tls/testdata/Client-TLSv13-ExportKeyingMaterial @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,75 +16,75 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 6d fb 70 07 b4 |....z...v..m.p..| -00000010 2d 14 d1 d1 88 17 6a a3 b1 c1 e7 23 4b 06 c4 fa |-.....j....#K...| -00000020 4a 0e e1 2c ce 5a d5 c7 8c ab f2 20 00 00 00 00 |J..,.Z..... ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 d6 7f ef 2d f6 |....z...v.....-.| +00000010 82 d9 be 6d 33 80 73 c0 d4 d8 63 e9 95 a6 5b 1f |...m3.s...c...[.| +00000020 ce c0 ec 13 07 f4 68 7d cc 79 18 20 00 00 00 00 |......h}.y. ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 01 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 4e |..+.....3.$... N| -00000060 fe 87 d7 81 71 25 ba 33 de 10 df 19 38 d8 af 43 |....q%.3....8..C| -00000070 58 3f 41 2e b9 b8 cb 1c 65 a7 cd 8d 00 b1 0e 14 |X?A.....e.......| -00000080 03 03 00 01 01 17 03 03 00 17 b3 63 09 54 ad 41 |...........c.T.A| -00000090 24 fe 2c 81 49 c8 86 88 c2 ad ba cd 45 77 51 c0 |$.,.I.......EwQ.| -000000a0 d5 17 03 03 02 6d 74 7d de 53 70 5c 11 d0 a7 68 |.....mt}.Sp\...h| -000000b0 8e 10 c9 cb cd 0c 25 ac 88 e7 17 54 8b 32 2c ee |......%....T.2,.| -000000c0 97 9c 3d f6 ce d1 83 70 ee c0 85 0c fc 61 ba db |..=....p.....a..| -000000d0 6d e0 04 26 6f b7 4e 44 4d 1c 5c 16 9a 57 4f e6 |m..&o.NDM.\..WO.| -000000e0 52 89 27 53 88 f8 93 91 ed b2 42 b4 4c f0 58 a3 |R.'S......B.L.X.| -000000f0 50 a7 af 2c 47 ac ad 8b 14 a0 9f d4 28 2e 7b 28 |P..,G.......(.{(| -00000100 8e ec d1 bb 7d d9 78 fb 24 82 9f 2a ac 4e 85 83 |....}.x.$..*.N..| -00000110 35 25 75 8f 9e 6d 4c 8a dd 6f 9f 9a 34 93 a2 9d |5%u..mL..o..4...| -00000120 d0 26 4c 7b a8 72 a3 12 b9 ef 6b c8 d0 4f 44 5b |.&L{.r....k..OD[| -00000130 dd f1 72 3a b4 5c 7e a8 8d d4 68 bc 6d 54 2c ee |..r:.\~...h.mT,.| -00000140 c1 f7 78 f1 15 cd 57 b5 54 89 08 f0 d8 56 ef 8d |..x...W.T....V..| -00000150 14 d1 e8 fd 83 bd ab 64 c1 99 36 4e af 81 27 52 |.......d..6N..'R| -00000160 0f 5e 31 5e c0 70 21 fb 05 40 d4 d2 71 df 0c 09 |.^1^.p!..@..q...| -00000170 31 83 b0 71 82 84 d9 90 6b 25 5a 67 03 30 c4 80 |1..q....k%Zg.0..| -00000180 2c 99 41 3f fa 51 ce a8 b4 b8 98 2a bc e9 cc ce |,.A?.Q.....*....| -00000190 f7 0c 69 a3 c3 02 dc b9 4f 00 ac 4f 29 d5 e5 df |..i.....O..O)...| -000001a0 df 67 3b ed 94 8e 80 3f aa 6e a8 b7 e0 7f 4d fd |.g;....?.n....M.| -000001b0 95 80 54 89 57 ff d7 73 86 bd e8 98 11 d5 09 c6 |..T.W..s........| -000001c0 ab af 1a a4 a0 cc 30 40 bc 63 dc d0 db 92 41 f5 |......0@.c....A.| -000001d0 5c 1e f1 92 03 5b 3f 27 23 1f 9c 8e f8 8b 4f 69 |\....[?'#.....Oi| -000001e0 0c 3d 09 e5 95 d8 ba 8c 90 cd ac 53 ed 77 8d 75 |.=.........S.w.u| -000001f0 3a 56 b4 f3 21 a5 4e c2 6e 1f 87 74 56 69 32 95 |:V..!.N.n..tVi2.| -00000200 29 56 07 2c 0d b3 74 47 28 6d 8f ef 56 f6 68 7f |)V.,..tG(m..V.h.| -00000210 25 e4 76 06 7c 82 40 11 f8 eb 3c ec 62 fa be 60 |%.v.|.@...<.b..`| -00000220 d3 11 98 e2 d4 b1 d0 72 3d e6 4a da f0 d6 c0 42 |.......r=.J....B| -00000230 8e a6 63 cc a1 41 e3 18 21 00 ac cc 98 f8 8d 78 |..c..A..!......x| -00000240 ab 9b 39 16 ad 4c fd 11 15 79 0c fd 0e 87 45 d6 |..9..L...y....E.| -00000250 81 30 bb 3a 72 89 92 c1 fa e8 ad 59 3b 8b b0 38 |.0.:r......Y;..8| -00000260 2d c3 6e 87 a8 b8 1f 7d a0 b3 e6 91 83 97 78 94 |-.n....}......x.| -00000270 f0 01 66 a2 c8 89 45 8e 2e a0 7e 89 4d 7f 49 ee |..f...E...~.M.I.| -00000280 2a 69 c0 ec 77 db 85 df 01 d9 02 36 df 94 81 01 |*i..w......6....| -00000290 aa 43 a2 3d 76 8c c3 21 bf 05 c3 b2 c4 28 85 65 |.C.=v..!.....(.e| -000002a0 7b 4a ac e3 45 40 77 1d a9 ee 1e e9 97 7c 2f 45 |{J..E@w......|/E| -000002b0 45 18 58 47 ab 51 0f 26 eb d5 bb ac c2 8b a9 ae |E.XG.Q.&........| -000002c0 65 6a 91 9b 13 93 69 c6 9d bc 61 23 20 d2 ad a0 |ej....i...a# ...| -000002d0 d3 f9 2d 32 79 e3 4b 07 90 32 9e e1 f3 13 18 b0 |..-2y.K..2......| -000002e0 65 6e 89 a5 45 c6 a1 9b f0 f6 d1 66 d3 e7 49 1a |en..E......f..I.| -000002f0 b8 e2 17 cd d0 13 9c e6 e1 77 87 a4 8b 6a d3 74 |.........w...j.t| -00000300 0e 85 b1 2c f3 c8 a8 f3 65 b3 71 c2 bb f5 95 d7 |...,....e.q.....| -00000310 81 78 45 17 03 03 00 99 1e 53 96 f9 b9 97 ec 53 |.xE......S.....S| -00000320 4e 97 a9 8c 01 06 ee 6b 31 47 93 4b ac f7 b6 4a |N......k1G.K...J| -00000330 15 bb 28 d7 87 73 7c 1d 3b d3 6b 9d 48 77 df 09 |..(..s|.;.k.Hw..| -00000340 c9 97 98 b6 d6 20 94 8a ed 71 08 2d 56 af b2 b8 |..... ...q.-V...| -00000350 20 fc d7 81 e4 53 eb 57 6a bd 9b 1c 11 4f 2e fb | ....S.Wj....O..| -00000360 9a 0e 65 08 69 df 28 70 a7 50 21 62 9f 63 39 db |..e.i.(p.P!b.c9.| -00000370 9e 73 40 5d 73 77 a7 1d 2e 79 61 fa b9 50 f0 70 |.s@]sw...ya..P.p| -00000380 1e 71 d1 9e c6 2f 8c 4c 5f e0 b1 37 d7 c9 ab fc |.q.../.L_..7....| -00000390 5f 6a ca a9 9e 27 38 42 78 ba fb e6 8e c2 3f a6 |_j...'8Bx.....?.| -000003a0 a0 c6 04 b6 d8 b7 3a 68 83 15 3b 70 f9 0a 27 4a |......:h..;p..'J| -000003b0 0a 17 03 03 00 35 d0 88 b7 b8 cf 81 4e 97 76 96 |.....5......N.v.| -000003c0 c2 ed e8 15 e4 01 54 2b 1f 0e 34 08 52 6c a8 6a |......T+..4.Rl.j| -000003d0 cf 04 29 7b 27 fb e9 1e d1 6c d2 28 15 03 2a 58 |..){'....l.(..*X| -000003e0 d4 eb 67 18 83 3f d4 2a ab 9f aa |..g..?.*...| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 00 |..+.....3.$... .| +00000060 e9 40 7a 65 78 98 47 43 aa e1 63 fd 6b c4 21 1d |.@zex.GC..c.k.!.| +00000070 58 45 5f 64 a0 18 55 a0 c3 14 7d 4e 12 93 7c 14 |XE_d..U...}N..|.| +00000080 03 03 00 01 01 17 03 03 00 17 4c 01 0b f7 e7 1b |..........L.....| +00000090 a9 47 84 10 3b 50 85 6e 3d 8e 52 bc 99 bf d4 35 |.G..;P.n=.R....5| +000000a0 45 17 03 03 02 6d 8c b3 22 04 de 8b 09 e5 e7 9f |E....m..".......| +000000b0 d5 1f fb 8a 57 ad a7 93 4c 5f 29 46 df c3 e5 86 |....W...L_)F....| +000000c0 66 f1 c7 6b 14 79 cf 9d cc e1 f5 3f 31 2c dc ff |f..k.y.....?1,..| +000000d0 77 99 14 9e 56 12 4e a4 cb 56 5c d6 c0 5b 57 dc |w...V.N..V\..[W.| +000000e0 22 72 12 2d d6 a0 8a c7 90 e6 41 66 78 1a d7 a6 |"r.-......Afx...| +000000f0 87 db f1 e3 9b 86 8c cf 94 22 cf 81 99 20 bc 19 |........."... ..| +00000100 50 f9 fe 6c ab ea d4 a2 ee f8 17 1d ae 37 86 2a |P..l.........7.*| +00000110 f9 83 3c 59 d0 aa 63 22 18 d5 12 40 be f7 02 f1 |..<Y..c"...@....| +00000120 9a bf 07 39 23 73 23 a1 66 70 b7 be 9a 24 de 30 |...9#s#.fp...$.0| +00000130 2f 62 6e f8 d5 ee 69 a7 87 3c 73 10 4c 7c 97 42 |/bn...i..<s.L|.B| +00000140 62 b9 d5 74 40 f0 d7 b3 74 42 73 d7 41 bc 35 43 |b..t@...tBs.A.5C| +00000150 87 2e c5 1b e9 15 e8 5e 18 b9 6b 57 2a ee 59 7a |.......^..kW*.Yz| +00000160 1c a6 2b cb b4 db e8 bb 99 87 74 4a ee 57 3a 87 |..+.......tJ.W:.| +00000170 3c 2d b9 76 41 4a 7a a5 6a fa 92 e9 80 24 08 dc |<-.vAJz.j....$..| +00000180 18 44 4b 59 7c 81 99 29 f2 c4 55 b6 58 71 0d 68 |.DKY|..)..U.Xq.h| +00000190 6b 06 bd 13 2c a0 04 15 2e 49 cc 99 7f a6 b4 5d |k...,....I.....]| +000001a0 d3 49 a5 21 15 d7 66 2d a2 e8 cd a7 7e 46 c4 ac |.I.!..f-....~F..| +000001b0 89 ae cb 58 73 42 9f dc c3 c9 5a 13 2f 6f f7 ab |...XsB....Z./o..| +000001c0 04 4b 9f f1 6c c4 ac 0f f5 eb 8d 7a ef cf 01 00 |.K..l......z....| +000001d0 8a 02 ec 16 09 c1 e9 27 81 32 70 b1 24 d4 db 4e |.......'.2p.$..N| +000001e0 9e 22 65 21 a7 8f 19 d5 c6 57 78 8a fa a6 41 87 |."e!.....Wx...A.| +000001f0 52 eb 5d ef f8 7e 3b 34 a5 31 ff 33 33 fd 85 03 |R.]..~;4.1.33...| +00000200 e4 94 56 ef 11 c0 fe 84 f6 87 94 26 de 7c bd d1 |..V........&.|..| +00000210 1b ea 15 34 62 e5 da bd e6 c4 b0 74 b5 27 ad 21 |...4b......t.'.!| +00000220 39 16 c8 be e8 41 50 7b de fb 71 10 4c b1 f4 5a |9....AP{..q.L..Z| +00000230 bf ea fd 9b 86 a5 c6 e7 2f c2 13 e4 d2 cd 32 7a |......../.....2z| +00000240 6b ad ab 43 12 3b 45 b9 5c e4 cf 2c f9 f3 44 2c |k..C.;E.\..,..D,| +00000250 11 31 ce c5 65 dd ea e6 52 bd 8a 35 d0 31 d4 4f |.1..e...R..5.1.O| +00000260 01 24 54 e4 d2 bf 6e 79 b2 bf a8 f0 5d 9d 72 44 |.$T...ny....].rD| +00000270 6e df 29 8a d2 cc a8 d2 ee 0c 51 50 cd 71 a6 2a |n.).......QP.q.*| +00000280 fe 53 2e f7 ae fa 4c 34 d0 68 31 d5 69 be 64 a5 |.S....L4.h1.i.d.| +00000290 03 54 31 1a dc f0 9e c7 82 1f 15 d1 64 ff 79 07 |.T1.........d.y.| +000002a0 5e 71 3a 98 3c 21 a7 8e 1e bf 2d f3 86 4b 3f 30 |^q:.<!....-..K?0| +000002b0 73 0d 7c 5d 57 1b a9 89 2b 52 70 84 8e e6 bb fe |s.|]W...+Rp.....| +000002c0 b7 1f 65 6a 08 63 58 16 81 51 09 b2 79 7d 84 c0 |..ej.cX..Q..y}..| +000002d0 6f e1 ab 92 35 16 2e 8f 5c 17 2d 5e 68 7f d4 94 |o...5...\.-^h...| +000002e0 5a 1b 1d 6c 5f e0 36 a0 ae 54 5b e9 39 1f bc 73 |Z..l_.6..T[.9..s| +000002f0 f9 04 80 e9 36 d2 2c de 64 ca 08 95 d0 98 4b da |....6.,.d.....K.| +00000300 7b 0d 7f 79 1b a0 56 6c dd 3c 40 52 3e 7a 8f 52 |{..y..Vl.<@R>z.R| +00000310 3c c9 2f 17 03 03 00 99 07 91 f0 6b e0 bb 6f 0b |<./........k..o.| +00000320 ff 08 69 bc d2 1d f1 40 d2 d7 c7 f6 c2 b3 57 d7 |..i....@......W.| +00000330 90 00 c9 9e ef 40 b6 96 86 0d 27 8b 6f ac 54 2f |.....@....'.o.T/| +00000340 73 b3 b4 82 1b d3 f5 e9 41 a7 fd d5 b1 67 f7 6e |s.......A....g.n| +00000350 2e c1 06 34 ef a3 b9 97 4d a8 64 4f f8 48 24 5c |...4....M.dO.H$\| +00000360 66 f4 d7 d4 e3 ad 45 fb 4a 42 0d 19 bb a1 cc b3 |f.....E.JB......| +00000370 88 d2 2a d7 c3 53 c4 7b 08 a5 68 dc c4 1a f6 f3 |..*..S.{..h.....| +00000380 a1 42 48 1c c9 2b 1f fb 5d fc 49 ed ce 16 14 34 |.BH..+..].I....4| +00000390 34 01 c9 ef e6 29 9c 81 1a 7d 7b bd 95 eb ad 5f |4....)...}{...._| +000003a0 ce 19 30 9c e6 ae 09 15 3c 2b 38 8b e6 97 76 4e |..0.....<+8...vN| +000003b0 dd 17 03 03 00 35 d2 a1 3f 22 e9 2b b6 7a d1 d8 |.....5..?".+.z..| +000003c0 7b 87 bf d1 bf 56 0b 55 52 d0 a9 cf ae 57 6e 6f |{....V.UR....Wno| +000003d0 29 0c c3 f7 f3 d4 bf ff a4 6b 49 1a 57 57 27 89 |)........kI.WW'.| +000003e0 e0 f5 bb d2 16 85 39 40 fd 77 a3 |......9@.w.| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 02 ed 34 8f 83 |..........5..4..| -00000010 44 27 8b 71 af c1 06 33 0b 25 aa 22 85 96 41 75 |D'.q...3.%."..Au| -00000020 4f fe 46 82 ba 95 91 4c cc a9 99 60 5c f7 72 7f |O.F....L...`\.r.| -00000030 e4 1f e4 99 6a c2 25 db d0 11 5d fc d6 28 8f 56 |....j.%...]..(.V| -00000040 17 03 03 00 17 fe e8 cf ed a0 7a ce 77 57 e6 aa |..........z.wW..| -00000050 f0 ce 6d 2f 5c e5 1f 7d 37 c8 91 cf 17 03 03 00 |..m/\..}7.......| -00000060 13 a4 a9 4c b5 33 38 4a 1e b7 65 9d 72 85 1b 79 |...L.38J..e.r..y| -00000070 79 87 e3 bf |y...| +00000000 14 03 03 00 01 01 17 03 03 00 35 b3 39 ad 6b 24 |..........5.9.k$| +00000010 47 e3 9f 11 f9 7e 9a cf 41 db c8 43 ce 86 ae ce |G....~..A..C....| +00000020 0c af 17 42 d7 24 57 13 e6 ba a7 44 7c 72 38 aa |...B.$W....D|r8.| +00000030 8f fa a2 a2 9f b0 ba 43 47 20 e8 03 3c 00 ee ad |.......CG ..<...| +00000040 17 03 03 00 17 ff 5b 79 f8 c8 0c 7a 52 6d b0 b2 |......[y...zRm..| +00000050 22 17 3b 5d f9 75 23 bb 27 38 35 a6 17 03 03 00 |".;].u#.'85.....| +00000060 13 d3 94 d9 b5 8b fa dc b6 fe 26 ca b0 52 5c ef |..........&..R\.| +00000070 84 e3 3c f9 |..<.| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv13-HelloRetryRequest b/libgo/go/crypto/tls/testdata/Client-TLSv13-HelloRetryRequest index 10e13ec..4840339 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv13-HelloRetryRequest +++ b/libgo/go/crypto/tls/testdata/Client-TLSv13-HelloRetryRequest @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 77 00 05 00 05 01 00 00 00 00 00 0a 00 |...w............| 00000090 06 00 04 00 1d 00 17 00 0b 00 02 01 00 00 0d 00 |................| 000000a0 1a 00 18 08 04 04 03 08 07 08 05 08 06 04 01 05 |................| @@ -20,7 +20,7 @@ 00000010 9a 61 11 be 1d 8c 02 1e 65 b8 91 c2 a2 11 16 7a |.a......e......z| 00000020 bb 8c 5e 07 9e 09 e2 c8 a8 33 9c 20 00 00 00 00 |..^......3. ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 01 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| 00000050 0c 00 2b 00 02 03 04 00 33 00 02 00 17 14 03 03 |..+.....3.......| 00000060 00 01 01 |...| >>> Flow 3 (client to server) @@ -29,10 +29,10 @@ 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000030 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |. ..............| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000050 00 00 00 32 cc a8 cc a9 c0 2f c0 2b c0 30 c0 2c |...2...../.+.0.,| -00000060 c0 27 c0 13 c0 23 c0 09 c0 14 c0 0a 00 9c 00 9d |.'...#..........| -00000070 00 3c 00 2f 00 35 c0 12 00 0a 00 05 c0 11 c0 07 |.<./.5..........| -00000080 13 01 13 03 13 02 01 00 00 98 00 05 00 05 01 00 |................| +00000050 00 00 00 32 cc a9 cc a8 c0 2b c0 2f c0 2c c0 30 |...2.....+./.,.0| +00000060 c0 09 c0 13 c0 0a c0 14 00 9c 00 9d 00 2f 00 35 |............./.5| +00000070 c0 12 00 0a c0 23 c0 27 00 3c c0 07 c0 11 00 05 |.....#.'.<......| +00000080 13 03 13 01 13 02 01 00 00 98 00 05 00 05 01 00 |................| 00000090 00 00 00 00 0a 00 06 00 04 00 1d 00 17 00 0b 00 |................| 000000a0 02 01 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 |................| 000000b0 05 08 06 04 01 05 01 06 01 05 03 06 03 02 01 02 |................| @@ -44,76 +44,76 @@ 00000110 32 42 e9 58 b6 d7 49 a6 b5 68 1a 41 03 56 6b dc |2B.X..I..h.A.Vk.| 00000120 5a 89 |Z.| >>> Flow 4 (server to client) -00000000 16 03 03 00 9b 02 00 00 97 03 03 b5 7c 4a c4 82 |............|J..| -00000010 67 2c 0d e4 cf 12 5a 8c fc 44 10 da 7e ef ec ae |g,....Z..D..~...| -00000020 bc 59 6c 7d 62 b1 d8 95 5d 9d 3b 20 00 00 00 00 |.Yl}b...].; ....| +00000000 16 03 03 00 9b 02 00 00 97 03 03 1d 65 62 8f 58 |............eb.X| +00000010 2b 99 04 1d fd cc e3 0b 46 5c 55 a9 3a 80 76 60 |+.......F\U.:.v`| +00000020 8f 52 09 6e 48 5d 5a e3 92 da a3 20 00 00 00 00 |.R.nH]Z.... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 01 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| 00000050 4f 00 2b 00 02 03 04 00 33 00 45 00 17 00 41 04 |O.+.....3.E...A.| -00000060 51 c8 a4 d2 63 ec a1 b7 72 7e 42 30 8e d2 eb b0 |Q...c...r~B0....| -00000070 3c e0 06 d0 69 39 b7 55 ee 47 c3 b3 b6 56 2d df |<...i9.U.G...V-.| -00000080 3e 0c 1c 92 cf f6 c4 52 13 90 fa e6 52 13 e6 6d |>......R....R..m| -00000090 35 46 de 60 05 a1 85 a9 ec 86 dc da 19 4d 21 67 |5F.`.........M!g| -000000a0 17 03 03 00 17 d7 59 69 75 49 13 ac 27 ad 1c a9 |......YiuI..'...| -000000b0 17 68 46 77 a2 22 0a f5 6f ce 70 67 17 03 03 02 |.hFw."..o.pg....| -000000c0 6d ee 92 51 b3 07 0f 46 be 24 a1 12 02 7e d1 d4 |m..Q...F.$...~..| -000000d0 b1 2e f5 87 f5 96 ed 00 77 f1 ad 1b 8e cd 1d 01 |........w.......| -000000e0 41 78 6a ff 68 9f 6d ac fe 92 8a c5 43 d2 c9 1d |Axj.h.m.....C...| -000000f0 a8 d8 0f 00 7e c1 06 a9 16 ba 13 94 e7 d9 cd e1 |....~...........| -00000100 01 fd 52 12 be b0 04 14 85 d3 06 a2 63 d7 16 7a |..R.........c..z| -00000110 06 5f 1f c2 31 ea 27 1a a5 1d f6 39 d2 b1 99 8c |._..1.'....9....| -00000120 e0 71 32 3b ef 4e d3 1c 21 3f 30 59 5b 3e 1f 64 |.q2;.N..!?0Y[>.d| -00000130 3c 27 35 0f ee f4 75 5c 53 38 f8 43 87 55 88 28 |<'5...u\S8.C.U.(| -00000140 17 8f 4c 2d 73 d0 bd db 43 25 2f da fb f3 f7 b4 |..L-s...C%/.....| -00000150 63 90 08 24 c6 b3 ae 91 00 2d 4f bd af bc 22 82 |c..$.....-O...".| -00000160 08 ef 29 c9 49 d2 73 97 ce 6c 8d 1e a2 cb 53 ff |..).I.s..l....S.| -00000170 fe 9c b1 14 58 6f 45 bf ee 93 c0 9b 96 86 54 1a |....XoE.......T.| -00000180 fc fe 84 c3 88 13 92 d4 d7 de 00 07 d4 f7 ef 8e |................| -00000190 5e 5f b0 12 c9 6a 81 df 05 e6 c3 a1 f6 8a bc 06 |^_...j..........| -000001a0 bc 45 47 06 d4 45 70 78 f9 16 0f d2 f4 ae b5 94 |.EG..Epx........| -000001b0 e6 ac b5 bf e3 40 d1 fe 20 07 23 f8 65 fe 57 b2 |.....@.. .#.e.W.| -000001c0 63 a0 db 7b fa 12 25 2b 1f 1c df 66 ee c4 84 80 |c..{..%+...f....| -000001d0 4a 95 64 3d 9f c2 e9 eb 7c 59 72 1c 52 68 fa 5a |J.d=....|Yr.Rh.Z| -000001e0 b3 d6 9e dc 51 d6 ac 0b 34 f1 66 42 4b 99 1d cb |....Q...4.fBK...| -000001f0 94 f4 08 c6 57 f9 97 87 54 9c 3b ba 4e 21 c7 b3 |....W...T.;.N!..| -00000200 a0 d9 41 33 22 c4 3f a4 29 e4 7a 3c a1 86 e0 65 |..A3".?.).z<...e| -00000210 f4 ff 67 c5 32 ae 16 01 67 8e 16 d7 28 5e b3 19 |..g.2...g...(^..| -00000220 c6 18 c7 27 0d 01 8e 04 87 fb 6b f9 72 ee 00 ff |...'......k.r...| -00000230 25 f9 c5 dd bc 30 45 63 2d 4d 2d 9d ea 7f 54 aa |%....0Ec-M-...T.| -00000240 ac 9e d8 a2 ae c2 e3 64 b7 3d 54 56 67 39 e8 96 |.......d.=TVg9..| -00000250 a5 5d fd 1e 01 2a 0c 7d ee f1 4e fc 1b 19 f9 ef |.]...*.}..N.....| -00000260 60 dd e1 b2 94 f3 5f 54 d4 05 f7 86 83 6f 97 43 |`....._T.....o.C| -00000270 4e 30 c1 49 cc 5e 98 10 5c 4e 32 84 97 70 c8 b9 |N0.I.^..\N2..p..| -00000280 6d 0b c2 23 ab f9 e8 85 6f 0a 2a 99 e7 12 33 e8 |m..#....o.*...3.| -00000290 f2 62 6f 65 0c 3d ff 9f e6 15 eb 1d 24 0e e9 8a |.boe.=......$...| -000002a0 28 e0 09 31 23 a4 5c 2c 25 49 b4 0c 5f 18 e1 12 |(..1#.\,%I.._...| -000002b0 82 16 6e 79 68 21 fb 5a 68 73 dd f7 2f aa e2 f9 |..nyh!.Zhs../...| -000002c0 85 8d af c6 84 50 af 84 95 12 c8 32 a6 eb f0 93 |.....P.....2....| -000002d0 a2 bd 97 d3 ba 76 a8 2e a2 44 2f 98 23 ca 78 cd |.....v...D/.#.x.| -000002e0 7a 5f bf ab 19 00 72 b5 b3 e0 a7 b5 da 47 05 c8 |z_....r......G..| -000002f0 44 0b 6c 7f 0b 4c 99 79 3c 47 7e e9 25 bd a8 4d |D.l..L.y<G~.%..M| -00000300 7a 1c 17 aa 00 dc f8 d8 98 5b 8e e4 30 9f 52 9e |z........[..0.R.| -00000310 d3 13 ea 82 65 8b 43 1f 05 f9 3a 86 09 e0 ed b9 |....e.C...:.....| -00000320 8d 42 75 c7 dd 70 5d 04 c5 a4 68 04 e1 36 17 03 |.Bu..p]...h..6..| -00000330 03 00 99 52 81 9b 5c ed c2 08 48 13 d9 4f 0a 52 |...R..\...H..O.R| -00000340 db 15 fc 73 66 03 85 10 b3 32 f3 e9 60 f1 c5 30 |...sf....2..`..0| -00000350 e4 85 d8 ab 85 c7 52 f0 1e 99 88 cf b0 e1 f9 c7 |......R.........| -00000360 c1 8a d0 ed 0f 0d 34 05 35 63 a6 52 bf 91 db f0 |......4.5c.R....| -00000370 b2 46 fb d9 68 95 ec a7 e4 fc ff f7 f0 7f 54 db |.F..h.........T.| -00000380 a8 96 fe 9d 12 f0 38 3e 4f 68 ff 27 1c 25 a6 1d |......8>Oh.'.%..| -00000390 1f 89 9e 21 34 97 b9 7e 6e 2a c2 df 47 22 7d a6 |...!4..~n*..G"}.| -000003a0 aa 7a 4a fd 11 b0 73 10 f5 16 8b 2c 3a af a6 7a |.zJ...s....,:..z| -000003b0 cc 3d 4b f0 36 43 60 db 53 2a 4e 2c 1b 2c 0a 54 |.=K.6C`.S*N,.,.T| -000003c0 01 ff ad 7e 93 a8 d0 76 da 5a 88 88 17 03 03 00 |...~...v.Z......| -000003d0 35 d0 36 70 7c 4c 6a 10 bd 43 50 2c 47 74 f9 ed |5.6p|Lj..CP,Gt..| -000003e0 9f 0b d7 33 82 74 2f fd 81 4d 08 d6 cf f4 13 4e |...3.t/..M.....N| -000003f0 de ec 84 bf 79 35 ee 72 8a a3 d0 61 29 94 ad 79 |....y5.r...a)..y| -00000400 04 42 0f 2b 65 a1 |.B.+e.| +00000060 1c 01 c6 9e c8 49 43 49 6f 0f 17 f3 ce 87 1a 0f |.....ICIo.......| +00000070 1f 2c 70 18 e4 29 f2 16 a2 e0 02 b7 9d 52 bc b9 |.,p..).......R..| +00000080 d4 b0 1d 19 da 3a 38 f6 93 04 0b ae 5f 60 45 87 |.....:8....._`E.| +00000090 57 80 20 27 c6 9c d4 eb ec c0 85 df f5 aa be de |W. '............| +000000a0 17 03 03 00 17 d4 a9 5f 09 d3 e6 47 ad a7 7b 38 |......._...G..{8| +000000b0 a3 b8 02 37 16 ec 03 56 df d5 8d ec 17 03 03 02 |...7...V........| +000000c0 6d be 1b 2a 60 52 3c 01 2e 6e 7f e3 68 fa de 09 |m..*`R<..n..h...| +000000d0 ed 5e 8f 0f a0 34 d5 0a 8b 2f 30 8f 6c 56 9e fe |.^...4.../0.lV..| +000000e0 e6 9a a9 f1 6e 7c 63 a7 d8 88 e2 95 fa 17 ad 0c |....n|c.........| +000000f0 49 20 93 18 3c ba db fc a1 14 60 2c 77 d4 44 5f |I ..<.....`,w.D_| +00000100 69 9c c7 a3 b9 d0 ee e8 c5 ec 45 d3 79 d0 ee 04 |i.........E.y...| +00000110 fd c3 6d 12 1a f2 6e 62 9f eb ff 32 88 17 4c df |..m...nb...2..L.| +00000120 20 4f cc f9 fd d5 7c 8b 8c c2 da 7d 8a c9 f9 27 | O....|....}...'| +00000130 32 06 75 fe 75 e2 bb bd 6c 31 5d 32 af 36 95 39 |2.u.u...l1]2.6.9| +00000140 92 6c 32 e5 4f b5 f7 07 9f b3 1b b8 10 a8 d9 db |.l2.O...........| +00000150 d3 b0 40 2f 1e e6 54 f5 35 73 7d 22 b3 6b b8 3c |..@/..T.5s}".k.<| +00000160 83 82 8a 75 f4 ec 18 94 57 0c de 98 41 73 61 63 |...u....W...Asac| +00000170 5b 95 3e 4e d4 02 c3 b7 f9 4c 6f 01 c9 52 3c b9 |[.>N.....Lo..R<.| +00000180 ad 61 83 2c 89 6d 63 40 fd d4 67 83 36 8b 9a 1c |.a.,.mc@..g.6...| +00000190 ca 93 16 d8 e3 91 08 d1 3f ba af cb d9 69 09 10 |........?....i..| +000001a0 07 a7 54 9c ee a2 7d 97 ce b6 1f 31 9b 85 b0 82 |..T...}....1....| +000001b0 fc 22 87 70 93 59 9c c9 e3 07 9b d0 c0 a4 1d d4 |.".p.Y..........| +000001c0 2e 36 c0 72 b6 d5 2a f5 b3 fa ab fb 1a 90 05 51 |.6.r..*........Q| +000001d0 b7 19 15 af d9 b2 5f 32 ef e6 5a 2d 4a 2c 7f a9 |......_2..Z-J,..| +000001e0 43 cf b8 ac e4 8a f0 bf 68 90 b9 7c 1c 7e fa f0 |C.......h..|.~..| +000001f0 bc e3 a9 4f a7 2d 3a f3 12 eb b1 93 b4 b9 1b d7 |...O.-:.........| +00000200 81 31 db 58 c4 8e 9f 46 44 39 74 a1 a8 b0 78 0c |.1.X...FD9t...x.| +00000210 b9 23 6d 90 bb a8 b0 7c e2 a3 a3 c4 e6 83 32 5d |.#m....|......2]| +00000220 ea 5a a4 3d 94 ca 51 3c 71 28 cf 43 27 9f 66 9b |.Z.=..Q<q(.C'.f.| +00000230 ec 49 0f a4 12 f5 a3 96 cd 3e 05 5b 9c d0 07 6f |.I.......>.[...o| +00000240 8a 11 df 2f be a7 1d 0d 9f a8 04 41 3d 5e 1b f6 |.../.......A=^..| +00000250 b0 10 9b 6a 49 da 6c f9 6c 6e 2e 6c 9b cf f1 fe |...jI.l.ln.l....| +00000260 49 92 2b 16 3f 63 ef 87 71 9c da 0d 49 63 2a 4c |I.+.?c..q...Ic*L| +00000270 b5 82 c8 b0 75 5b 7b 89 39 cd 9a da dc 42 d1 1f |....u[{.9....B..| +00000280 92 61 e1 71 b9 b5 d2 40 3c 7a 4a 8d 91 1f e6 9d |.a.q...@<zJ.....| +00000290 79 37 71 3c dc a3 98 0b b3 64 39 74 f1 8f 84 35 |y7q<.....d9t...5| +000002a0 1d 6b b7 0a f9 aa 26 55 a8 39 7f 11 26 18 98 fe |.k....&U.9..&...| +000002b0 94 fb 5d e4 a1 2f 0f 3b f0 b6 78 d5 87 32 73 6e |..]../.;..x..2sn| +000002c0 3e b1 3e 3c 19 31 7a ae d8 73 67 96 56 9c 38 a6 |>.><.1z..sg.V.8.| +000002d0 bc 39 1f 11 74 ad 69 c6 d2 40 0f 65 d8 ee aa 87 |.9..t.i..@.e....| +000002e0 b3 4c 6c 1a 1d 62 4a 7a d9 15 05 54 0d 8a 22 68 |.Ll..bJz...T.."h| +000002f0 8e 41 22 b0 ee 41 b3 94 5d 1a 62 d8 bb ac f2 87 |.A"..A..].b.....| +00000300 ad 91 19 e7 e1 bc 29 3b 96 8c d1 76 99 e5 82 48 |......);...v...H| +00000310 0b 87 6a 93 3b 2c b7 c1 73 07 53 7c 1f 9f 48 dd |..j.;,..s.S|..H.| +00000320 71 da 55 e1 4a a3 86 d2 ff 23 b2 1d ea b0 17 03 |q.U.J....#......| +00000330 03 00 99 75 af 84 36 54 8e 17 09 c7 2e 72 de 7d |...u..6T.....r.}| +00000340 29 5c 94 a9 e3 d3 d0 9b 3e a0 84 e6 cf b4 48 d8 |)\......>.....H.| +00000350 dd 7c 8a 82 96 15 aa cb 95 38 88 9e 48 c4 bf 75 |.|.......8..H..u| +00000360 9c f4 07 ed 5d 4d 36 8b 58 7f 9c 32 0b f9 d2 44 |....]M6.X..2...D| +00000370 3d d6 ab 3b 3d 38 1f 8d 7e e8 b6 26 57 c9 c6 98 |=..;=8..~..&W...| +00000380 49 4f 1e ad 5d fa 8b ca bc ce 99 f2 d9 5b 14 54 |IO..]........[.T| +00000390 56 0c 59 c8 22 9f 77 f1 db 92 43 c3 dd a5 29 ec |V.Y.".w...C...).| +000003a0 0d 79 0d b3 04 3f 4b 6b d6 a8 da 99 64 94 78 a5 |.y...?Kk....d.x.| +000003b0 e9 cd 7e f8 0c fb 72 d6 03 89 dd 00 13 f3 14 18 |..~...r.........| +000003c0 ba 59 3c 04 7f 6a b5 62 37 56 2e 2d 17 03 03 00 |.Y<..j.b7V.-....| +000003d0 35 af eb 05 4e ec ee 4b d6 6b 03 35 d8 ba a3 cf |5...N..K.k.5....| +000003e0 50 c6 80 07 90 92 1c ed 1f d2 d5 12 e3 7f 74 1a |P.............t.| +000003f0 2c 3b 4b 6c f4 58 af 9a 1a cd 90 f4 d8 78 97 09 |,;Kl.X.......x..| +00000400 2f f6 35 c1 29 b8 |/.5.).| >>> Flow 5 (client to server) -00000000 17 03 03 00 35 4b f7 dd b6 64 32 61 42 e7 b2 93 |....5K...d2aB...| -00000010 b8 4b dd 7c 25 c6 57 5b 68 d5 f2 d9 27 85 ee cf |.K.|%.W[h...'...| -00000020 09 44 79 8d 8e 14 0f 84 44 e5 16 a9 bf d9 14 bb |.Dy.....D.......| -00000030 22 73 c7 a9 24 c1 dd 38 1e 63 17 03 03 00 17 63 |"s..$..8.c.....c| -00000040 56 45 91 62 9c 00 4b d6 ae f4 dc 17 a2 89 55 0d |VE.b..K.......U.| -00000050 c3 d4 f3 12 8b bf 17 03 03 00 13 1f ac ed f8 80 |................| -00000060 31 7f 75 9f 6c a1 48 6e 20 89 b8 45 08 33 |1.u.l.Hn ..E.3| +00000000 17 03 03 00 35 8d 07 5a 33 f5 d1 e7 6d 71 48 45 |....5..Z3...mqHE| +00000010 3e 2a c0 7e 66 03 77 b5 69 b1 e5 13 04 0e 0d ea |>*.~f.w.i.......| +00000020 6f 80 46 a1 9a 54 09 6f a7 be b7 a3 a1 0c d4 ba |o.F..T.o........| +00000030 0e 7d 00 8f 1b 01 0b d4 6b 4c 17 03 03 00 17 b9 |.}......kL......| +00000040 fd 5a 5c a1 c2 33 71 63 99 25 bd 03 a3 24 a7 b6 |.Z\..3qc.%...$..| +00000050 e7 42 04 6a 81 c5 17 03 03 00 13 b6 4a f1 0a 26 |.B.j........J..&| +00000060 95 e8 fb 4b d1 db 24 95 8f 65 1f 3c 5d b9 |...K..$..e.<].| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv13-KeyUpdate b/libgo/go/crypto/tls/testdata/Client-TLSv13-KeyUpdate index d1efba9..ea10f66 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv13-KeyUpdate +++ b/libgo/go/crypto/tls/testdata/Client-TLSv13-KeyUpdate @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 7b 00 05 00 05 01 00 00 00 00 00 0a 00 |...{............| 00000090 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................| 000000a0 00 00 0d 00 1a 00 18 08 04 04 03 08 07 08 05 08 |................| @@ -16,87 +16,87 @@ 000000e0 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 000000f0 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 |.........._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 a2 49 b5 61 fe |....z...v...I.a.| -00000010 e3 52 ca 87 58 57 0f ec bc 71 51 a9 50 7c ac 5e |.R..XW...qQ.P|.^| -00000020 af 4e 47 56 81 6c 92 d9 10 3d d0 20 00 00 00 00 |.NGV.l...=. ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 86 ed 46 3d 38 |....z...v....F=8| +00000010 c5 47 10 b5 4e ac e5 b7 d7 ba cc 23 db f5 0a f4 |.G..N......#....| +00000020 5e d3 62 af 47 8a 23 34 59 5c db 20 00 00 00 00 |^.b.G.#4Y\. ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 01 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 75 |..+.....3.$... u| -00000060 c4 ba b0 c4 9b a0 57 6a ca e4 9c c6 eb f8 66 5a |......Wj......fZ| -00000070 d4 64 36 34 71 9d 6d 0f 2f 34 b8 ad b7 4a 55 14 |.d64q.m./4...JU.| -00000080 03 03 00 01 01 17 03 03 00 17 ec 4c 36 aa 81 cf |...........L6...| -00000090 61 2c 2f 6c 35 e8 25 62 54 17 ae 9b 46 b0 96 f5 |a,/l5.%bT...F...| -000000a0 0f 17 03 03 02 6d 6f 6c 27 e5 53 42 db 32 b4 2c |.....mol'.SB.2.,| -000000b0 6a 70 56 a7 0d 3a 7f a3 d7 fe 04 4f 0a 3e 52 8c |jpV..:.....O.>R.| -000000c0 52 1e 3a 26 5d 47 b1 6b da 90 e2 74 50 0d 6e fa |R.:&]G.k...tP.n.| -000000d0 1b 3f 17 3b 21 f7 fa f7 c7 c3 e3 14 05 09 76 b2 |.?.;!.........v.| -000000e0 27 66 bc 42 7e 49 4b ff 3a f1 3f a3 1a d4 9e 03 |'f.B~IK.:.?.....| -000000f0 3f b6 a8 87 98 50 f3 d8 cb 8b a2 e9 2a ea ff bc |?....P......*...| -00000100 50 18 d0 57 58 c5 e9 c8 96 67 01 8b e2 a3 f4 77 |P..WX....g.....w| -00000110 5e 1d 93 89 b6 f6 57 7d 93 b6 62 86 0a 21 18 56 |^.....W}..b..!.V| -00000120 8c 14 25 df 47 1a b3 23 e6 99 d1 fc dc 07 0a 38 |..%.G..#.......8| -00000130 9a 05 c8 3f 23 5c c5 d3 c4 48 fb b2 fd 9f 83 37 |...?#\...H.....7| -00000140 1d 0c 85 9c 2b e6 ae 42 aa ad d4 5a 9e 49 89 b7 |....+..B...Z.I..| -00000150 b0 c2 c5 ec 42 89 88 87 6e 54 3d 73 b2 f1 5f 0f |....B...nT=s.._.| -00000160 4b 49 3f 6b a3 8f 5f 99 bf fe af e9 25 ac 27 b7 |KI?k.._.....%.'.| -00000170 e7 96 bb 4a c8 e8 9e f1 2c 23 c2 e7 96 ba b4 fe |...J....,#......| -00000180 d5 94 b5 72 82 bd 7f c2 e1 af b4 bd db c7 15 20 |...r........... | -00000190 85 60 bb 02 f6 4b ef 09 3e a1 4e b9 77 64 0a 4a |.`...K..>.N.wd.J| -000001a0 2c 05 82 96 91 be 23 44 50 c1 c5 6c 05 55 51 42 |,.....#DP..l.UQB| -000001b0 84 87 20 71 65 8d 09 86 66 fa 88 8b 54 21 44 34 |.. qe...f...T!D4| -000001c0 df 6f ce a3 e9 12 4a e0 90 76 bb 1a f5 00 79 cb |.o....J..v....y.| -000001d0 d8 82 3b 88 c8 6a 5b a1 49 49 a0 c0 f7 d9 8f 89 |..;..j[.II......| -000001e0 f2 04 59 2b 0c 6f e2 3f b8 a8 c9 aa bf 2e 18 74 |..Y+.o.?.......t| -000001f0 45 b5 35 34 9a bb fa 77 e8 46 b2 f8 6d 41 65 36 |E.54...w.F..mAe6| -00000200 d9 f8 64 81 a6 50 63 b4 73 3e fb f9 b3 3e 03 3d |..d..Pc.s>...>.=| -00000210 d1 f4 b5 c1 ac f8 3f 4d 73 b7 da 16 8a 37 c9 a7 |......?Ms....7..| -00000220 51 33 b1 68 69 19 0b 26 de a6 42 4d 22 a3 e8 c0 |Q3.hi..&..BM"...| -00000230 7b 1d 66 e7 70 26 44 f7 62 3f 3d 0d e2 02 50 61 |{.f.p&D.b?=...Pa| -00000240 db 9b 5e e4 49 e8 32 32 7a c0 03 37 a8 c6 85 80 |..^.I.22z..7....| -00000250 4a 7e 39 b5 ba 6c cb 6f 53 e5 90 d0 0d 9c 2e e5 |J~9..l.oS.......| -00000260 90 df 9b b1 c5 3f 16 98 a9 dd a1 b5 7a 48 04 0e |.....?......zH..| -00000270 15 f9 60 a7 35 0b 33 a1 93 4b 73 5f b3 46 a6 43 |..`.5.3..Ks_.F.C| -00000280 ea a3 6e 4c fa bb 24 44 cd 48 85 c1 9f ea c2 14 |..nL..$D.H......| -00000290 92 48 2e 35 43 30 dc e6 76 23 0b e4 2f 28 13 c1 |.H.5C0..v#../(..| -000002a0 e1 bb 2d 9f de cf 10 8f c3 8f 48 eb 64 eb 6d ef |..-.......H.d.m.| -000002b0 2a b3 c5 d6 85 db a2 05 b2 46 f8 77 aa 2c fb 14 |*........F.w.,..| -000002c0 be 09 e7 11 33 88 cb 71 1b ca 46 cb 79 c6 99 eb |....3..q..F.y...| -000002d0 43 bb 59 c6 91 3b 0f 1a 76 cb c7 3b ef 07 c9 cb |C.Y..;..v..;....| -000002e0 3a 75 ac 14 d9 53 08 ca 4d 45 48 24 4a af 4e 94 |:u...S..MEH$J.N.| -000002f0 0e 81 31 63 d1 f6 67 25 7d c0 dd 02 05 1b ce 38 |..1c..g%}......8| -00000300 69 cf e7 6a bb b5 02 85 00 82 71 a6 e3 c0 33 b8 |i..j......q...3.| -00000310 78 51 55 17 03 03 00 99 b3 5c cb a4 a3 6c e9 fa |xQU......\...l..| -00000320 33 25 04 21 28 66 e7 d4 22 02 8f d4 3e cc e1 20 |3%.!(f.."...>.. | -00000330 15 5b 5a 55 14 d3 2b a5 de 7b 95 48 3c 26 68 22 |.[ZU..+..{.H<&h"| -00000340 a3 0d c6 ac 7f ec d3 7b fa 4d 51 20 6f 32 97 bc |.......{.MQ o2..| -00000350 fa 0c d6 8e bf ee 13 ca b3 cf 00 c5 f5 87 f1 cb |................| -00000360 9b 63 22 e6 61 99 83 78 69 1d 03 f1 0b 66 c5 c4 |.c".a..xi....f..| -00000370 2e 6f d8 b5 59 93 f7 40 3c 40 4e 1a 58 af b5 37 |.o..Y..@<@N.X..7| -00000380 ce dd 83 dd b1 78 a8 ba a3 35 f8 9f 0c 47 1e fb |.....x...5...G..| -00000390 aa 9b b5 5f 11 4c b9 0c c1 a0 01 47 87 f9 e6 1f |..._.L.....G....| -000003a0 d5 e5 3f a7 15 4d c8 a5 79 9c e5 bc 62 6f cb cd |..?..M..y...bo..| -000003b0 86 17 03 03 00 35 e7 4d 67 3a 39 5b ac 13 89 cc |.....5.Mg:9[....| -000003c0 c4 dc 20 2b a4 b2 3c 5d 96 f1 45 17 52 12 ed 85 |.. +..<]..E.R...| -000003d0 00 f0 7e 73 3a 6d a2 46 b8 59 7f e8 6f 46 06 e1 |..~s:m.F.Y..oF..| -000003e0 43 c9 ca af a9 3e ca d6 42 4b 41 |C....>..BKA| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 e3 |..+.....3.$... .| +00000060 ff 35 33 31 c9 d8 5c 68 2a e5 73 98 4d 11 5b d7 |.531..\h*.s.M.[.| +00000070 06 18 a9 dd 0e 4a 21 92 5b 15 8f bb 91 a9 6c 14 |.....J!.[.....l.| +00000080 03 03 00 01 01 17 03 03 00 17 ea ac f8 a0 41 47 |..............AG| +00000090 af 01 fb 51 2e ec 3b 79 f1 8a 54 2b 93 45 33 c3 |...Q..;y..T+.E3.| +000000a0 79 17 03 03 02 6d 0e c9 a4 55 8e 8c 09 55 cd a6 |y....m...U...U..| +000000b0 d4 dc 1e 5a de ee 56 c8 c2 ac 12 77 77 76 82 fc |...Z..V....wwv..| +000000c0 a6 44 cb c8 c3 16 c4 5e bc 3f f3 3b 6c 33 f3 35 |.D.....^.?.;l3.5| +000000d0 ed bd 8e 37 1a 25 de 7e b3 88 71 ce f9 e5 9b a6 |...7.%.~..q.....| +000000e0 99 11 0f 71 6b 36 11 04 66 a2 5f 74 1c c6 6a 99 |...qk6..f._t..j.| +000000f0 49 84 d1 36 96 df 6d 2c c5 a3 cf 5a c9 37 22 8a |I..6..m,...Z.7".| +00000100 72 e4 d4 25 ed 4a b1 c4 85 5a 9a f7 de 0b dd 41 |r..%.J...Z.....A| +00000110 7d 14 63 35 2e 1c 77 6c 9e 6f 41 d1 cb 29 ca 6d |}.c5..wl.oA..).m| +00000120 88 1c 35 53 1b 14 24 79 84 ec 85 0d de e3 0f 2c |..5S..$y.......,| +00000130 23 ae 41 72 85 fb 43 36 82 ba 8f 78 79 a2 c3 95 |#.Ar..C6...xy...| +00000140 72 19 ea 1d 2f 29 0e d5 11 85 e4 cc 8c a5 f4 8e |r.../)..........| +00000150 39 ba 88 8f e1 5a 54 7c 53 8b a3 1a 44 9c ae 5b |9....ZT|S...D..[| +00000160 1f 0e ea 06 f1 8e 5f 22 d1 ef ee e1 4c b6 1a 26 |......_"....L..&| +00000170 db 53 96 e6 bc 0b 2f ee b7 fa 47 af 1e 9c f6 7b |.S..../...G....{| +00000180 81 97 0f c3 08 9b 2c a3 de bd f7 8a 1e 13 ad de |......,.........| +00000190 a5 fc 5f c7 7a 53 72 e5 17 dc 0a eb 90 91 29 2e |.._.zSr.......).| +000001a0 7a a5 09 fd be 31 ff 81 ec a3 fc 91 41 4f cb c7 |z....1......AO..| +000001b0 27 c3 39 8f cd 77 62 72 9a e9 e9 16 da 90 b6 6b |'.9..wbr.......k| +000001c0 05 70 c8 aa f5 cd 88 13 4d ff a5 a9 0f e7 d2 d3 |.p......M.......| +000001d0 97 2b eb e1 d7 fe 74 da fb 1e af 94 e6 52 18 48 |.+....t......R.H| +000001e0 5b e8 c3 10 9d 76 de 17 86 67 83 4a e9 fa 30 e8 |[....v...g.J..0.| +000001f0 46 95 f5 81 b1 a5 76 38 57 37 3a 8d df ad e7 30 |F.....v8W7:....0| +00000200 41 b2 94 31 da 0d d6 5c df 76 01 cd 4d c2 1b fe |A..1...\.v..M...| +00000210 bc 69 41 ac dd d7 dd 0a 7c 5b 31 5c c8 1e b3 14 |.iA.....|[1\....| +00000220 39 20 51 26 6d e5 55 27 a4 9a bb fc 3d 4b 6a b0 |9 Q&m.U'....=Kj.| +00000230 54 92 ee 33 1b 9b d5 41 fd ef 21 c6 f0 f8 90 a0 |T..3...A..!.....| +00000240 c4 f5 86 d4 d9 c7 89 6f 67 23 37 31 44 2f 8f 55 |.......og#71D/.U| +00000250 0a aa e1 9a ec 32 26 e2 ce 96 90 c6 f5 cc 95 79 |.....2&........y| +00000260 da 0c b4 c1 62 d3 0a 8d 7b 83 33 8e af ff 57 c0 |....b...{.3...W.| +00000270 5b ca 0f b5 64 10 81 43 12 86 67 cf b2 0a 53 f2 |[...d..C..g...S.| +00000280 04 46 4f 99 ee e2 cd ce 3e 82 1f 34 43 26 f9 4c |.FO.....>..4C&.L| +00000290 57 b0 10 c0 37 40 9c 4f fb 14 fa 4e 1e 4b 40 da |W...7@.O...N.K@.| +000002a0 cc c3 d0 d7 ee 63 18 2e 97 06 a6 49 69 07 7a 3e |.....c.....Ii.z>| +000002b0 da 47 68 70 b0 10 bf 8d 18 d2 14 c0 18 18 b2 61 |.Ghp...........a| +000002c0 45 54 e8 20 34 f8 a3 74 5a 8d aa c2 63 af e8 ff |ET. 4..tZ...c...| +000002d0 f9 1b 33 d6 34 c2 f2 c2 3d d8 0e 32 7a 10 cc 21 |..3.4...=..2z..!| +000002e0 02 22 a6 aa 7d 15 c3 7b 3f a2 50 5a 4e 53 ec f5 |."..}..{?.PZNS..| +000002f0 11 dd 48 6e 7e e9 c5 94 2c c4 9a 6e 10 a6 c6 a5 |..Hn~...,..n....| +00000300 9d e1 c5 43 e6 69 a1 91 65 50 eb e6 76 db f0 09 |...C.i..eP..v...| +00000310 14 45 ef 17 03 03 00 99 e4 82 99 6b d8 57 ca 1b |.E.........k.W..| +00000320 78 98 88 ad c7 04 b7 d2 b2 d5 00 3b a9 bf 86 66 |x..........;...f| +00000330 a7 30 72 95 29 2a 27 9f 9a 3d bd 0b e6 a0 04 22 |.0r.)*'..=....."| +00000340 56 3d d8 08 84 a7 e7 c5 67 74 34 7d 57 1f c9 df |V=......gt4}W...| +00000350 71 0c 97 55 5a d9 8d 99 df 49 b5 a9 57 6d b0 c7 |q..UZ....I..Wm..| +00000360 2d 4b 70 9d e7 e3 70 31 f0 2f 32 15 7b 67 b4 4c |-Kp...p1./2.{g.L| +00000370 f0 f0 4a 16 a5 37 b2 ae 9b 2a 72 7c 2e d8 22 a1 |..J..7...*r|..".| +00000380 2b 91 f2 14 fc f9 27 fd ca ad 27 dd 15 11 df b1 |+.....'...'.....| +00000390 cc 4c 3a 45 3f b6 7c 53 c5 d0 82 49 1a f2 28 63 |.L:E?.|S...I..(c| +000003a0 a2 be 6f 2f db d8 d3 76 0a 12 fa 87 14 00 11 e7 |..o/...v........| +000003b0 1f 17 03 03 00 35 0c af 49 a1 ba 14 d4 e5 5c cf |.....5..I.....\.| +000003c0 c8 f7 fb 93 e3 d5 45 ac 59 ed 56 3c 1c e6 53 6a |......E.Y.V<..Sj| +000003d0 77 62 a3 1a 8c 55 14 b0 d8 6f dd 1c fb a4 6f 25 |wb...U...o....o%| +000003e0 18 28 ab 9e a5 ad 6d 97 63 f4 9c |.(....m.c..| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 4d ad c5 c7 cc |..........5M....| -00000010 5a 34 8a f8 5f 71 83 af fa 94 df 2a 94 a0 c4 8e |Z4.._q.....*....| -00000020 5e 00 f7 02 e1 30 62 a5 49 27 58 0b 1f fa 46 98 |^....0b.I'X...F.| -00000030 f0 b8 6f 42 e3 3a 7f 26 77 b6 46 8f ab c6 5d d6 |..oB.:.&w.F...].| -00000040 17 03 03 00 17 90 81 68 7a 48 8d 3b 59 9e 11 6f |.......hzH.;Y..o| -00000050 86 b5 24 e4 d9 e0 60 9f c2 4f 3d 33 |..$...`..O=3| +00000000 14 03 03 00 01 01 17 03 03 00 35 12 2a a7 31 42 |..........5.*.1B| +00000010 e9 65 d6 88 9c 49 85 53 16 6c 85 bc d1 70 65 3a |.e...I.S.l...pe:| +00000020 aa cd d3 12 ce 69 e3 3a 63 7a 8d ed 54 df 9c 97 |.....i.:cz..T...| +00000030 4e ef 7c 20 ce 41 ac 33 a9 3b fc 5e 35 34 65 00 |N.| .A.3.;.^54e.| +00000040 17 03 03 00 17 11 5f 88 3b 45 0e 4e 8a 26 43 a3 |......_.;E.N.&C.| +00000050 9e 77 10 76 8c e1 ed d3 19 f4 27 5f |.w.v......'_| >>> Flow 4 (server to client) -00000000 17 03 03 00 16 94 83 fa cc 66 b4 60 c0 c7 6d b3 |.........f.`..m.| -00000010 6e 8c 84 9d 89 76 61 3d 69 fd 29 |n....va=i.)| +00000000 17 03 03 00 16 7d 92 67 60 95 ba fa a0 5f 03 e9 |.....}.g`...._..| +00000010 2b e6 53 ed fb 6b 4f b9 e9 09 10 |+.S..kO....| >>> Flow 5 (client to server) -00000000 17 03 03 00 16 60 cb 39 3d 7d 79 01 88 93 bd bf |.....`.9=}y.....| -00000010 23 3b d1 f3 a4 5e 78 ea cd 0f 5e |#;...^x...^| +00000000 17 03 03 00 16 06 17 fb 4b 33 c7 06 d5 a9 40 e8 |........K3....@.| +00000010 c7 09 65 b2 5c 2d 45 2f bf 45 a8 |..e.\-E/.E.| >>> Flow 6 (server to client) -00000000 17 03 03 00 1a 88 13 b4 f1 5f cc 63 1e 99 9f 85 |........._.c....| -00000010 60 ff 0e 97 13 59 64 2a c3 0d 2b ac ca a2 25 |`....Yd*..+...%| +00000000 17 03 03 00 1a 04 5e c0 bb ad 6c 2f 65 61 5c 39 |......^...l/ea\9| +00000010 a9 e2 c4 9e 0e 4c 68 d2 a9 97 8a bf 95 39 3f |.....Lh......9?| >>> Flow 7 (client to server) -00000000 17 03 03 00 1d 4f f2 48 ea b8 d6 75 8e 97 ab 54 |.....O.H...u...T| -00000010 29 57 50 5b 59 40 59 d3 7a 3c 01 43 6a 33 30 bb |)WP[Y@Y.z<.Cj30.| -00000020 d4 40 17 03 03 00 13 18 fc b7 ac eb e7 52 6d f0 |.@...........Rm.| -00000030 d4 d3 03 c6 5f 4e ea e3 7b 4e |...._N..{N| +00000000 17 03 03 00 1d 1f 74 d0 fb ed fa 59 81 21 7e f0 |......t....Y.!~.| +00000010 41 c8 6e 6b 9f b6 1a 86 ad 2e ac 9e 3d 3b 66 c9 |A.nk........=;f.| +00000020 4a 87 17 03 03 00 13 7b 76 c4 85 c1 41 47 6d 35 |J......{v...AGm5| +00000030 98 86 02 d5 3b e4 6b 4c 3e 7a |....;.kL>z| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv13-P256-ECDHE b/libgo/go/crypto/tls/testdata/Client-TLSv13-P256-ECDHE index e6d8118..db87bef 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv13-P256-ECDHE +++ b/libgo/go/crypto/tls/testdata/Client-TLSv13-P256-ECDHE @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 96 00 05 00 05 01 00 00 00 00 00 0a 00 |................| 00000090 04 00 02 00 17 00 0b 00 02 01 00 00 0d 00 1a 00 |................| 000000a0 18 08 04 04 03 08 07 08 05 08 06 04 01 05 01 06 |................| @@ -18,77 +18,77 @@ 00000100 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 |..lK[.V.2B.X..I.| 00000110 b5 68 1a 41 03 56 6b dc 5a 89 |.h.A.Vk.Z.| >>> Flow 2 (server to client) -00000000 16 03 03 00 9b 02 00 00 97 03 03 b5 3c c8 fe 64 |............<..d| -00000010 f6 04 7d 28 a4 25 7c 1b f5 0b e6 6d 0b f5 2f ec |..}(.%|....m../.| -00000020 78 c1 bd 5a cf c8 19 d9 5c 54 72 20 00 00 00 00 |x..Z....\Tr ....| +00000000 16 03 03 00 9b 02 00 00 97 03 03 bb 03 f1 4e 88 |..............N.| +00000010 23 9e 85 ee 32 13 db 0d 69 11 48 47 c6 c9 e5 b2 |#...2...i.HG....| +00000020 25 9d 0c 27 87 05 3f 58 42 60 2d 20 00 00 00 00 |%..'..?XB`- ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 01 00 00 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| 00000050 4f 00 2b 00 02 03 04 00 33 00 45 00 17 00 41 04 |O.+.....3.E...A.| -00000060 d7 63 55 0e 0d 7b fb 09 a9 61 92 70 2b 52 9c 38 |.cU..{...a.p+R.8| -00000070 2d e8 2a 68 27 b7 15 3e 4a 1e 92 c8 08 7b 5c c9 |-.*h'..>J....{\.| -00000080 8d d4 aa 97 63 42 a5 3e 4b e8 7d 37 98 d9 8c a6 |....cB.>K.}7....| -00000090 e7 c7 45 9f 73 48 bd c3 14 82 67 5b bb 19 bd a5 |..E.sH....g[....| -000000a0 14 03 03 00 01 01 17 03 03 00 17 67 d9 cb 2b d1 |...........g..+.| -000000b0 d2 30 7d b3 3f c1 77 5a 6c 87 41 2c 29 83 36 19 |.0}.?.wZl.A,).6.| -000000c0 74 38 17 03 03 02 6d ac 0c 4f fe b5 93 6a fa 9f |t8....m..O...j..| -000000d0 e9 76 a7 c3 8a bb 4a 64 7a 04 35 58 e6 a2 d8 7a |.v....Jdz.5X...z| -000000e0 cf 99 1c 60 13 1a ca c6 e6 10 11 7a f1 f4 be ec |...`.......z....| -000000f0 1d 2d db b1 a5 3a dd 7e 10 2b 65 ca 40 b2 5f fc |.-...:.~.+e.@._.| -00000100 3f c9 df 7d 26 c1 fc b7 2d 67 a1 2d a2 22 b3 40 |?..}&...-g.-.".@| -00000110 79 d4 c8 b6 73 f7 93 8a 97 4f b7 ab b6 0c ca 14 |y...s....O......| -00000120 3c 1e 6c 27 c0 be 01 d7 98 ef 93 78 f5 14 15 21 |<.l'.......x...!| -00000130 4c f8 8e a6 f7 72 b2 b7 bc c2 3e 9b b7 e4 0d 15 |L....r....>.....| -00000140 b5 69 75 e9 61 10 e4 d5 8e 60 44 88 bf 5f df f9 |.iu.a....`D.._..| -00000150 8d 70 54 4e f6 0f 37 70 ff b8 6b c0 4f fb 61 c1 |.pTN..7p..k.O.a.| -00000160 48 00 96 9b da 05 0f 78 7a 87 f5 b1 69 f6 4f 8e |H......xz...i.O.| -00000170 80 74 7b e0 e5 b7 0f ba 7d 9d 4c ff c9 d7 7c b9 |.t{.....}.L...|.| -00000180 f0 bd dd 34 8e 77 5f 3b 48 10 10 6f ed c7 84 15 |...4.w_;H..o....| -00000190 7a 0c 26 3e 5d 9d 58 07 02 8c e3 fa f0 6b 86 df |z.&>].X......k..| -000001a0 76 af 3c 13 c4 93 28 7a 17 04 98 91 26 72 5f aa |v.<...(z....&r_.| -000001b0 cf b2 9e 37 a9 93 12 bd 1d 92 64 b8 82 60 b0 b5 |...7......d..`..| -000001c0 1d 2c 4e 18 24 11 3b 52 33 05 f0 3b f2 27 ed a6 |.,N.$.;R3..;.'..| -000001d0 f6 4a 82 b6 df 05 a0 07 a3 9d 73 0a 3c 7f 02 47 |.J........s.<..G| -000001e0 60 c8 aa 20 b4 9c cd 48 12 a3 82 fe 99 4e 0c bb |`.. ...H.....N..| -000001f0 ec 4f 10 75 26 99 a4 ed 5e 4a 34 51 38 88 2c 3c |.O.u&...^J4Q8.,<| -00000200 0b 8d f8 65 84 38 47 c8 31 30 82 71 3f 54 e3 3f |...e.8G.10.q?T.?| -00000210 f1 e6 2c ef a3 fe 02 34 16 58 21 55 6e 0f 95 d3 |..,....4.X!Un...| -00000220 3e 18 e5 c4 fa 95 65 07 d8 4b 31 4b fa a7 85 74 |>.....e..K1K...t| -00000230 6c 1c a3 7c 7b c6 20 e0 1f 28 33 6d 61 93 d0 7d |l..|{. ..(3ma..}| -00000240 e7 c4 5c 27 c9 d9 ca f9 fe 21 6f 7f 05 34 37 54 |..\'.....!o..47T| -00000250 30 59 68 e1 04 36 60 52 d7 fc 4f 8c 67 f6 42 88 |0Yh..6`R..O.g.B.| -00000260 bc 41 5f 8e 2c 05 dd 6a b0 49 6c d8 8e 9c 9e 06 |.A_.,..j.Il.....| -00000270 35 f9 f1 33 f2 54 b0 3f 9e bd 4f c7 48 aa a3 9e |5..3.T.?..O.H...| -00000280 fe 69 79 16 e0 5a ca 48 72 fe 52 4a f1 6f f1 e0 |.iy..Z.Hr.RJ.o..| -00000290 8c fe 16 15 ce c9 87 dc 9b 66 4d 3a bb 05 21 82 |.........fM:..!.| -000002a0 21 65 cb 7b da 06 1a 0b 53 ee 60 e4 79 0f bc 5d |!e.{....S.`.y..]| -000002b0 b6 52 fd 3b 33 28 97 6c 67 d7 ab 3d b0 da bb ac |.R.;3(.lg..=....| -000002c0 0d d9 06 81 a3 6c 1f ad b8 05 20 63 2b c7 cb 4b |.....l.... c+..K| -000002d0 e2 96 6e 3d f1 9c 0a 6a c6 01 3e 3a d0 54 c8 09 |..n=...j..>:.T..| -000002e0 9b 17 a0 cc d6 d0 82 d1 02 a8 eb 9d 91 7e 30 b9 |.............~0.| -000002f0 3d 5e 6d 43 fc 50 f8 9f 80 67 7a e3 33 30 cd b7 |=^mC.P...gz.30..| -00000300 00 b3 bc 17 50 82 6c 80 67 bd c4 12 11 b1 53 22 |....P.l.g.....S"| -00000310 96 67 07 90 d4 54 5c f1 5d ca cd f8 b5 35 94 e0 |.g...T\.]....5..| -00000320 21 e6 58 d7 b0 32 ca 24 90 11 30 f5 2b 1d ca 3d |!.X..2.$..0.+..=| -00000330 6a 6d 35 fa 17 03 03 00 99 ad ab 79 79 28 a0 a9 |jm5........yy(..| -00000340 9a cd 6d 8d 8c 92 2e 83 3d d4 be c7 50 61 f5 49 |..m.....=...Pa.I| -00000350 97 6c ab 92 d4 a7 1a 6f fc 5b dd 6e 73 0d bd d2 |.l.....o.[.ns...| -00000360 09 52 9f c9 de bb 8d 09 0a 4f e0 c5 9a 08 79 4c |.R.......O....yL| -00000370 fc 01 b3 94 45 f6 1d bd 8d 23 62 14 14 65 4c 2a |....E....#b..eL*| -00000380 d9 ad 8f 76 5a 5e 9d da 68 37 c7 b1 54 1e b4 bd |...vZ^..h7..T...| -00000390 d3 15 b8 89 94 87 8b 17 17 0f 4c dc db a8 3b 2f |..........L...;/| -000003a0 e5 e2 25 d6 ec f6 f4 bb ab d0 c5 7f 2a cb c6 57 |..%.........*..W| -000003b0 84 50 3a e7 62 8b 76 ae 6a 06 6b 85 1c 23 f1 d1 |.P:.b.v.j.k..#..| -000003c0 10 e2 6f 57 8c 20 7d da 2d f8 bc c5 df 4e 7c 22 |..oW. }.-....N|"| -000003d0 d8 36 17 03 03 00 35 62 fa d4 65 7f 9a 97 5b ec |.6....5b..e...[.| -000003e0 25 4a 3a 43 18 08 08 fb 7f 9d 3b 73 64 9e f3 7a |%J:C......;sd..z| -000003f0 28 f1 a0 0e 00 7a 51 74 0e 6b 90 c6 39 7a 09 98 |(....zQt.k..9z..| -00000400 6e d8 63 cc 1f f0 8f bc 37 66 27 a0 |n.c.....7f'.| +00000060 85 3c 83 1b e5 02 e9 0d 89 cc c0 f7 af 1e ba af |.<..............| +00000070 de ad cb 8f 4d 58 04 40 c2 60 e9 41 8b 94 26 76 |....MX.@.`.A..&v| +00000080 73 64 c3 27 e3 51 9d 5f 21 97 59 a3 02 cc 20 61 |sd.'.Q._!.Y... a| +00000090 b7 ef cb bb d9 31 b6 b7 b1 77 ea 8d 69 13 13 48 |.....1...w..i..H| +000000a0 14 03 03 00 01 01 17 03 03 00 17 ab ac 2e 62 de |..............b.| +000000b0 b6 f4 c7 35 cf b4 75 fc a4 a5 2c 40 68 f5 48 80 |...5..u...,@h.H.| +000000c0 d2 8b 17 03 03 02 6d a9 36 b5 10 78 1f af 79 65 |......m.6..x..ye| +000000d0 dd ee 36 08 b9 96 e2 bf 09 53 c7 ee 12 19 1b de |..6......S......| +000000e0 96 25 cb a7 55 71 28 22 16 3f 4b 3e 15 a2 2e 57 |.%..Uq(".?K>...W| +000000f0 99 85 28 b2 01 16 3a 75 ff 5e 21 39 6c be fc bd |..(...:u.^!9l...| +00000100 24 33 ec c7 50 83 49 91 8a ed 43 38 b5 48 cd 92 |$3..P.I...C8.H..| +00000110 dd 9a f1 b7 90 61 3b 8f ff b9 cf 97 3d 8e 23 8e |.....a;.....=.#.| +00000120 d1 78 52 b4 ba a1 75 97 32 52 e3 1f c8 43 ca b7 |.xR...u.2R...C..| +00000130 89 46 e6 30 c2 c5 32 b3 5f a8 ea ea e2 31 d2 41 |.F.0..2._....1.A| +00000140 23 5e 64 a2 b9 23 27 73 b2 df 77 cd 04 8b dd 37 |#^d..#'s..w....7| +00000150 a5 77 df 0e 4f 9d 01 22 7b be 7a 0c 18 5c 8b 62 |.w..O.."{.z..\.b| +00000160 7c 6b 7e a7 54 8c 69 97 50 d7 cf a0 a4 cb 3a 3b ||k~.T.i.P.....:;| +00000170 76 7b 0a de 80 d1 40 c3 05 5e b3 4e 71 cd 03 82 |v{....@..^.Nq...| +00000180 d5 95 d0 38 ab 65 83 24 66 d2 31 2d 9e 58 16 87 |...8.e.$f.1-.X..| +00000190 b8 ab 4c 4e 75 40 7e 3d 33 2f f4 ed 0b a8 11 1c |..LNu@~=3/......| +000001a0 7a a4 b0 e3 6a 73 d0 6e e6 82 39 c1 cf 57 a4 9a |z...js.n..9..W..| +000001b0 8b fc bc 8e e8 6a c3 e1 b0 64 18 55 6d 19 30 25 |.....j...d.Um.0%| +000001c0 34 f8 b1 ef cf 3c 04 08 69 10 ad 08 67 5b 8d 64 |4....<..i...g[.d| +000001d0 eb 83 72 39 2e 56 e4 d2 e9 f2 da 40 3e 85 29 ab |..r9.V.....@>.).| +000001e0 5b 83 e5 b0 d2 9b eb c3 99 6e 2a f3 78 95 d4 7a |[........n*.x..z| +000001f0 7f bf 9c 16 55 77 43 4d 67 f7 4a 6f 40 27 a2 82 |....UwCMg.Jo@'..| +00000200 b9 86 05 5d 90 e2 52 a2 d4 7c 7b 3e da 30 c1 aa |...]..R..|{>.0..| +00000210 30 2e 9a 34 c5 59 dd db e9 25 67 da 22 47 f2 be |0..4.Y...%g."G..| +00000220 cc c8 5a 4e da cf ad 86 8d bd b0 68 26 69 ea 3a |..ZN.......h&i.:| +00000230 1c 1e 29 ae e1 09 63 88 f0 81 31 f9 70 a7 92 27 |..)...c...1.p..'| +00000240 32 9e 3b 6f 09 5e 42 20 53 88 bf 09 8b a8 17 5c |2.;o.^B S......\| +00000250 24 7c 18 1f 9c 99 9b db 6d 11 26 8e 92 2c a1 b4 |$|......m.&..,..| +00000260 5c 9f d9 0a a8 af 25 f7 84 f5 65 d1 b1 6c d8 aa |\.....%...e..l..| +00000270 49 c7 a6 13 47 2e 55 f4 2e de 3d 43 c1 15 8d 60 |I...G.U...=C...`| +00000280 c1 27 59 7e 7b 14 ee 54 09 fc 99 79 c9 bf fb 45 |.'Y~{..T...y...E| +00000290 2d 32 ed 1a 2c 84 bc f4 a2 b5 5f 4e cf 60 29 91 |-2..,....._N.`).| +000002a0 90 b6 ab 06 8f 2d 43 a5 a5 54 0d 67 52 c2 1c fb |.....-C..T.gR...| +000002b0 f3 41 b7 67 b4 50 05 86 19 75 93 8b 6c c3 bf 08 |.A.g.P...u..l...| +000002c0 64 f2 df ff 37 6d 2f 1e 3a 28 f4 ba 27 8d 61 d5 |d...7m/.:(..'.a.| +000002d0 79 70 19 82 99 7a e5 68 f3 c1 23 da 5d e1 98 b2 |yp...z.h..#.]...| +000002e0 69 ca 42 83 61 29 3f d9 20 51 f2 a9 ea 1c 0b 5a |i.B.a)?. Q.....Z| +000002f0 20 b0 af 70 cc c5 ad 72 6b 09 85 56 8a 26 86 cf | ..p...rk..V.&..| +00000300 4e 9a 56 97 5d 63 8d 1d 46 04 48 16 c9 1e 91 47 |N.V.]c..F.H....G| +00000310 74 53 28 51 7e 3c 84 a1 50 d6 f3 ac 31 ce 04 18 |tS(Q~<..P...1...| +00000320 81 38 0d c5 3d f5 d5 04 2f f0 96 9b 73 49 4c d6 |.8..=.../...sIL.| +00000330 89 d9 b9 be 17 03 03 00 99 3a 37 ed 2d 98 80 f9 |.........:7.-...| +00000340 d0 04 14 12 8c 63 45 cc 8d cb 29 5f 0e f0 86 ef |.....cE...)_....| +00000350 8d 6c d6 0f ef 66 99 91 e8 8c d7 7b 21 07 7e 96 |.l...f.....{!.~.| +00000360 84 f8 f9 5b 1b 39 8b 4f 16 ec 5c 69 7b 18 09 5d |...[.9.O..\i{..]| +00000370 95 f1 f3 73 4b 8f 84 66 ee 61 85 dd fe ea 36 df |...sK..f.a....6.| +00000380 e5 2a 71 ec 2d 7e 47 1c b7 79 2d 87 f8 dc 44 27 |.*q.-~G..y-...D'| +00000390 8a f1 13 6e df ca 59 79 9b 18 01 7e 31 bd 44 f7 |...n..Yy...~1.D.| +000003a0 8d ad 1c 97 e7 e1 b9 a6 17 d1 25 d1 b8 0d 04 bb |..........%.....| +000003b0 21 a4 08 db a2 08 87 5c 04 9a 11 fa c6 24 db 20 |!......\.....$. | +000003c0 42 79 9c 97 dd 6c d2 e7 24 b4 79 47 be f3 43 87 |By...l..$.yG..C.| +000003d0 0f 95 17 03 03 00 35 9e 7d 12 0e d6 0a e6 af a3 |......5.}.......| +000003e0 83 dd eb 08 73 2d 43 7e 81 85 51 4c d1 ad d0 77 |....s-C~..QL...w| +000003f0 8d 28 62 44 41 9c b0 e9 93 d7 3d 07 e4 e1 6e 4c |.(bDA.....=...nL| +00000400 a8 5b 4a 3f 58 3f 97 07 73 d7 5a 62 |.[J?X?..s.Zb| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 ba 59 57 3e a3 |..........5.YW>.| -00000010 cd 02 7f 7c c2 16 f5 6b ec 42 66 aa a2 7a 3d 47 |...|...k.Bf..z=G| -00000020 43 c9 02 4b a3 72 d0 4d fa f8 32 28 1a 19 16 6a |C..K.r.M..2(...j| -00000030 7c 0e 4a 75 80 94 34 fe 30 7b d0 52 15 48 10 30 ||.Ju..4.0{.R.H.0| -00000040 17 03 03 00 17 5d de 53 df 00 21 ca 6d 69 ff 45 |.....].S..!.mi.E| -00000050 2e 53 57 db 3f 8d d8 6c 5a e1 f8 cc 17 03 03 00 |.SW.?..lZ.......| -00000060 13 43 d9 94 95 41 af 1d 80 a7 f2 28 2a 44 50 8d |.C...A.....(*DP.| -00000070 41 8f 82 09 |A...| +00000000 14 03 03 00 01 01 17 03 03 00 35 df 31 1a 84 e2 |..........5.1...| +00000010 93 54 01 f2 d1 e8 32 6c 32 91 e5 64 86 68 ad 5f |.T....2l2..d.h._| +00000020 aa 24 54 86 b2 39 92 24 06 65 5c 06 67 43 7d 09 |.$T..9.$.e\.gC}.| +00000030 79 78 c6 f3 cf 6c a9 ec 38 e3 ec 81 c4 9b c5 33 |yx...l..8......3| +00000040 17 03 03 00 17 25 ed 98 67 8f ad e8 60 ce 5b ad |.....%..g...`.[.| +00000050 ab 3e 67 64 e3 8d bf 98 96 a2 3d 99 17 03 03 00 |.>gd......=.....| +00000060 13 9d 28 f2 24 fe d6 11 b0 64 d6 8a 8d c1 81 e0 |..(.$....d......| +00000070 17 d5 a0 f3 |....| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv13-X25519-ECDHE b/libgo/go/crypto/tls/testdata/Client-TLSv13-X25519-ECDHE index 4e3eb76..4a43382 100644 --- a/libgo/go/crypto/tls/testdata/Client-TLSv13-X25519-ECDHE +++ b/libgo/go/crypto/tls/testdata/Client-TLSv13-X25519-ECDHE @@ -3,10 +3,10 @@ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 00 |........... ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a8 |.............2..| -00000050 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| -00000060 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| -00000070 c0 12 00 0a 00 05 c0 11 c0 07 13 01 13 03 13 02 |................| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 32 cc a9 |.............2..| +00000050 cc a8 c0 2b c0 2f c0 2c c0 30 c0 09 c0 13 c0 0a |...+./.,.0......| +00000060 c0 14 00 9c 00 9d 00 2f 00 35 c0 12 00 0a c0 23 |......./.5.....#| +00000070 c0 27 00 3c c0 07 c0 11 00 05 13 03 13 01 13 02 |.'.<............| 00000080 01 00 00 75 00 05 00 05 01 00 00 00 00 00 0a 00 |...u............| 00000090 04 00 02 00 1d 00 0b 00 02 01 00 00 0d 00 1a 00 |................| 000000a0 18 08 04 04 03 08 07 08 05 08 06 04 01 05 01 06 |................| @@ -16,75 +16,75 @@ 000000e0 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......| 000000f0 c2 ed 90 99 5f 58 cb 3b 74 |...._X.;t| >>> Flow 2 (server to client) -00000000 16 03 03 00 7a 02 00 00 76 03 03 5d 2e e6 ba 34 |....z...v..]...4| -00000010 6c 42 bb 48 58 fe c5 f0 95 f9 34 11 04 b5 2a f4 |lB.HX.....4...*.| -00000020 f1 16 41 db 14 a0 19 d8 43 7c 09 20 00 00 00 00 |..A.....C|. ....| +00000000 16 03 03 00 7a 02 00 00 76 03 03 eb 1b 4e e5 65 |....z...v....N.e| +00000010 54 ab 07 68 1c d9 32 0f 0e c2 ae a3 2a 89 37 50 |T..h..2.....*.7P| +00000020 23 51 61 7d 68 60 34 0d 40 2f b8 20 00 00 00 00 |#Qa}h`4.@/. ....| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 01 00 00 |................| -00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 82 |..+.....3.$... .| -00000060 de 1b d1 83 7a e1 46 cc c7 36 15 62 48 07 6b f6 |....z.F..6.bH.k.| -00000070 eb 0a 53 a3 34 cd 34 ee cc 0c d0 c9 02 d5 38 14 |..S.4.4.......8.| -00000080 03 03 00 01 01 17 03 03 00 17 3d 0c 61 12 1b 55 |..........=.a..U| -00000090 6e f4 13 59 c8 4a e7 12 63 5d bf be 34 9f d7 2a |n..Y.J..c]..4..*| -000000a0 c2 17 03 03 02 6d 82 e8 43 93 e4 80 4d a7 d2 cf |.....m..C...M...| -000000b0 43 9d 71 8d cc 78 e8 e9 58 7e 28 53 57 6d 95 1e |C.q..x..X~(SWm..| -000000c0 fb 98 05 ec 66 47 d9 a1 6a b5 f4 28 09 4a 6c 4c |....fG..j..(.JlL| -000000d0 ee a0 1a 86 e7 29 c0 0e d8 e0 ca 2d bb 50 e4 34 |.....).....-.P.4| -000000e0 8d 66 be 54 b5 df 94 fc 69 0e a6 9a 76 8b 8f f5 |.f.T....i...v...| -000000f0 a9 01 1a 1d 8d b0 ae a9 0c 10 58 13 f9 91 80 43 |..........X....C| -00000100 69 f8 3f 03 14 8e 73 1a ce 52 72 86 3d 60 8b 0f |i.?...s..Rr.=`..| -00000110 38 e7 4b 43 f0 b3 4b 12 3a a7 cd 4b ac ef 7d fb |8.KC..K.:..K..}.| -00000120 27 3a 38 36 ad a5 90 eb 57 80 47 99 bc c6 58 55 |':86....W.G...XU| -00000130 15 6f 53 f7 83 ca 2b 89 ae be 23 9a 83 3c 6b b1 |.oS...+...#..<k.| -00000140 10 67 a2 c4 65 e0 3a 25 05 4a 5b dc 10 96 93 b8 |.g..e.:%.J[.....| -00000150 72 7b 1f 07 6d c7 48 c4 86 b5 a5 cd bf 6f d4 98 |r{..m.H......o..| -00000160 bc 71 5b 39 36 67 9b 1a 88 a1 74 c4 7d 34 7c 1b |.q[96g....t.}4|.| -00000170 a7 31 c1 04 77 b7 cd 30 8e 69 6c 99 c4 9f 0b b8 |.1..w..0.il.....| -00000180 e4 53 03 b9 86 12 61 b0 fe 0e 37 df 99 77 00 3f |.S....a...7..w.?| -00000190 d4 10 c9 73 eb a2 9a 00 d6 cd 6a 5e 67 ec 55 ca |...s......j^g.U.| -000001a0 26 89 2f 11 9d 30 8f bd 5a 68 55 20 f5 93 44 5e |&./..0..ZhU ..D^| -000001b0 1f f2 24 20 fa 80 94 c7 01 62 c2 95 d3 18 c6 2c |..$ .....b.....,| -000001c0 00 42 fa ee 32 75 27 5f df 81 f2 14 83 30 cd 25 |.B..2u'_.....0.%| -000001d0 1d 6c 3a c5 f5 3f 6e b7 6a f0 cf 02 f9 a3 8d da |.l:..?n.j.......| -000001e0 96 55 31 2c 3c ef 62 c0 19 ac 36 f3 89 44 a4 a4 |.U1,<.b...6..D..| -000001f0 60 c3 99 b5 db 9f c7 4c 9d fb f1 77 98 dc 90 0e |`......L...w....| -00000200 8a e2 0e e2 6a 25 6e 84 2b d6 dc 73 57 7a 6e 1d |....j%n.+..sWzn.| -00000210 41 2e d0 de 45 ab 49 f0 e3 64 e4 6a 02 fa 64 6f |A...E.I..d.j..do| -00000220 09 22 05 b5 0c 12 b0 57 e2 61 5a 63 b1 4c a4 e5 |.".....W.aZc.L..| -00000230 79 c4 42 17 36 f0 0c 43 04 a5 d7 7c 3f 59 17 38 |y.B.6..C...|?Y.8| -00000240 f0 f1 2c 2d be 6c 4e 58 e5 45 c9 c2 d6 df 7b b3 |..,-.lNX.E....{.| -00000250 08 50 db e6 a8 ae 73 f2 82 09 6e 58 07 d3 87 e4 |.P....s...nX....| -00000260 c2 70 c6 8f 8f 13 74 09 b1 7d 1a 42 e1 d1 72 41 |.p....t..}.B..rA| -00000270 bd 71 cc f4 6c 7f 70 a2 99 95 34 b7 2c 08 af 43 |.q..l.p...4.,..C| -00000280 43 ec 61 66 51 73 e2 87 b3 f3 ef ee 20 f2 55 58 |C.afQs...... .UX| -00000290 c7 1a 0c ad dd 7b 44 9f f1 ff 5e 2b 18 63 e1 45 |.....{D...^+.c.E| -000002a0 88 5d c1 ce cb dc 42 ec 10 03 d4 d7 ae 2f ed ce |.]....B....../..| -000002b0 49 01 e3 1e de b0 68 ce 25 e0 69 b1 33 37 3d 0f |I.....h.%.i.37=.| -000002c0 b6 96 7e cd 7e 91 fb 82 a2 b8 66 6b 9a 44 83 c7 |..~.~.....fk.D..| -000002d0 56 86 87 a5 f2 b1 06 16 a3 43 e1 29 fe f7 26 c9 |V........C.)..&.| -000002e0 39 ea a4 b0 62 7b d5 9e 8a 0f 89 07 f9 a0 fc 45 |9...b{.........E| -000002f0 bf ce 70 1d 75 7f fa db 2a 5b 32 02 bb 69 cc 72 |..p.u...*[2..i.r| -00000300 cf 24 3d 92 20 d9 2f ee a5 9d 72 33 23 f5 99 f5 |.$=. ./...r3#...| -00000310 b1 82 eb 17 03 03 00 99 01 f0 87 1b 28 83 73 0f |............(.s.| -00000320 67 c8 76 69 e7 e6 ae d4 5c fc e0 e7 1c 6b 85 de |g.vi....\....k..| -00000330 de a0 9e 6c 1a 7d 90 31 d8 63 92 a1 bc f3 47 54 |...l.}.1.c....GT| -00000340 c4 00 b9 62 30 db 1d 5b c9 d5 e5 58 67 5e ab 68 |...b0..[...Xg^.h| -00000350 3a 41 65 11 8d 9b a2 8c 4f e7 b7 76 ca c6 ca 2e |:Ae.....O..v....| -00000360 2d 6b 7b d1 90 41 9f 0c c6 a5 18 4d d2 99 49 0b |-k{..A.....M..I.| -00000370 24 ab c5 84 cd a1 79 0a 0f 48 f3 f6 a4 f3 44 f3 |$.....y..H....D.| -00000380 42 cb eb 6d 7d 16 b8 42 43 37 78 d9 e3 47 ce ee |B..m}..BC7x..G..| -00000390 c9 4b 3d 4f 47 ab 77 15 45 59 dd 31 02 f9 f8 60 |.K=OG.w.EY.1...`| -000003a0 41 c6 dc e2 e3 25 8f 43 dd 77 c4 ce ba b9 63 c7 |A....%.C.w....c.| -000003b0 5e 17 03 03 00 35 2a d8 c8 91 25 bb 27 c2 fc cd |^....5*...%.'...| -000003c0 b3 d0 c2 57 70 39 fc 81 d7 11 01 6c 72 ca 58 19 |...Wp9.....lr.X.| -000003d0 c1 5d 72 9e 72 dc 70 2a 3d 1f 35 1c 05 4f 51 26 |.]r.r.p*=.5..OQ&| -000003e0 30 72 97 a5 7a 7a 0a 7b 9e 91 03 |0r..zz.{...| +00000040 00 00 00 00 00 00 00 00 00 00 00 00 13 03 00 00 |................| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 17 |..+.....3.$... .| +00000060 7d df 14 8a ad 43 51 c3 c2 08 3a ea f7 e3 96 6a |}....CQ...:....j| +00000070 b7 8b 61 66 d9 82 c5 7b b9 77 bc 62 6a 19 04 14 |..af...{.w.bj...| +00000080 03 03 00 01 01 17 03 03 00 17 4e 7b b6 d1 b1 19 |..........N{....| +00000090 0d 0c d0 d3 5a 66 44 5c 81 49 74 f3 71 3b 97 5e |....ZfD\.It.q;.^| +000000a0 ee 17 03 03 02 6d 00 17 b1 4d b9 f5 fc ea 48 72 |.....m...M....Hr| +000000b0 aa a5 1c 8b fe 97 08 54 ab 2d 0a 0e f7 51 41 bf |.......T.-...QA.| +000000c0 7b 14 ba b7 d9 0a 30 44 db b9 06 e7 6b a9 0a 94 |{.....0D....k...| +000000d0 49 a2 29 50 f2 7f 7e 68 91 41 ad a9 cb ee e2 bd |I.)P..~h.A......| +000000e0 03 fd 95 79 ea c3 77 ee 88 3b 7a 81 15 9f 17 96 |...y..w..;z.....| +000000f0 b2 db b9 f3 26 dd 75 69 ef 12 c0 63 b0 04 63 ae |....&.ui...c..c.| +00000100 aa b3 67 f8 7f a5 17 cf 56 5f ee 34 2d d7 83 23 |..g.....V_.4-..#| +00000110 84 00 4b 94 1a 76 2a 01 ce 49 0a 57 7d c8 65 7a |..K..v*..I.W}.ez| +00000120 d7 16 34 1c a8 37 fd 71 d4 79 08 b1 44 9f 9e a7 |..4..7.q.y..D...| +00000130 78 ab 9d 0d c4 80 0e 81 35 75 23 59 89 1b 2c d3 |x.......5u#Y..,.| +00000140 bc c9 86 b9 7b 22 19 30 dd cc 68 93 ab d2 98 dd |....{".0..h.....| +00000150 c2 9f 20 af c9 1a 87 b3 28 73 84 83 ca 98 1d 60 |.. .....(s.....`| +00000160 df 12 19 70 80 f2 ff 20 64 b5 8c ef e2 e8 6a 5a |...p... d.....jZ| +00000170 df 8e ba 95 d8 2c c4 b6 4f a1 33 8c 8d a3 fc d3 |.....,..O.3.....| +00000180 c4 4b ba b2 6d 3a f7 da 38 23 5f 03 a7 92 13 76 |.K..m:..8#_....v| +00000190 12 73 26 17 30 e0 21 f1 16 8f a1 e5 6d f0 21 a8 |.s&.0.!.....m.!.| +000001a0 c6 25 64 86 95 5e 6f 4d 21 f0 f3 a3 27 23 2b 4b |.%d..^oM!...'#+K| +000001b0 90 03 ba 6c ce 9c 20 ed 69 15 76 cb 39 bc fd 44 |...l.. .i.v.9..D| +000001c0 10 b4 72 d5 44 9d f7 eb a4 b0 d5 07 20 a1 6b 71 |..r.D....... .kq| +000001d0 16 e4 f7 8f a0 d8 fa 86 db e6 ef eb 63 41 a0 17 |............cA..| +000001e0 83 71 0d 1c 4b ec 58 c3 90 9c ea 34 79 a7 91 43 |.q..K.X....4y..C| +000001f0 ad 3d ff 28 c8 b4 3e 7a b6 83 53 f4 99 0b 86 bc |.=.(..>z..S.....| +00000200 f2 cf ae 1d a7 5c 7f 57 d9 85 95 25 33 bb 4d 79 |.....\.W...%3.My| +00000210 25 2e 54 6d 5d 14 32 68 7d 6e 45 bd b1 e1 24 30 |%.Tm].2h}nE...$0| +00000220 c2 1c 45 b9 a2 42 ae b5 c6 6a 56 f9 8a 12 51 f9 |..E..B...jV...Q.| +00000230 61 a2 9d 56 98 09 8d ea 70 17 48 d8 23 48 ca 18 |a..V....p.H.#H..| +00000240 43 1e a2 bc 88 69 3d 45 95 89 cc f0 74 8d 88 36 |C....i=E....t..6| +00000250 5e a8 1b be 88 41 35 8d de a9 20 23 f3 5e ab c9 |^....A5... #.^..| +00000260 61 22 2e 86 54 2f c4 4a 60 04 c2 e3 b8 cf 1a 41 |a"..T/.J`......A| +00000270 a6 31 ab 7a b5 07 dc 54 82 89 b1 1f 9f 62 98 bc |.1.z...T.....b..| +00000280 bd 39 be 23 ed d5 bc 0d 8e a6 69 14 26 39 fe ed |.9.#......i.&9..| +00000290 98 c8 48 36 6c 8e 9f 93 57 7a ba 33 03 35 c6 de |..H6l...Wz.3.5..| +000002a0 55 03 63 e8 a4 53 08 0a b0 a7 3e a3 cb f2 df 3d |U.c..S....>....=| +000002b0 cd 59 df ee f6 45 2d 77 39 32 4a 1f 08 21 e7 db |.Y...E-w92J..!..| +000002c0 52 2a 06 86 e6 00 98 ca 9f a3 ad 0f 7f d3 25 6d |R*............%m| +000002d0 56 58 21 e2 39 59 56 15 74 4d 18 37 f5 40 29 db |VX!.9YV.tM.7.@).| +000002e0 de be 49 77 e0 2c 5c 6b ee b1 bd 4a ea 2a 07 94 |..Iw.,\k...J.*..| +000002f0 0f 21 7c bb 1f bd 3e ad 9e b6 95 7d 16 e8 f0 4e |.!|...>....}...N| +00000300 de e2 ca 9c 34 9f b8 e5 57 d5 b7 b5 8d 60 dd c2 |....4...W....`..| +00000310 ce 47 2c 17 03 03 00 99 37 37 20 49 98 44 f6 b4 |.G,.....77 I.D..| +00000320 58 54 ff 5e b0 05 22 8e c6 68 9a ae 49 51 e9 f1 |XT.^.."..h..IQ..| +00000330 71 75 cf 1a 79 da 33 f1 5f 7e a1 02 81 05 12 8b |qu..y.3._~......| +00000340 a3 a8 ad 87 ee f0 87 da f1 16 80 9d 2e fa 5a 22 |..............Z"| +00000350 a5 f5 b9 14 f5 8f 9b 35 87 ba 1a f7 c4 17 c8 f6 |.......5........| +00000360 a1 1e 28 cd fe 03 90 9f f0 81 d3 80 bb 4c 1a b1 |..(..........L..| +00000370 c6 11 de 19 a1 5a 3c 73 77 f0 70 b8 d1 38 16 f3 |.....Z<sw.p..8..| +00000380 64 d0 8e 9c fe 4d 83 48 dc 20 78 db 6a 65 3f f4 |d....M.H. x.je?.| +00000390 0f a0 70 cc 30 bb cd 86 51 0c 20 ea 59 a5 ed e8 |..p.0...Q. .Y...| +000003a0 72 d9 5e f3 c3 41 0b 19 f3 97 0f fc 77 42 6d 15 |r.^..A......wBm.| +000003b0 92 17 03 03 00 35 ac 97 30 a0 8a d8 d2 e6 4a 5b |.....5..0.....J[| +000003c0 f5 58 32 22 63 8e 36 2e 21 a2 30 33 ae 49 55 76 |.X2"c.6.!.03.IUv| +000003d0 cf c8 b3 3f 82 8d c3 0e ea 22 ec 8f 65 c8 c4 0d |...?....."..e...| +000003e0 bf cc 6a 86 e9 32 50 db 02 93 ec |..j..2P....| >>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 7d 5e 95 38 a2 |..........5}^.8.| -00000010 d3 f4 04 59 57 2a 1a 86 ac 12 8e 17 88 fb 52 25 |...YW*........R%| -00000020 1d 19 2c c5 ac 57 c9 bf af 07 e7 c1 4d f3 dd f0 |..,..W......M...| -00000030 13 ad a1 73 07 32 a4 c5 7c 9e ad 5a 88 59 57 4b |...s.2..|..Z.YWK| -00000040 17 03 03 00 17 e2 65 4f bd 1f bb 00 a1 6b ae a4 |......eO.....k..| -00000050 9d d3 d2 6e 7b 62 b5 09 19 d6 8f 1b 17 03 03 00 |...n{b..........| -00000060 13 96 de 94 2b a7 bb c5 4b 7e 02 b2 27 07 4d 49 |....+...K~..'.MI| -00000070 32 2b 83 48 |2+.H| +00000000 14 03 03 00 01 01 17 03 03 00 35 e5 27 80 72 fd |..........5.'.r.| +00000010 6c 0d b5 a7 14 23 08 0b f5 54 70 8c 29 61 d0 2a |l....#...Tp.)a.*| +00000020 81 2d 05 83 2a 21 1e 16 94 5b 65 0d 6a ca b6 81 |.-..*!...[e.j...| +00000030 d9 9d 3c 5c 9c fe 2b 01 a8 3b 23 fb 9e eb 2c 56 |..<\..+..;#...,V| +00000040 17 03 03 00 17 79 fd 43 29 72 96 e0 ad fd 7e 60 |.....y.C)r....~`| +00000050 94 51 8d 8a 6e 6a 5d 6c f3 0d 4b 74 17 03 03 00 |.Q..nj]l..Kt....| +00000060 13 a4 7c e1 31 71 61 82 e7 7d 28 0f 63 d7 ae 76 |..|.1qa..}(.c..v| +00000070 9c 71 37 cd |.q7.| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial b/libgo/go/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial index a5d9ee4..cb3b8da 100644 --- a/libgo/go/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial +++ b/libgo/go/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial @@ -1,11 +1,11 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 63 01 00 00 5f 03 01 7a df fa af 20 |....c..._..z... | -00000010 74 5a 83 3b 91 95 b4 9b 57 d8 6b f2 88 2a 68 e8 |tZ.;....W.k..*h.| -00000020 b8 9e e7 88 a6 c5 e7 59 08 ff 9b 00 00 12 c0 0a |.......Y........| -00000030 c0 14 00 39 c0 09 c0 13 00 33 00 35 00 2f 00 ff |...9.....3.5./..| -00000040 01 00 00 24 00 0b 00 04 03 00 01 02 00 0a 00 0c |...$............| -00000050 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 00 00 |.............#..| -00000060 00 16 00 00 00 17 00 00 |........| +00000000 16 03 01 00 67 01 00 00 63 03 01 41 69 16 b5 d5 |....g...c..Ai...| +00000010 c2 9d 36 2b 95 8e e5 41 9b 92 82 27 2a cc 4e 6e |..6+...A...'*.Nn| +00000020 5d f1 1b 58 49 3c 95 1d 8b 61 35 00 00 04 c0 14 |]..XI<...a5.....| +00000030 00 ff 01 00 00 36 00 00 00 0e 00 0c 00 00 09 31 |.....6.........1| +00000040 32 37 2e 30 2e 30 2e 31 00 0b 00 04 03 00 01 02 |27.0.0.1........| +00000050 00 0a 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 |................| +00000060 00 23 00 00 00 16 00 00 00 17 00 00 |.#..........| >>> Flow 2 (server to client) 00000000 16 03 01 00 3b 02 00 00 37 03 01 00 00 00 00 00 |....;...7.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| @@ -51,43 +51,43 @@ 00000290 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 |...=.`.\!.;.....| 000002a0 01 00 aa 0c 00 00 a6 03 00 1d 20 2f e5 7d a3 47 |.......... /.}.G| 000002b0 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af |.bC.(.._.).0....| -000002c0 c4 cf c2 ed 90 99 5f 58 cb 3b 74 00 80 bb 96 fe |......_X.;t.....| -000002d0 bf a0 81 24 bc 40 b4 e2 37 b1 c9 66 2d c3 c1 bb |...$.@..7..f-...| -000002e0 89 fb 28 23 60 76 b1 e6 2c c1 e9 06 d0 95 c5 10 |..(#`v..,.......| -000002f0 17 ce 79 36 c2 14 e0 1d 1d 0d 0e 49 3e b9 7f 00 |..y6.......I>...| -00000300 ad e3 1d 37 ab ce 2c 37 dc eb be aa 6c 28 33 05 |...7..,7....l(3.| -00000310 53 fd 06 17 b4 85 b9 b8 35 1c a7 3c bb 07 3f 4b |S.......5..<..?K| -00000320 53 98 00 4d 8e 49 bd 35 55 64 92 d0 a0 db 05 80 |S..M.I.5Ud......| -00000330 57 24 78 cd 10 ed ae f0 6a 83 bc b4 4d 77 79 ba |W$x.....j...Mwy.| -00000340 6e e7 2e 8f ac 9e 98 34 36 9d a9 27 f0 16 03 01 |n......46..'....| +000002c0 c4 cf c2 ed 90 99 5f 58 cb 3b 74 00 80 c6 ad e2 |......_X.;t.....| +000002d0 21 0d d7 30 42 da 08 52 d5 46 70 a3 e5 d6 40 ab |!..0B..R.Fp...@.| +000002e0 bf 52 f8 da a5 41 86 1d 48 e6 51 91 52 8d 3c 5d |.R...A..H.Q.R.<]| +000002f0 ca 36 4c 62 d1 6b c8 48 8c 99 50 89 a9 27 4b 21 |.6Lb.k.H..P..'K!| +00000300 c9 9d a6 43 34 d2 47 a7 b3 1a 6d 98 b3 7f 37 94 |...C4.G...m...7.| +00000310 60 ba 88 f1 b7 ed 34 2b 47 f4 80 27 d3 a0 74 6a |`.....4+G..'..tj| +00000320 c6 d6 49 e3 8a e5 5d f1 a7 54 8a b4 84 8d a8 6b |..I...]..T.....k| +00000330 3b 7a 3f eb 81 77 4b bf be 1e ac cd aa f9 4b 79 |;z?..wK.......Ky| +00000340 24 78 6c 67 14 13 ab f8 ad 33 7c 94 38 16 03 01 |$xlg.....3|.8...| 00000350 00 04 0e 00 00 00 |......| >>> Flow 3 (client to server) -00000000 16 03 01 00 25 10 00 00 21 20 00 ad c5 2b 21 7f |....%...! ...+!.| -00000010 8e 44 f2 f5 32 22 c8 c2 c6 de 2c 0b 7a a9 24 b6 |.D..2"....,.z.$.| -00000020 03 20 c0 cc 79 2e 11 2f d3 43 14 03 01 00 01 01 |. ..y../.C......| -00000030 16 03 01 00 30 78 5c 32 72 a1 c8 3b 9c 7b 77 0b |....0x\2r..;.{w.| -00000040 a0 28 52 55 17 16 d5 39 89 d0 43 bf 67 29 85 6f |.(RU...9..C.g).o| -00000050 b5 1e 83 fa 22 96 78 e3 5c 45 5a 3d fe 2b d5 b7 |....".x.\EZ=.+..| -00000060 3d 64 44 8c a8 |=dD..| +00000000 16 03 01 00 25 10 00 00 21 20 f5 be 48 cb fb 0d |....%...! ..H...| +00000010 69 27 a8 ab 59 c4 9a ac 92 71 46 d1 17 7e 35 67 |i'..Y....qF..~5g| +00000020 15 b1 ea 9f 53 48 a3 b5 f9 55 14 03 01 00 01 01 |....SH...U......| +00000030 16 03 01 00 30 e1 79 95 7c ab 01 74 35 39 9b ce |....0.y.|..t59..| +00000040 79 5f 15 21 88 fc be fc 46 a9 31 ca 82 07 0c 1f |y_.!....F.1.....| +00000050 d8 2f 93 b5 5d 23 bf f9 10 40 bc b5 22 53 df d6 |./..]#...@.."S..| +00000060 b1 10 b9 16 96 |.....| >>> Flow 4 (server to client) 00000000 16 03 01 00 8b 04 00 00 87 00 00 00 00 00 81 50 |...............P| 00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.| 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| -00000030 6d ec a4 83 51 ed 14 ef 68 ca 42 c5 4c 5f bb 3b |m...Q...h.B.L_.;| -00000040 9c c8 3c 7e 1c cf dc da e4 35 83 03 13 95 82 5f |..<~.....5....._| -00000050 32 77 8a cf dc e9 10 65 9b 97 d4 5d ff 43 57 14 |2w.....e...].CW.| -00000060 a3 25 e0 fa c8 26 0c ff 71 67 9b 32 2f 49 38 16 |.%...&..qg.2/I8.| -00000070 aa ea b9 fa 99 86 4c b9 db 7a ef bc 87 43 e8 db |......L..z...C..| -00000080 26 27 73 76 80 77 59 c4 fb 7d 56 e9 7e 23 03 75 |&'sv.wY..}V.~#.u| -00000090 14 03 01 00 01 01 16 03 01 00 30 80 8f 8e 11 b5 |..........0.....| -000000a0 f4 a0 8c 4a ae 3f 25 17 66 93 1c c5 a5 10 57 e3 |...J.?%.f.....W.| -000000b0 24 7a c1 a9 72 74 4f fd 20 5e 5b 58 4d bd 5d f0 |$z..rtO. ^[XM.].| -000000c0 05 8e 06 61 0a 98 19 a0 a8 73 02 17 03 01 00 20 |...a.....s..... | -000000d0 d9 dd 86 e6 55 55 df 2c 0d 1e 5f 0e 9e 1e 76 51 |....UU.,.._...vQ| -000000e0 98 e0 2b 09 f9 44 4d 4d 22 97 0d 1e 95 7b b9 41 |..+..DMM"....{.A| -000000f0 17 03 01 00 30 74 82 1c 35 9b 87 cd 5e 29 95 e1 |....0t..5...^)..| -00000100 18 e3 76 32 94 b5 1b d0 06 d2 ec 49 40 24 73 d3 |..v2.......I@$s.| -00000110 fc 5d 1a 26 59 5b 33 d8 5a 30 d5 92 30 bc 80 e0 |.].&Y[3.Z0..0...| -00000120 ed 85 e8 14 01 15 03 01 00 20 ec 69 2f 9d 29 4f |......... .i/.)O| -00000130 1f 8e e6 34 f0 87 66 40 e8 13 14 02 74 c4 1d aa |...4..f@....t...| -00000140 65 72 43 50 6e 71 9c 2e b6 3a |erCPnq...:| +00000030 6d ec a4 83 51 ed 14 ef 68 ca 42 c5 4c d2 34 08 |m...Q...h.B.L.4.| +00000040 0b cc b9 32 8f 21 f7 50 c4 e1 28 9b 7d 5e ed de |...2.!.P..(.}^..| +00000050 0a df 30 0d 16 34 6b 6d 22 3c d3 c8 b2 99 84 8e |..0..4km"<......| +00000060 09 6d 3c 62 d4 0f f6 37 dc 53 ae 72 40 49 38 16 |.m<b...7.S.r@I8.| +00000070 9c 30 34 bf 6e 34 bb 54 73 33 c0 c9 8c 12 ae bc |.04.n4.Ts3......| +00000080 e9 a8 80 23 de d0 e5 d3 46 d8 6a 86 c7 a5 6c 61 |...#....F.j...la| +00000090 14 03 01 00 01 01 16 03 01 00 30 27 a7 5d e7 93 |..........0'.]..| +000000a0 54 9a 77 d5 43 aa e3 ec 21 00 fa d4 36 04 c3 82 |T.w.C...!...6...| +000000b0 b0 b7 f5 b4 19 ce f9 58 0a b4 7f d6 bf 95 43 9d |.......X......C.| +000000c0 26 44 46 77 48 cd 77 82 e2 48 51 17 03 01 00 20 |&DFwH.w..HQ.... | +000000d0 c0 9b b1 d3 9f e6 4f 55 59 17 5a dc e4 2f bc 04 |......OUY.Z../..| +000000e0 6f eb 4d d9 22 6e 97 20 33 94 d4 91 aa 70 4d ab |o.M."n. 3....pM.| +000000f0 17 03 01 00 30 9b 0f 50 a8 95 f5 db 67 96 c2 3e |....0..P....g..>| +00000100 46 a7 41 99 d5 e2 ab 60 b1 eb 8d 68 2f 71 30 70 |F.A....`...h/q0p| +00000110 75 cc b8 50 1a 58 3b 96 d3 5c 99 43 27 4f b1 4a |u..P.X;..\.C'O.J| +00000120 c8 8d 5b ab 49 15 03 01 00 20 34 a6 41 25 fd 23 |..[.I.... 4.A%.#| +00000130 44 6d 60 7f 79 5d 27 23 f7 cb 77 d0 cd 81 c4 67 |Dm`.y]'#..w....g| +00000140 0e 56 92 60 ac a1 32 a5 0d 94 |.V.`..2...| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-Fallback b/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-Fallback new file mode 100644 index 0000000..4fadf39 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-Fallback @@ -0,0 +1,91 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 a6 01 00 00 a2 03 03 b5 c9 ab 32 7f |..............2.| +00000010 e1 af 3f f2 ac 2a 11 dd 33 f9 b5 21 88 0d e4 29 |..?..*..3..!...)| +00000020 e2 47 49 dc c7 31 a8 a5 25 81 0c 00 00 04 cc a8 |.GI..1..%.......| +00000030 00 ff 01 00 00 75 00 0b 00 04 03 00 01 02 00 0a |.....u..........| +00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| +00000050 00 00 00 10 00 19 00 17 06 70 72 6f 74 6f 33 08 |.........proto3.| +00000060 68 74 74 70 2f 31 2e 31 06 70 72 6f 74 6f 34 00 |http/1.1.proto4.| +00000070 16 00 00 00 17 00 00 00 0d 00 30 00 2e 04 03 05 |..........0.....| +00000080 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 |................| +00000090 05 08 06 04 01 05 01 06 01 03 03 02 03 03 01 02 |................| +000000a0 01 03 02 02 02 04 02 05 02 06 02 |...........| +>>> Flow 2 (server to client) +00000000 16 03 03 00 3b 02 00 00 37 03 03 00 00 00 00 00 |....;...7.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 cc a8 00 00 |...DOWNGRD......| +00000030 0f 00 23 00 00 ff 01 00 01 00 00 0b 00 02 01 00 |..#.............| +00000040 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 |....Y...U..R..O0| +00000050 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 |..K0............| +00000060 f0 9d 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 |..?.[..0...*.H..| +00000070 0d 01 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 |......0.1.0...U.| +00000080 0a 13 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 |...Go1.0...U....| +00000090 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 |Go Root0...16010| +000000a0 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 |1000000Z..250101| +000000b0 30 30 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 |000000Z0.1.0...U| +000000c0 04 0a 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 |....Go1.0...U...| +000000d0 02 47 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d |.Go0..0...*.H...| +000000e0 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 |.........0......| +000000f0 db 46 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 |.F}...'.H..(!.~.| +00000100 b6 a2 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 |..]..RE.z6G....B| +00000110 5b c2 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 |[.....y.@.Om..+.| +00000120 8b c2 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 |....g....."8.J.t| +00000130 73 2b c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c |s+.4......t{.X.l| +00000140 61 3c c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd |a<..A..++$#w[.;.| +00000150 75 5d ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a |u]. T..c...$....| +00000160 50 8b aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 |P....C...ub...R.| +00000170 02 03 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 |........0..0...U| +00000180 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 |...........0...U| +00000190 1d 25 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......| +000001a0 06 08 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d |..+.......0...U.| +000001b0 13 01 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 |......0.0...U...| +000001c0 12 04 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 |.......CC>I..m..| +000001d0 d7 9f 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 |..`0...U.#..0...| +000001e0 48 13 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b |H.IM.~.1......n{| +000001f0 30 19 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 |0...U....0...exa| +00000200 6d 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a |mple.golang0...*| +00000210 86 48 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 |.H.............0| +00000220 cc 40 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 |.@+[P.a...SX...(| +00000230 a9 58 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 |.X..8....1Z..f=C| +00000240 d3 2d d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc |.-...... d8.$:..| +00000250 cf 9c 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd |..}.@ ._...a..v.| +00000260 13 c3 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb |.....\.....l..s.| +00000270 b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 |.Cw.......@.a.Lr| +00000280 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 |+...F..M...>...B| +00000290 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 |...=.`.\!.;.....| +000002a0 03 00 ac 0c 00 00 a8 03 00 1d 20 2f e5 7d a3 47 |.......... /.}.G| +000002b0 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af |.bC.(.._.).0....| +000002c0 c4 cf c2 ed 90 99 5f 58 cb 3b 74 08 04 00 80 5f |......_X.;t...._| +000002d0 37 27 84 58 1e ea 1e 40 1b de a9 8f 04 d4 94 64 |7'.X...@.......d| +000002e0 4e 27 c7 f1 b3 30 d0 53 f5 3d 57 50 d2 17 97 c8 |N'...0.S.=WP....| +000002f0 3d 61 af a6 21 ab 1c 34 47 70 f8 b1 3b 9c 06 86 |=a..!..4Gp..;...| +00000300 87 00 e2 13 50 83 91 ad bc 84 bd b4 7b f3 4b ed |....P.......{.K.| +00000310 ca 81 0c 94 37 a8 ec 67 ca 9c f3 00 f6 af c2 92 |....7..g........| +00000320 c4 8c 78 07 18 0e 43 24 1b 98 16 50 5c 2b 75 0e |..x...C$...P\+u.| +00000330 40 66 dc 40 cd 10 1a 51 25 f3 96 25 1a 3e 70 af |@f.@...Q%..%.>p.| +00000340 16 24 d0 1c 0e 33 f9 c1 74 cf b7 e2 28 ac 60 16 |.$...3..t...(.`.| +00000350 03 03 00 04 0e 00 00 00 |........| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 30 f2 bb f7 a7 ac |....%...! 0.....| +00000010 23 20 22 ee 73 0d 49 9c b3 7b c1 9a db 2c 85 f3 |# ".s.I..{...,..| +00000020 c0 82 31 60 bd 8b 14 4e 73 43 14 03 03 00 01 01 |..1`...NsC......| +00000030 16 03 03 00 20 09 8d c7 86 ee cc f4 c7 36 a3 49 |.... ........6.I| +00000040 d3 f7 a1 4a 68 a2 1e b4 fc cc a2 15 cb 01 92 d8 |...Jh...........| +00000050 72 b0 d1 6f eb |r..o.| +>>> Flow 4 (server to client) +00000000 16 03 03 00 8b 04 00 00 87 00 00 00 00 00 81 50 |...............P| +00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| +00000030 6f e0 18 83 51 ed 14 ef 68 ca 42 c5 4c a2 ac 05 |o...Q...h.B.L...| +00000040 9c 69 69 99 08 9f de a4 d4 e7 37 ab 14 38 4c 47 |.ii.......7..8LG| +00000050 70 f0 97 1d db 2d 0a 14 c2 1e f0 16 9f 6d 37 02 |p....-.......m7.| +00000060 4b f1 16 be 98 3f df 74 83 7c 19 85 61 49 38 16 |K....?.t.|..aI8.| +00000070 ee 35 7a e2 3f 74 fe 8d e3 07 93 a1 5e fa f2 02 |.5z.?t......^...| +00000080 e5 c8 60 3f 11 83 8b 0e 32 52 f1 aa 52 b7 0a 89 |..`?....2R..R...| +00000090 14 03 03 00 01 01 16 03 03 00 20 9e 65 15 cf 45 |.......... .e..E| +000000a0 a5 03 69 c9 b1 d8 9e 92 a3 a2 b0 df 2e 62 b1 3a |..i..........b.:| +000000b0 17 78 cd e5 1d f3 51 42 7e 4e 25 17 03 03 00 1d |.x....QB~N%.....| +000000c0 d9 ae d0 fa b7 90 a9 2f 28 8d 1d 6f 54 1f c0 1e |......./(..oT...| +000000d0 4d ae b6 91 f0 e8 84 cf 86 11 22 25 ea 15 03 03 |M........."%....| +000000e0 00 12 0e 71 f2 11 9e 9f 58 ad c0 d8 fc fa 34 bc |...q....X.....4.| +000000f0 02 5a 60 00 |.Z`.| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch b/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch index fdfb175..2d8a2eb 100644 --- a/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch @@ -1,7 +1,7 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 9d 01 00 00 99 03 03 7f fc 15 86 d1 |................| -00000010 83 09 78 47 8d cd 7b 88 b3 86 52 27 bc da bc 8d |..xG..{...R'....| -00000020 0e 5d 35 44 21 17 7b d9 67 b9 fb 00 00 04 cc a8 |.]5D!.{.g.......| +00000000 16 03 01 00 9d 01 00 00 99 03 03 24 15 a8 f2 f5 |...........$....| +00000010 53 02 78 f0 4c f7 82 3c 68 7d a0 b1 9a 0f 29 32 |S.x.L..<h}....)2| +00000020 9c 38 cc e7 92 95 63 f2 30 53 46 00 00 04 cc a8 |.8....c.0SF.....| 00000030 00 ff 01 00 00 6c 00 0b 00 04 03 00 01 02 00 0a |.....l..........| 00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| 00000050 00 00 00 10 00 10 00 0e 06 70 72 6f 74 6f 32 06 |.........proto2.| @@ -11,81 +11,4 @@ 00000090 03 03 02 03 03 01 02 01 03 02 02 02 04 02 05 02 |................| 000000a0 06 02 |..| >>> Flow 2 (server to client) -00000000 16 03 03 00 3b 02 00 00 37 03 03 00 00 00 00 00 |....;...7.......| -00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 cc a8 00 00 |...DOWNGRD......| -00000030 0f 00 23 00 00 ff 01 00 01 00 00 0b 00 02 01 00 |..#.............| -00000040 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 |....Y...U..R..O0| -00000050 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 |..K0............| -00000060 f0 9d 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 |..?.[..0...*.H..| -00000070 0d 01 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 |......0.1.0...U.| -00000080 0a 13 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 |...Go1.0...U....| -00000090 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 |Go Root0...16010| -000000a0 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 |1000000Z..250101| -000000b0 30 30 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 |000000Z0.1.0...U| -000000c0 04 0a 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 |....Go1.0...U...| -000000d0 02 47 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d |.Go0..0...*.H...| -000000e0 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 |.........0......| -000000f0 db 46 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 |.F}...'.H..(!.~.| -00000100 b6 a2 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 |..]..RE.z6G....B| -00000110 5b c2 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 |[.....y.@.Om..+.| -00000120 8b c2 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 |....g....."8.J.t| -00000130 73 2b c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c |s+.4......t{.X.l| -00000140 61 3c c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd |a<..A..++$#w[.;.| -00000150 75 5d ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a |u]. T..c...$....| -00000160 50 8b aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 |P....C...ub...R.| -00000170 02 03 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 |........0..0...U| -00000180 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 |...........0...U| -00000190 1d 25 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......| -000001a0 06 08 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d |..+.......0...U.| -000001b0 13 01 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 |......0.0...U...| -000001c0 12 04 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 |.......CC>I..m..| -000001d0 d7 9f 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 |..`0...U.#..0...| -000001e0 48 13 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b |H.IM.~.1......n{| -000001f0 30 19 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 |0...U....0...exa| -00000200 6d 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a |mple.golang0...*| -00000210 86 48 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 |.H.............0| -00000220 cc 40 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 |.@+[P.a...SX...(| -00000230 a9 58 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 |.X..8....1Z..f=C| -00000240 d3 2d d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc |.-...... d8.$:..| -00000250 cf 9c 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd |..}.@ ._...a..v.| -00000260 13 c3 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb |.....\.....l..s.| -00000270 b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 |.Cw.......@.a.Lr| -00000280 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 |+...F..M...>...B| -00000290 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 |...=.`.\!.;.....| -000002a0 03 00 ac 0c 00 00 a8 03 00 1d 20 2f e5 7d a3 47 |.......... /.}.G| -000002b0 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af |.bC.(.._.).0....| -000002c0 c4 cf c2 ed 90 99 5f 58 cb 3b 74 08 04 00 80 b8 |......_X.;t.....| -000002d0 a8 88 ac 85 ea 59 ac f1 41 e8 2d a2 76 3c 3b 4f |.....Y..A.-.v<;O| -000002e0 58 90 b7 03 74 4b 7a a7 5a 65 ea 08 9c cf e9 4d |X...tKz.Ze.....M| -000002f0 b4 8a ef f3 e1 d8 0a 83 0f 50 29 0b 59 77 90 e9 |.........P).Yw..| -00000300 f3 e8 ca 6c b5 da e5 2b 95 47 e7 ed ff d6 3b 30 |...l...+.G....;0| -00000310 45 61 2c af 5c 8c 4c df bd c4 dc 28 dd d2 31 fa |Ea,.\.L....(..1.| -00000320 be 65 2b a4 cd 7c 41 29 4c 99 07 97 5c 2a 3c a7 |.e+..|A)L...\*<.| -00000330 4d 9c ed 72 eb a1 a4 9e db eb a0 cf c7 c2 b1 3b |M..r...........;| -00000340 5a d9 f8 f8 8e d5 07 81 f6 65 aa 0d 4f 4d 11 16 |Z........e..OM..| -00000350 03 03 00 04 0e 00 00 00 |........| ->>> Flow 3 (client to server) -00000000 16 03 03 00 25 10 00 00 21 20 5f d2 13 b1 79 f6 |....%...! _...y.| -00000010 f3 2a 21 f5 89 a3 22 29 73 30 14 60 1d 1e 77 8a |.*!...")s0.`..w.| -00000020 f4 1a 92 3f b0 04 06 98 1a 1e 14 03 03 00 01 01 |...?............| -00000030 16 03 03 00 20 63 10 89 c0 c0 56 37 40 8c e8 5e |.... c....V7@..^| -00000040 7f f0 f0 e3 a0 8e d5 20 33 5f dd c3 16 e8 eb 6c |....... 3_.....l| -00000050 c3 a8 75 6d dc |..um.| ->>> Flow 4 (server to client) -00000000 16 03 03 00 8b 04 00 00 87 00 00 00 00 00 81 50 |...............P| -00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.| -00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| -00000030 6f e0 18 83 51 ed 14 ef 68 ca 42 c5 4c e3 f1 12 |o...Q...h.B.L...| -00000040 a1 17 a6 ee 99 af e8 06 65 d0 6d c1 4f ce 92 7c |........e.m.O..|| -00000050 40 df 41 c1 90 e3 e0 d8 a1 95 da 38 25 26 ea b5 |@.A........8%&..| -00000060 ca a9 42 5f 8c 55 d4 d2 73 a6 a2 b6 22 49 38 16 |..B_.U..s..."I8.| -00000070 ec 70 52 f9 c0 12 18 9e 9b 4d e3 6d 49 b7 3b c0 |.pR......M.mI.;.| -00000080 e9 53 9d 06 96 fc a9 06 8c 2a 7a c5 7d 48 47 ef |.S.......*z.}HG.| -00000090 14 03 03 00 01 01 16 03 03 00 20 19 27 38 37 bf |.......... .'87.| -000000a0 07 4e 2f 77 b9 73 4b dd c8 f8 4c c5 f1 35 86 2b |.N/w.sK...L..5.+| -000000b0 97 7e 0f 89 4b bf db 81 76 8a 41 17 03 03 00 1d |.~..K...v.A.....| -000000c0 6d b8 c3 eb b1 5a f3 06 97 04 61 fc 82 74 5d a0 |m....Z....a..t].| -000000d0 73 57 75 6e 66 53 3e 12 5e 0d 60 31 52 15 03 03 |sWunfS>.^.`1R...| -000000e0 00 12 e4 93 fb 7b cb ee d6 70 ac af 5f 8b 82 9b |.....{...p.._...| -000000f0 e5 0b 68 9c |..h.| +00000000 15 03 03 00 02 02 78 |......x| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NotConfigured b/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NotConfigured new file mode 100644 index 0000000..e1c991b --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NotConfigured @@ -0,0 +1,91 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 9d 01 00 00 99 03 03 92 d8 d4 4f 2e |..............O.| +00000010 82 ad e9 4f a2 c3 f7 23 da 2e dc 23 c0 87 fc 33 |...O...#...#...3| +00000020 14 63 f1 da 98 a8 af 70 3a 7e f3 00 00 04 cc a8 |.c.....p:~......| +00000030 00 ff 01 00 00 6c 00 0b 00 04 03 00 01 02 00 0a |.....l..........| +00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| +00000050 00 00 00 10 00 10 00 0e 06 70 72 6f 74 6f 32 06 |.........proto2.| +00000060 70 72 6f 74 6f 31 00 16 00 00 00 17 00 00 00 0d |proto1..........| +00000070 00 30 00 2e 04 03 05 03 06 03 08 07 08 08 08 09 |.0..............| +00000080 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| +00000090 03 03 02 03 03 01 02 01 03 02 02 02 04 02 05 02 |................| +000000a0 06 02 |..| +>>> Flow 2 (server to client) +00000000 16 03 03 00 3b 02 00 00 37 03 03 00 00 00 00 00 |....;...7.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 cc a8 00 00 |...DOWNGRD......| +00000030 0f 00 23 00 00 ff 01 00 01 00 00 0b 00 02 01 00 |..#.............| +00000040 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 |....Y...U..R..O0| +00000050 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 |..K0............| +00000060 f0 9d 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 |..?.[..0...*.H..| +00000070 0d 01 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 |......0.1.0...U.| +00000080 0a 13 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 |...Go1.0...U....| +00000090 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 |Go Root0...16010| +000000a0 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 |1000000Z..250101| +000000b0 30 30 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 |000000Z0.1.0...U| +000000c0 04 0a 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 |....Go1.0...U...| +000000d0 02 47 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d |.Go0..0...*.H...| +000000e0 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 |.........0......| +000000f0 db 46 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 |.F}...'.H..(!.~.| +00000100 b6 a2 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 |..]..RE.z6G....B| +00000110 5b c2 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 |[.....y.@.Om..+.| +00000120 8b c2 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 |....g....."8.J.t| +00000130 73 2b c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c |s+.4......t{.X.l| +00000140 61 3c c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd |a<..A..++$#w[.;.| +00000150 75 5d ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a |u]. T..c...$....| +00000160 50 8b aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 |P....C...ub...R.| +00000170 02 03 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 |........0..0...U| +00000180 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 |...........0...U| +00000190 1d 25 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......| +000001a0 06 08 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d |..+.......0...U.| +000001b0 13 01 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 |......0.0...U...| +000001c0 12 04 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 |.......CC>I..m..| +000001d0 d7 9f 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 |..`0...U.#..0...| +000001e0 48 13 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b |H.IM.~.1......n{| +000001f0 30 19 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 |0...U....0...exa| +00000200 6d 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a |mple.golang0...*| +00000210 86 48 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 |.H.............0| +00000220 cc 40 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 |.@+[P.a...SX...(| +00000230 a9 58 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 |.X..8....1Z..f=C| +00000240 d3 2d d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc |.-...... d8.$:..| +00000250 cf 9c 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd |..}.@ ._...a..v.| +00000260 13 c3 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb |.....\.....l..s.| +00000270 b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 |.Cw.......@.a.Lr| +00000280 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 |+...F..M...>...B| +00000290 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 |...=.`.\!.;.....| +000002a0 03 00 ac 0c 00 00 a8 03 00 1d 20 2f e5 7d a3 47 |.......... /.}.G| +000002b0 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af |.bC.(.._.).0....| +000002c0 c4 cf c2 ed 90 99 5f 58 cb 3b 74 08 04 00 80 8c |......_X.;t.....| +000002d0 cb 8c f6 6c dd 02 5f c9 13 7e c2 26 26 41 7a 1a |...l.._..~.&&Az.| +000002e0 25 c7 3e 22 11 30 32 c0 67 a5 53 32 1e 32 21 cb |%.>".02.g.S2.2!.| +000002f0 ff 0a b7 e1 7a 98 26 e9 bf 05 30 f6 13 38 ee 1d |....z.&...0..8..| +00000300 90 56 a6 0d e0 65 a8 02 0e 08 3e c0 31 ff dd fa |.V...e....>.1...| +00000310 05 3a 22 7c f8 ce 65 43 0c b6 c4 9a e4 ed 22 eb |.:"|..eC......".| +00000320 c4 46 b2 3d 1d 9c c1 e7 d4 6a 79 4f cf 8f 1c 45 |.F.=.....jyO...E| +00000330 52 51 b3 d1 a4 0d 0d df 4e 19 15 e6 af 2e 5a d5 |RQ......N.....Z.| +00000340 8a 2e 3c 48 8a f7 86 e5 53 0e 35 9a 8a c6 dd 16 |..<H....S.5.....| +00000350 03 03 00 04 0e 00 00 00 |........| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 b7 d6 2f 99 8f c7 |....%...! ../...| +00000010 bc 48 b8 4f 01 f8 2c ff 75 e5 fe 10 c6 2d 2d d5 |.H.O..,.u....--.| +00000020 43 2b c3 14 cb d0 b2 7a e9 71 14 03 03 00 01 01 |C+.....z.q......| +00000030 16 03 03 00 20 c9 88 f1 a0 1a 9b 8a 14 00 33 f0 |.... .........3.| +00000040 e8 01 f3 c2 66 06 98 44 4d 35 89 8f 1b 65 d0 cf |....f..DM5...e..| +00000050 eb 7d 9f b1 df |.}...| +>>> Flow 4 (server to client) +00000000 16 03 03 00 8b 04 00 00 87 00 00 00 00 00 81 50 |...............P| +00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................| +00000030 6f e0 18 83 51 ed 14 ef 68 ca 42 c5 4c 76 fb ec |o...Q...h.B.Lv..| +00000040 0d 89 48 e7 19 98 64 df 59 8f df 50 ce 28 e8 3c |..H...d.Y..P.(.<| +00000050 b6 f8 5a ae bc 6b 2e a2 d6 23 05 f6 7f 36 ea 55 |..Z..k...#...6.U| +00000060 13 54 9e 9c 31 df d0 56 00 1f a7 6a b2 49 38 16 |.T..1..V...j.I8.| +00000070 7f d0 78 12 95 86 11 ca 98 63 07 4a 81 a5 d3 bd |..x......c.J....| +00000080 dc 9e 54 9c 25 f2 55 d5 fd cf 36 94 99 e0 c5 82 |..T.%.U...6.....| +00000090 14 03 03 00 01 01 16 03 03 00 20 e6 d9 c2 bb ca |.......... .....| +000000a0 02 d3 79 a4 fb b0 00 7d e2 47 46 d3 e7 b4 fe be |..y....}.GF.....| +000000b0 b3 8f c4 98 b7 f7 25 bc cc 3f a8 17 03 03 00 1d |......%..?......| +000000c0 ad f3 27 a0 c4 a4 5b 7b 40 11 a4 35 e6 10 03 63 |..'...[{@..5...c| +000000d0 13 d3 1c ce 75 8f 09 8b 85 6c 93 b1 9f 15 03 03 |....u....l......| +000000e0 00 12 79 0c dd 21 72 68 b8 30 45 5d 45 39 a9 c4 |..y..!rh.0E]E9..| +000000f0 a6 d7 12 99 |....| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA b/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA deleted file mode 100644 index 63e0edb..0000000 --- a/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA +++ /dev/null @@ -1,88 +0,0 @@ ->>> Flow 1 (client to server) -00000000 16 03 01 00 cb 01 00 00 c7 03 03 3f 5d 09 25 4e |...........?].%N| -00000010 82 83 13 89 ba 89 43 d5 43 4f f1 c3 2f 08 77 39 |......C.CO../.w9| -00000020 bf eb c7 1d 4b d6 85 c8 17 2f 83 00 00 38 c0 2c |....K..../...8.,| -00000030 c0 30 00 9f cc a9 cc a8 cc aa c0 2b c0 2f 00 9e |.0.........+./..| -00000040 c0 24 c0 28 00 6b c0 23 c0 27 00 67 c0 0a c0 14 |.$.(.k.#.'.g....| -00000050 00 39 c0 09 c0 13 00 33 00 9d 00 9c 00 3d 00 3c |.9.....3.....=.<| -00000060 00 35 00 2f 00 ff 01 00 00 66 00 00 00 0e 00 0c |.5./.....f......| -00000070 00 00 09 31 32 37 2e 30 2e 30 2e 31 00 0b 00 04 |...127.0.0.1....| -00000080 03 00 01 02 00 0a 00 0c 00 0a 00 1d 00 17 00 1e |................| -00000090 00 19 00 18 00 16 00 00 00 17 00 00 00 0d 00 30 |...............0| -000000a0 00 2e 04 03 05 03 06 03 08 07 08 08 08 09 08 0a |................| -000000b0 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 03 03 |................| -000000c0 02 03 03 01 02 01 03 02 02 02 04 02 05 02 06 02 |................| ->>> Flow 2 (server to client) -00000000 16 03 03 00 37 02 00 00 33 03 03 00 00 00 00 00 |....7...3.......| -00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 c0 0a 00 00 |...DOWNGRD......| -00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 03 02 |................| -00000040 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 00 30 |...........0...0| -00000050 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 30 09 |..b.....-G....0.| -00000060 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 09 06 |..*.H.=..0E1.0..| -00000070 03 55 04 06 13 02 41 55 31 13 30 11 06 03 55 04 |.U....AU1.0...U.| -00000080 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 |...Some-State1!0| -00000090 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 |...U....Internet| -000000a0 20 57 69 64 67 69 74 73 20 50 74 79 20 4c 74 64 | Widgits Pty Ltd| -000000b0 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 33 32 |0...121122150632| -000000c0 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 32 5a |Z..221120150632Z| -000000d0 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 |0E1.0...U....AU1| -000000e0 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 |.0...U....Some-S| -000000f0 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 |tate1!0...U....I| -00000100 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 |nternet Widgits | -00000110 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 2a 86 |Pty Ltd0..0...*.| -00000120 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 86 00 |H.=....+...#....| -00000130 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 16 56 |.........Hs6~..V| -00000140 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 f6 b0 |.".=S.;M!=.ku...| -00000150 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 2f 1c |...&.....r2|.d/.| -00000160 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 e0 28 |...h#.~..%.H:i.(| -00000170 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 d8 81 |m.7...b....pb...| -00000180 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 de 76 |.d1...1...h..#.v| -00000190 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd 9b d8 |d?.\....XX._p...| -000001a0 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a 20 e2 |.........0f[f. .| -000001b0 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d 04 01 |'...;0...*.H.=..| -000001c0 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb e2 45 |....0...B...O..E| -000001d0 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e 1b b6 |.H}.......Gp.^..| -000001e0 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b 7e 92 |/...M.a@......~.| -000001f0 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 ec 47 |~.v..;~.?....Y.G| -00000200 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 4d fc |-|..N....o..B.M.| -00000210 be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 13 83 |.g..-...?..%.3..| -00000220 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd d7 11 |.....7z..z......| -00000230 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d ae cb |i..|V..1x+..x...| -00000240 be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f 2a 16 |..N6$1{j.9....*.| -00000250 03 03 00 b7 0c 00 00 b3 03 00 1d 20 2f e5 7d a3 |........... /.}.| -00000260 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...| -00000270 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 04 03 00 8b |......._X.;t....| -00000280 30 81 88 02 42 01 5c 2a 30 4f 9f dc df a8 33 06 |0...B.\*0O....3.| -00000290 3b bc 35 46 6a 9c a3 a1 26 ec 42 29 bf 63 b3 9b |;.5Fj...&.B).c..| -000002a0 8c bf 7b 07 8d 28 eb 41 68 7a 8a 1b f3 de a9 dc |..{..(.Ahz......| -000002b0 1e d1 21 3c 4d 24 df 89 90 b6 f2 fb ad 60 d2 27 |..!<M$.......`.'| -000002c0 96 6d a2 b6 9b 48 e6 02 42 00 f1 c8 c2 f4 ee 4a |.m...H..B......J| -000002d0 8f 08 c5 09 05 e9 bf 7f aa b6 3e 56 e9 98 46 b4 |..........>V..F.| -000002e0 b4 e5 90 72 ed af 71 0d fb e6 39 2f d5 4b 73 ba |...r..q...9/.Ks.| -000002f0 85 d2 a4 bf 99 74 d7 81 eb 3e 69 4d f0 12 1e 3c |.....t...>iM...<| -00000300 53 ca f0 35 85 ef ff ed cc 0f f7 16 03 03 00 04 |S..5............| -00000310 0e 00 00 00 |....| ->>> Flow 3 (client to server) -00000000 16 03 03 00 25 10 00 00 21 20 b8 a6 ed 33 20 59 |....%...! ...3 Y| -00000010 76 0b 7c 87 53 f1 12 c1 46 d9 db 68 c0 6f d6 30 |v.|.S...F..h.o.0| -00000020 ea e0 64 04 54 7a 4c 95 03 41 14 03 03 00 01 01 |..d.TzL..A......| -00000030 16 03 03 00 40 c0 70 29 39 a0 8a bd 59 58 88 44 |....@.p)9...YX.D| -00000040 ea 10 b4 79 3e 0e 72 b7 2a 03 6d 4d 5a 24 f5 c0 |...y>.r.*.mMZ$..| -00000050 4e e5 19 f0 fb 66 ca 97 89 4b 67 dc bb 19 cd 0b |N....f...Kg.....| -00000060 6e 74 01 d3 a4 9a ab af 8e 44 10 99 ac ff 9e 9e |nt.......D......| -00000070 17 04 56 78 55 |..VxU| ->>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| -00000010 00 00 00 00 00 00 00 00 00 00 00 01 a0 6b 2c c5 |.............k,.| -00000020 7e 83 70 b5 2c 8c 43 b6 8b 2e 18 2a 1d be 11 6d |~.p.,.C....*...m| -00000030 13 f9 ba b5 de db 01 2a 64 d9 5b 24 c9 61 a1 4d |.......*d.[$.a.M| -00000040 11 bb fc b1 86 61 b0 04 a9 cd 1e 17 03 03 00 40 |.....a.........@| -00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000060 d8 98 85 b4 cb 61 39 69 2f b1 1f 24 c1 5a 4f e3 |.....a9i/..$.ZO.| -00000070 0b 20 5d 6c 3f 3f 82 3a a3 8a b3 cf e9 41 bb 60 |. ]l??.:.....A.`| -00000080 ed b6 67 a0 76 39 ab 93 a5 35 d0 42 b3 a7 4c 92 |..g.v9...5.B..L.| -00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -000000a0 00 00 00 00 00 c7 0d 06 b2 2b 73 ab ed 16 88 6f |.........+s....o| -000000b0 62 77 fb 48 e4 5e 6d 7e 24 02 b6 08 fa 46 c8 76 |bw.H.^m~$....F.v| -000000c0 18 fc f4 c4 08 |.....| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA b/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA deleted file mode 100644 index 802aa1a..0000000 --- a/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA +++ /dev/null @@ -1,92 +0,0 @@ ->>> Flow 1 (client to server) -00000000 16 03 01 00 cb 01 00 00 c7 03 03 27 8a e9 f3 58 |...........'...X| -00000010 5a 08 90 d6 d4 97 23 b6 a7 92 73 3a a3 3c c1 a1 |Z.....#...s:.<..| -00000020 ca 06 23 c8 ed 4a 19 26 73 c9 62 00 00 38 c0 2c |..#..J.&s.b..8.,| -00000030 c0 30 00 9f cc a9 cc a8 cc aa c0 2b c0 2f 00 9e |.0.........+./..| -00000040 c0 24 c0 28 00 6b c0 23 c0 27 00 67 c0 0a c0 14 |.$.(.k.#.'.g....| -00000050 00 39 c0 09 c0 13 00 33 00 9d 00 9c 00 3d 00 3c |.9.....3.....=.<| -00000060 00 35 00 2f 00 ff 01 00 00 66 00 00 00 0e 00 0c |.5./.....f......| -00000070 00 00 09 31 32 37 2e 30 2e 30 2e 31 00 0b 00 04 |...127.0.0.1....| -00000080 03 00 01 02 00 0a 00 0c 00 0a 00 1d 00 17 00 1e |................| -00000090 00 19 00 18 00 16 00 00 00 17 00 00 00 0d 00 30 |...............0| -000000a0 00 2e 04 03 05 03 06 03 08 07 08 08 08 09 08 0a |................| -000000b0 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 03 03 |................| -000000c0 02 03 03 01 02 01 03 02 02 02 04 02 05 02 06 02 |................| ->>> Flow 2 (server to client) -00000000 16 03 03 00 37 02 00 00 33 03 03 00 00 00 00 00 |....7...3.......| -00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 c0 14 00 00 |...DOWNGRD......| -00000030 0b ff 01 00 01 00 00 0b 00 02 01 00 16 03 03 02 |................| -00000040 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 |Y...U..R..O0..K0| -00000050 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 |..............?.| -00000060 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |[..0...*.H......| -00000070 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 |..0.1.0...U....G| -00000080 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 |o1.0...U....Go R| -00000090 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 |oot0...160101000| -000000a0 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 |000Z..2501010000| -000000b0 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 |00Z0.1.0...U....| -000000c0 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 |Go1.0...U....Go0| -000000d0 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| -000000e0 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 |.....0.......F}.| -000000f0 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe |..'.H..(!.~...].| -00000100 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 |.RE.z6G....B[...| -00000110 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e |..y.@.Om..+.....| -00000120 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 |g....."8.J.ts+.4| -00000130 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 |......t{.X.la<..| -00000140 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 |A..++$#w[.;.u]. | -00000150 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 |T..c...$....P...| -00000160 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 |.C...ub...R.....| -00000170 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 |....0..0...U....| -00000180 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 |.......0...U.%..| -00000190 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 |0...+.........+.| -000001a0 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff |......0...U.....| -000001b0 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f |..0.0...U.......| -000001c0 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 |...CC>I..m....`0| -000001d0 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d |...U.#..0...H.IM| -000001e0 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 |.~.1......n{0...| -000001f0 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 |U....0...example| -00000200 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 |.golang0...*.H..| -00000210 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b |...........0.@+[| -00000220 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 |P.a...SX...(.X..| -00000230 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b |8....1Z..f=C.-..| -00000240 f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 |.... d8.$:....}.| -00000250 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 |@ ._...a..v.....| -00000260 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d |.\.....l..s..Cw.| -00000270 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db |......@.a.Lr+...| -00000280 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d |F..M...>...B...=| -00000290 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 ac 0c |.`.\!.;.........| -000002a0 00 00 a8 03 00 1d 20 2f e5 7d a3 47 cd 62 43 15 |...... /.}.G.bC.| -000002b0 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed |(.._.).0........| -000002c0 90 99 5f 58 cb 3b 74 08 04 00 80 42 86 d0 0a 5b |.._X.;t....B...[| -000002d0 d7 97 20 4d be 16 b8 eb 51 66 28 3b f9 45 35 f5 |.. M....Qf(;.E5.| -000002e0 de 1d 28 c9 36 63 5b 7b f6 a7 64 79 fb 39 20 c3 |..(.6c[{..dy.9 .| -000002f0 dd db 38 3e af 89 ce 91 f7 bd 51 b4 5e 01 d8 9b |..8>......Q.^...| -00000300 54 62 58 24 3b c2 43 59 a4 11 1a 2b 67 c5 5f 79 |TbX$;.CY...+g._y| -00000310 fe 68 9d c7 e6 8b 36 8b f9 cb 00 b0 b3 0f 52 fb |.h....6.......R.| -00000320 fe a5 e6 c6 26 9b d1 a2 17 4e e2 58 7f b2 80 78 |....&....N.X...x| -00000330 10 b4 0a 47 e1 18 92 d4 a5 5a 86 06 36 ca f7 b6 |...G.....Z..6...| -00000340 1c 83 81 0e eb 32 7d fe 06 c5 03 16 03 03 00 04 |.....2}.........| -00000350 0e 00 00 00 |....| ->>> Flow 3 (client to server) -00000000 16 03 03 00 25 10 00 00 21 20 14 7f fb 7d 0c ef |....%...! ...}..| -00000010 48 c4 8f 75 24 19 5f ee 5f 51 08 35 74 cf c3 ea |H..u$._._Q.5t...| -00000020 67 20 c4 f9 49 b2 cf 69 5a 77 14 03 03 00 01 01 |g ..I..iZw......| -00000030 16 03 03 00 40 2b d2 f4 dc 36 98 ef 1d 43 f9 3e |....@+...6...C.>| -00000040 83 33 c0 71 a6 e3 ac f1 3c cc 94 e4 d0 fe 81 bc |.3.q....<.......| -00000050 94 56 15 eb 6a 7b 17 33 e1 a0 ef d5 7a 86 af ea |.V..j{.3....z...| -00000060 1f bb d5 8c 80 56 d5 e4 08 cd 68 bf c0 53 c2 56 |.....V....h..S.V| -00000070 aa b3 38 1e 4e |..8.N| ->>> Flow 4 (server to client) -00000000 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 00 |..........@.....| -00000010 00 00 00 00 00 00 00 00 00 00 00 45 07 c3 ba 8c |...........E....| -00000020 d8 9f b6 f1 6a 14 bb b1 4e 84 3f 25 6a 3d ef f6 |....j...N.?%j=..| -00000030 88 89 1a 91 22 ef e3 ed ba 2a a3 7c 5b db e0 1d |...."....*.|[...| -00000040 b5 8d 7a ed e7 ad e1 31 b2 12 f5 17 03 03 00 40 |..z....1.......@| -00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000060 a6 f3 0b 33 f7 7a 7c fb fb b5 e6 eb 6e 0a 26 aa |...3.z|.....n.&.| -00000070 06 3b a6 bc 08 e5 3a b6 c9 a3 f3 77 28 93 45 08 |.;....:....w(.E.| -00000080 1d 54 5e a3 92 cd 89 a3 e6 34 ec 52 70 c0 97 3c |.T^......4.Rp..<| -00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| -000000a0 00 00 00 00 00 2d 0d 96 57 b8 6f 90 1e 84 4d 35 |.....-..W.o...M5| -000000b0 91 52 42 6b 8d a3 6b 21 22 60 1a c9 38 7f 5a ef |.RBk..k!"`..8.Z.| -000000c0 6e dd 84 06 79 |n...y| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-Fallback b/libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-Fallback new file mode 100644 index 0000000..6203e68 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-Fallback @@ -0,0 +1,100 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 eb 01 00 00 e7 03 03 1c d3 8e 3b d9 |..............;.| +00000010 fe 7d e7 f9 9f fa c6 51 c3 8c 1b dd dc 87 95 f4 |.}.....Q........| +00000020 39 23 67 e4 d6 bd 94 93 fc 88 4e 20 c3 c0 e2 c1 |9#g.......N ....| +00000030 3d 12 ec 4c 0a 3f 40 51 13 24 61 11 c0 5d 09 f9 |=..L.?@Q.$a..]..| +00000040 08 d6 3e cd e7 b3 51 c3 06 8f b4 42 00 04 13 03 |..>...Q....B....| +00000050 00 ff 01 00 00 9a 00 0b 00 04 03 00 01 02 00 0a |................| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| +00000070 00 00 00 10 00 19 00 17 06 70 72 6f 74 6f 33 08 |.........proto3.| +00000080 68 74 74 70 2f 31 2e 31 06 70 72 6f 74 6f 34 00 |http/1.1.proto4.| +00000090 16 00 00 00 17 00 00 00 0d 00 1e 00 1c 04 03 05 |................| +000000a0 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 |................| +000000b0 05 08 06 04 01 05 01 06 01 00 2b 00 03 02 03 04 |..........+.....| +000000c0 00 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 20 |.-.....3.&.$... | +000000d0 f4 05 eb 4a 7a 73 20 18 74 aa 14 2a 0c 35 63 29 |...Jzs .t..*.5c)| +000000e0 cb f2 ad d1 a2 3d bd 9d 02 b4 62 00 bc eb 10 58 |.....=....b....X| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 c3 c0 e2 c1 |........... ....| +00000030 3d 12 ec 4c 0a 3f 40 51 13 24 61 11 c0 5d 09 f9 |=..L.?@Q.$a..]..| +00000040 08 d6 3e cd e7 b3 51 c3 06 8f b4 42 13 03 00 00 |..>...Q....B....| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 fb 75 d8 5c 50 35 |...........u.\P5| +00000090 55 82 ba 65 1e 63 73 b8 c1 e9 d7 f5 28 68 3c c1 |U..e.cs.....(h<.| +000000a0 5d 17 03 03 02 6d 56 c9 a9 09 73 6a bc fd 1a 3c |]....mV...sj...<| +000000b0 6a f8 3e 32 99 83 e8 f6 01 9e 5e 30 e8 53 7f 72 |j.>2......^0.S.r| +000000c0 fd 86 72 a8 9e 47 25 67 c1 f1 9a 03 c0 9d 6f 9d |..r..G%g......o.| +000000d0 bd ed 29 30 8f 3c 01 ce 49 bb 5f dd 58 9a ae 80 |..)0.<..I._.X...| +000000e0 5c 2d 81 fc ea 7b 03 03 3d 5d bb 92 23 73 67 89 |\-...{..=]..#sg.| +000000f0 2e f0 ec 08 20 8a 36 eb 43 a6 a1 68 d0 39 95 37 |.... .6.C..h.9.7| +00000100 6b 15 a9 0e 46 20 92 51 9c 04 bf 3b 07 97 84 cb |k...F .Q...;....| +00000110 1f 30 38 37 2e ff e7 0f f5 14 93 5a 84 f1 f7 10 |.087.......Z....| +00000120 c2 a5 0d bb 97 96 ef 4a e0 13 c0 63 72 2b 60 f3 |.......J...cr+`.| +00000130 59 b5 57 aa 5f d1 da a9 0e dd 9c dd c2 cb 61 fe |Y.W._.........a.| +00000140 e2 69 8e db 5d 70 6c 3a 33 e0 9e db 9a 31 26 6a |.i..]pl:3....1&j| +00000150 2b 9e 19 8e bb 5d 06 48 ea c0 a1 c6 11 24 fb c4 |+....].H.....$..| +00000160 ce ae 48 54 64 81 d1 84 38 a6 e0 7a 7b 74 2b bc |..HTd...8..z{t+.| +00000170 ce 07 8b b6 04 1f 5b 4c 36 29 68 0c 8c c7 32 15 |......[L6)h...2.| +00000180 93 e0 10 52 c2 27 23 96 c5 0c 9c e9 e2 a9 08 7d |...R.'#........}| +00000190 25 68 65 f5 4e 44 eb a9 85 78 13 e1 0d 86 5e dc |%he.ND...x....^.| +000001a0 fd e5 c6 dd 65 46 8e 2f 32 82 83 0b dd 67 f8 42 |....eF./2....g.B| +000001b0 65 87 3b 08 fe b1 f5 12 e9 74 21 04 12 6d 75 35 |e.;......t!..mu5| +000001c0 b2 eb 93 95 72 10 fa 56 96 77 c3 0c 17 8c 9e f6 |....r..V.w......| +000001d0 77 19 28 37 96 3e 73 98 f4 d2 91 4f 40 db 76 56 |w.(7.>s....O@.vV| +000001e0 ce b5 a8 7a b8 86 d0 9a ba b5 8b 40 c2 63 e1 cf |...z.......@.c..| +000001f0 49 29 2c 5d 1a 9b 8b 56 cb 93 ca 2c c0 d0 15 b7 |I),]...V...,....| +00000200 8a f1 6a d5 0a a8 81 57 b1 6e 10 cd a5 ff b1 4d |..j....W.n.....M| +00000210 47 c6 9b 35 f1 5f 83 91 22 f6 88 68 65 b3 b9 c9 |G..5._.."..he...| +00000220 02 dc 4b f7 13 39 06 e6 3a ec 94 ef 51 15 05 72 |..K..9..:...Q..r| +00000230 1d f4 9d 3b da ca 8d 2c 64 be 9b 45 99 2c 63 cc |...;...,d..E.,c.| +00000240 22 b3 8b 93 ad f6 2c f0 d2 d9 11 3f 5b c0 40 fa |".....,....?[.@.| +00000250 90 6e a0 76 b2 43 b9 4c 72 c4 24 28 a2 bf 56 d6 |.n.v.C.Lr.$(..V.| +00000260 d2 a7 2a d1 8c 5e 1d eb f8 be d0 43 da 7a c7 88 |..*..^.....C.z..| +00000270 61 67 a2 69 85 23 43 3e d4 88 f2 33 c3 5b 38 0a |ag.i.#C>...3.[8.| +00000280 1e de 28 3b 3b 19 de 95 2f 84 c0 37 88 80 59 2f |..(;;.../..7..Y/| +00000290 a6 ee 93 1a 69 08 c3 df 7c cf da c3 9b 96 70 d9 |....i...|.....p.| +000002a0 60 c5 e9 0f 42 f6 1a f2 58 5e f2 32 61 6a b2 a3 |`...B...X^.2aj..| +000002b0 1f 97 fa 08 6c 3f 4b 83 1f 04 66 80 8a 26 3a 7f |....l?K...f..&:.| +000002c0 24 30 ec 10 ae 7d 19 ff 39 91 ca 97 4e ed 0a d7 |$0...}..9...N...| +000002d0 64 3b 6b 50 29 33 0d b2 10 bc 83 63 3c fb 9a 82 |d;kP)3.....c<...| +000002e0 3b 7f bc 04 40 f1 33 64 4a 80 cd 01 f9 f4 c6 89 |;...@.3dJ.......| +000002f0 65 27 25 f9 cf 4f 7e c8 6e d9 0e ec 47 4a 51 29 |e'%..O~.n...GJQ)| +00000300 2f be 34 50 bd 9b d2 d8 b7 ea bb 0b a1 e0 20 1b |/.4P.......... .| +00000310 02 9c f2 17 03 03 00 99 61 dc 0b 3a 30 de 39 f6 |........a..:0.9.| +00000320 f3 db f8 6c 3b fa 4e 1e 7e 62 a5 ae 73 ba e1 41 |...l;.N.~b..s..A| +00000330 58 77 2a c1 7a 0c 50 bb 0c 57 b4 c4 25 bf 2f 9f |Xw*.z.P..W..%./.| +00000340 38 91 e2 65 22 9d ca ac 18 58 7e 81 2d fd 74 24 |8..e"....X~.-.t$| +00000350 28 69 76 11 df 9d 23 b8 be ae 8b e0 93 8e 5d df |(iv...#.......].| +00000360 0a 64 d0 b7 02 68 aa 86 01 0d 55 11 3b 76 70 c6 |.d...h....U.;vp.| +00000370 83 0c 5e 0a e3 37 a5 8b ad 25 50 b9 e8 5c 6b 04 |..^..7...%P..\k.| +00000380 b4 51 ec 9c d3 fa c6 b7 9c f0 46 aa 73 da 3c 0d |.Q........F.s.<.| +00000390 d3 bd 32 81 d4 d2 f1 1a b0 92 f3 73 3e 54 2b 05 |..2........s>T+.| +000003a0 92 24 34 75 df d6 18 a0 6a 82 95 4c 9b fc 7e b6 |.$4u....j..L..~.| +000003b0 8e 17 03 03 00 35 8f 34 0e 3b 91 d8 e7 74 24 71 |.....5.4.;...t$q| +000003c0 0e 7b f3 12 bb 76 2f 31 12 17 b8 9e 24 ce f9 2f |.{...v/1....$../| +000003d0 3f 5d f2 13 4b 2e 9b 1e c4 78 03 a6 c8 07 11 a3 |?]..K....x......| +000003e0 98 79 61 6e 4f 44 6e 18 ee c4 9b 17 03 03 00 93 |.yanODn.........| +000003f0 64 dd 52 a9 d9 51 63 6a a0 a3 c2 75 6b 5d 1d 54 |d.R..Qcj...uk].T| +00000400 ce d4 53 7e 14 8e d9 26 93 28 78 65 16 1b 95 77 |..S~...&.(xe...w| +00000410 68 0a 46 f1 82 36 bb 8a fa 0d df 54 8c 3d 83 e0 |h.F..6.....T.=..| +00000420 d7 de 2d 96 e9 c4 d7 22 d3 97 8e ae 90 f8 fc e6 |..-...."........| +00000430 a6 4b 78 98 4c c5 28 87 91 46 fa f4 1c 8d 0e ec |.Kx.L.(..F......| +00000440 0d 71 40 9a 04 49 b4 e8 5b 62 6f cd 16 c1 d5 fb |.q@..I..[bo.....| +00000450 73 2a 96 8f e5 a2 f4 11 1e df 2d 40 45 6b d5 a9 |s*........-@Ek..| +00000460 e4 e3 f7 93 fc fa d7 20 af d5 f7 b4 0e 09 ad d5 |....... ........| +00000470 26 87 b8 6c e2 20 95 fb c0 70 3e 38 be b7 b1 9f |&..l. ...p>8....| +00000480 70 da c1 |p..| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 29 d2 b9 bb 9b |..........5)....| +00000010 de 6c 5d 22 23 c1 fe 99 4c c5 33 bf fd 70 36 6b |.l]"#...L.3..p6k| +00000020 f1 a5 92 e8 bf 7c 3d 6e ef 6a 44 73 bc cb 27 1c |.....|=n.jDs..'.| +00000030 09 5d bf 99 4c 19 24 c3 3b 30 91 b5 e3 b6 63 45 |.]..L.$.;0....cE| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e 52 55 85 7c b8 87 dd c7 b2 d9 5b |.....RU.|......[| +00000010 18 1d bb ac bf b6 ab 76 82 be 64 0e b2 7b 2c 0f |.......v..d..{,.| +00000020 aa 17 92 17 03 03 00 13 79 0a 60 b1 46 20 33 74 |........y.`.F 3t| +00000030 ed 12 a0 23 de 68 88 fc 6f dd 8e |...#.h..o..| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-NoMatch b/libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-NoMatch index 0b5dc9b..b51ff25 100644 --- a/libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-NoMatch +++ b/libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-NoMatch @@ -1,9 +1,9 @@ >>> Flow 1 (client to server) -00000000 16 03 01 00 e2 01 00 00 de 03 03 ea ab 77 e1 48 |.............w.H| -00000010 64 70 23 5c af b3 a7 3d 60 93 a0 30 0a 8c 98 61 |dp#\...=`..0...a| -00000020 3a ab bc a9 11 c1 2f f5 ed d7 63 20 d4 29 26 9d |:...../...c .)&.| -00000030 64 37 72 d1 2c 7d 09 3b 94 67 f9 1c 19 c3 7e 17 |d7r.,}.;.g....~.| -00000040 ec 80 5f 09 38 c1 15 4d 59 45 5c c3 00 04 13 03 |.._.8..MYE\.....| +00000000 16 03 01 00 e2 01 00 00 de 03 03 9f 73 81 5f 56 |............s._V| +00000010 a9 02 5f 8c 33 db dc 2a 92 d0 5e 7c e9 e6 01 d7 |.._.3..*..^|....| +00000020 67 b6 bb 74 da bb d0 c1 11 08 20 20 9f bd d6 f8 |g..t...... ....| +00000030 d7 8c e5 32 15 1d 4a 4c 36 ce 72 90 cb 68 ca dc |...2..JL6.r..h..| +00000040 ea b3 57 93 9a 12 e6 0e 9a bd 91 1a 00 04 13 03 |..W.............| 00000050 00 ff 01 00 00 91 00 0b 00 04 03 00 01 02 00 0a |................| 00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| 00000070 00 00 00 10 00 10 00 0e 06 70 72 6f 74 6f 32 06 |.........proto2.| @@ -11,90 +11,17 @@ 00000090 00 1e 00 1c 04 03 05 03 06 03 08 07 08 08 08 09 |................| 000000a0 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| 000000b0 00 2b 00 03 02 03 04 00 2d 00 02 01 01 00 33 00 |.+......-.....3.| -000000c0 26 00 24 00 1d 00 20 68 64 e8 c1 4a c5 d5 b8 91 |&.$... hd..J....| -000000d0 a0 20 c7 aa 8a 41 90 d6 d0 5e ed 6c ed e4 77 aa |. ...A...^.l..w.| -000000e0 ec 33 93 e3 d5 b7 55 |.3....U| +000000c0 26 00 24 00 1d 00 20 79 79 04 d3 03 58 93 22 5d |&.$... yy...X."]| +000000d0 06 69 1a 03 11 4e 65 e5 30 85 29 02 22 c8 11 6d |.i...Ne.0.)."..m| +000000e0 21 86 d4 4d 58 93 74 |!..MX.t| >>> Flow 2 (server to client) 00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| -00000020 00 00 00 00 00 00 00 00 00 00 00 20 d4 29 26 9d |........... .)&.| -00000030 64 37 72 d1 2c 7d 09 3b 94 67 f9 1c 19 c3 7e 17 |d7r.,}.;.g....~.| -00000040 ec 80 5f 09 38 c1 15 4d 59 45 5c c3 13 03 00 00 |.._.8..MYE\.....| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 9f bd d6 f8 |........... ....| +00000030 d7 8c e5 32 15 1d 4a 4c 36 ce 72 90 cb 68 ca dc |...2..JL6.r..h..| +00000040 ea b3 57 93 9a 12 e6 0e 9a bd 91 1a 13 03 00 00 |..W.............| 00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| 00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| 00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| -00000080 03 03 00 01 01 17 03 03 00 17 c0 d3 a2 c3 42 b4 |..............B.| -00000090 39 f1 b6 f1 0a ac f3 76 dd 36 15 eb d7 3b 3f 63 |9......v.6...;?c| -000000a0 0b 17 03 03 02 6d f2 02 6d 15 de 46 b3 30 ef 57 |.....m..m..F.0.W| -000000b0 e5 a3 35 11 5c c3 b4 2e ad 74 ca db d2 90 eb b4 |..5.\....t......| -000000c0 ba 14 7e b0 65 68 e8 31 76 2a 28 e4 be bb d1 c3 |..~.eh.1v*(.....| -000000d0 45 cb ba 07 eb 27 d9 5e 4a 45 52 10 62 f0 8f b2 |E....'.^JER.b...| -000000e0 7c ad 0f 63 5c 39 f7 6e f2 68 3e bc fd ec fe fa ||..c\9.n.h>.....| -000000f0 9b ba 45 96 2b 94 27 34 2c 78 c8 5f 40 e3 f9 20 |..E.+.'4,x._@.. | -00000100 51 15 3d dc 70 d1 50 7c 26 6b 51 3f 47 61 0b e6 |Q.=.p.P|&kQ?Ga..| -00000110 04 ee 49 19 27 f0 91 c5 0f 15 0a 90 a6 0c 14 f2 |..I.'...........| -00000120 2f f1 42 28 be a0 7a ce 16 14 bf ff 34 34 a8 d8 |/.B(..z.....44..| -00000130 61 e6 26 6a 00 62 a0 82 53 c6 27 30 89 81 8d fb |a.&j.b..S.'0....| -00000140 9e 97 bc a0 ce 2f a1 e2 bf 9e fe d2 cc 11 4e 00 |...../........N.| -00000150 89 d1 e8 3b ab 58 e4 66 0a 87 00 b1 c1 a0 2d b0 |...;.X.f......-.| -00000160 96 b3 13 9b d3 c0 16 6b 87 e8 e3 9e 6c 30 1b 67 |.......k....l0.g| -00000170 c1 53 a5 4b 55 44 4e 27 6e ea 7c 7d 9f 44 b4 ca |.S.KUDN'n.|}.D..| -00000180 15 6f e5 d1 7f 18 e4 12 66 2d d5 a2 47 0c 73 26 |.o......f-..G.s&| -00000190 b0 bf 93 5b 46 9c 3f 78 69 05 a1 38 0f 61 ea d6 |...[F.?xi..8.a..| -000001a0 61 97 80 c5 72 be 6d be 2d e5 a2 9e d8 b3 bf 8d |a...r.m.-.......| -000001b0 a4 53 ba 6d fe c8 8d ac c1 4a 6e 76 bf 72 1e 5a |.S.m.....Jnv.r.Z| -000001c0 0a 51 f3 c8 1f 11 91 36 f0 f5 ba 68 e8 69 c3 77 |.Q.....6...h.i.w| -000001d0 52 63 dc b3 93 80 0d fd 9a 7d 7f f8 47 f8 62 2a |Rc.......}..G.b*| -000001e0 3d 4f 1b 46 9f cb 07 b6 96 00 b1 08 e7 32 50 41 |=O.F.........2PA| -000001f0 83 da 20 c2 b0 c0 33 33 3f f2 f9 84 f0 64 9f 37 |.. ...33?....d.7| -00000200 4b b6 7b ab 2e e9 50 8b 6a 61 da 12 51 54 13 25 |K.{...P.ja..QT.%| -00000210 46 5d 90 06 ef 88 4e be 64 67 80 02 1f 25 9c 28 |F]....N.dg...%.(| -00000220 07 b3 24 2b 10 81 c1 72 7c 94 97 b3 5a 16 bc cf |..$+...r|...Z...| -00000230 52 44 41 2c d7 ba e9 9f 4c d7 28 e6 b7 bb b0 fd |RDA,....L.(.....| -00000240 17 b2 0b 83 33 ed 2f c7 2d 42 37 fd 0a d0 4b c7 |....3./.-B7...K.| -00000250 97 61 17 d6 cd cd 0f e0 0d dd ab 40 fb 00 4d 81 |.a.........@..M.| -00000260 da 7d 1d 0e 48 d9 a7 6c ba 2a 21 49 18 0f a4 7c |.}..H..l.*!I...|| -00000270 af 0d 1b ca 94 f1 6c 78 59 ad 50 e4 1c 7b 37 45 |......lxY.P..{7E| -00000280 e8 1b 73 ad 96 8d 98 d6 07 26 07 fd a8 e6 8c 39 |..s......&.....9| -00000290 f1 5a 10 ef 04 97 fe d3 be cb f2 c1 5b 27 e8 d0 |.Z..........['..| -000002a0 f9 b3 16 b9 82 6d e8 be 54 c7 cf 44 a4 8a fd 75 |.....m..T..D...u| -000002b0 96 2a f1 65 2b d3 8f f5 86 a3 bf 12 74 c1 e4 d8 |.*.e+.......t...| -000002c0 a9 db c9 43 05 07 b1 51 dc 20 29 d0 c0 9a 6d 10 |...C...Q. )...m.| -000002d0 83 5f 87 a6 ab 03 58 43 1f 35 1c af dd 37 10 1b |._....XC.5...7..| -000002e0 16 50 52 e5 3c f5 3c ae 4f 92 7e dc 47 2e b3 9c |.PR.<.<.O.~.G...| -000002f0 1f d2 a0 31 8b 32 21 35 52 af bd f1 0b 2c 4e 6f |...1.2!5R....,No| -00000300 59 32 d8 db d6 9f b8 bd bc a0 3b 77 41 43 46 fb |Y2........;wACF.| -00000310 2b 0e 82 17 03 03 00 99 0a 63 cd 1f fa 90 4d 95 |+........c....M.| -00000320 17 d8 81 36 5c 62 17 33 6c 8d 9d 9f 26 3e 3a 2f |...6\b.3l...&>:/| -00000330 65 84 23 56 46 25 f6 1c dd ea 6f 21 b4 05 d8 19 |e.#VF%....o!....| -00000340 a3 c9 4b b1 03 78 39 32 00 97 6c d5 6e e3 ff 45 |..K..x92..l.n..E| -00000350 ac 2a 10 71 21 ad d3 b9 73 b7 77 0e a8 79 fd 50 |.*.q!...s.w..y.P| -00000360 a9 f1 41 39 2d 05 3d 92 3c 69 0a d7 7d 11 da f0 |..A9-.=.<i..}...| -00000370 fe 83 a6 c8 79 96 33 9c df 12 1c 39 90 da d3 94 |....y.3....9....| -00000380 7e 4a 5d 1c 31 b2 5c ea 33 2c 40 56 3a 80 86 0c |~J].1.\.3,@V:...| -00000390 93 bf 0f 56 b6 67 2e 4c 7f 9f 0c d5 58 9f 9d d6 |...V.g.L....X...| -000003a0 db e1 74 13 eb 7c a6 a5 1a 65 64 37 66 74 68 3a |..t..|...ed7fth:| -000003b0 73 17 03 03 00 35 53 63 0b ce 12 f7 f5 39 1d 20 |s....5Sc.....9. | -000003c0 41 89 5f a0 d2 fa 84 a3 2b e2 95 f4 9b e8 14 66 |A._.....+......f| -000003d0 2c c7 01 ad e9 ba 6c 11 86 c9 00 93 49 c1 af 30 |,.....l.....I..0| -000003e0 13 a7 59 16 a2 32 43 63 eb c2 64 17 03 03 00 93 |..Y..2Cc..d.....| -000003f0 20 da 02 66 ca 8d fa b5 4d 6a 0d e7 c6 a9 7b e2 | ..f....Mj....{.| -00000400 1c e8 61 c4 59 a2 30 f4 1b 27 c9 05 2e a1 33 93 |..a.Y.0..'....3.| -00000410 43 8a 70 15 9b 26 19 e3 0a a6 31 d9 ce 46 f7 78 |C.p..&....1..F.x| -00000420 bd 88 c4 ff 73 eb a0 3c 42 01 b0 6d 55 2c 61 7b |....s..<B..mU,a{| -00000430 d6 87 2f 50 6e 64 ae 73 69 a2 04 dc ec 3a e7 a5 |../Pnd.si....:..| -00000440 5c 24 df eb e8 bc 7b b9 df 3e a4 d8 26 1a ff 4b |\$....{..>..&..K| -00000450 a6 ce 93 36 ea a1 fd d9 78 61 a3 0e 08 72 da 03 |...6....xa...r..| -00000460 5d 0c 27 48 75 61 25 ef 77 39 39 e5 8e 87 2e 86 |].'Hua%.w99.....| -00000470 d5 70 d3 3b f4 b4 75 b1 44 d1 5f fe 9c d8 18 7d |.p.;..u.D._....}| -00000480 f9 89 20 |.. | ->>> Flow 3 (client to server) -00000000 14 03 03 00 01 01 17 03 03 00 35 a8 ab 13 71 ec |..........5...q.| -00000010 af a7 4a 48 65 6d 02 ea 8a 0f d1 4d 2a 97 b6 11 |..JHem.....M*...| -00000020 6d 53 5f be a4 b3 a7 20 d4 d3 aa 90 62 30 26 3f |mS_.... ....b0&?| -00000030 be c8 ed fc 6f 44 cc a5 3a 7f 4d 95 51 ed dc 80 |....oD..:.M.Q...| ->>> Flow 4 (server to client) -00000000 17 03 03 00 1e 6a f5 e4 df 1b 2a 5a 87 68 b1 a7 |.....j....*Z.h..| -00000010 1d b8 ef 04 b4 ac b9 50 b3 95 1c 12 d7 44 ca 46 |.......P.....D.F| -00000020 ea 26 2a 17 03 03 00 13 a4 6b 4d 27 81 62 b0 3c |.&*......kM'.b.<| -00000030 d0 be d1 34 46 4c 7b 6c 71 24 d8 |...4FL{lq$.| +00000080 03 03 00 01 01 17 03 03 00 13 7c ab 7f dd 94 cf |..........|.....| +00000090 d7 98 34 16 75 02 63 37 fa 4f 19 4e 18 |..4.u.c7.O.N.| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-NotConfigured b/libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-NotConfigured new file mode 100644 index 0000000..e0830d3 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv13-ALPN-NotConfigured @@ -0,0 +1,100 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 e2 01 00 00 de 03 03 9f 49 a7 46 f8 |............I.F.| +00000010 72 04 47 a1 8e 4f 89 c3 cd 89 92 2f 7a 8a 07 37 |r.G..O...../z..7| +00000020 8c 25 10 42 26 07 8b a2 71 3e 92 20 4c 83 1b 70 |.%.B&...q>. L..p| +00000030 45 c3 79 68 c3 83 a7 05 c2 22 06 c6 91 da 8b 96 |E.yh....."......| +00000040 4c 9d 89 c2 ec b8 49 87 17 3f 6c ae 00 04 13 03 |L.....I..?l.....| +00000050 00 ff 01 00 00 91 00 0b 00 04 03 00 01 02 00 0a |................| +00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#| +00000070 00 00 00 10 00 10 00 0e 06 70 72 6f 74 6f 32 06 |.........proto2.| +00000080 70 72 6f 74 6f 31 00 16 00 00 00 17 00 00 00 0d |proto1..........| +00000090 00 1e 00 1c 04 03 05 03 06 03 08 07 08 08 08 09 |................| +000000a0 08 0a 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 |................| +000000b0 00 2b 00 03 02 03 04 00 2d 00 02 01 01 00 33 00 |.+......-.....3.| +000000c0 26 00 24 00 1d 00 20 f4 91 87 6a ac cd 25 5e f1 |&.$... ...j..%^.| +000000d0 0d 25 fb af a4 d4 fb 16 32 63 af 04 2d 21 d7 2f |.%......2c..-!./| +000000e0 61 f2 c2 d4 c4 6c 2b |a....l+| +>>> Flow 2 (server to client) +00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 20 4c 83 1b 70 |........... L..p| +00000030 45 c3 79 68 c3 83 a7 05 c2 22 06 c6 91 da 8b 96 |E.yh....."......| +00000040 4c 9d 89 c2 ec b8 49 87 17 3f 6c ae 13 03 00 00 |L.....I..?l.....| +00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /| +00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0| +00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.| +00000080 03 03 00 01 01 17 03 03 00 17 60 79 16 61 4f 6c |..........`y.aOl| +00000090 9e 2e ce fd cc f5 29 67 38 e7 53 67 92 b1 5f 9d |......)g8.Sg.._.| +000000a0 db 17 03 03 02 6d 54 d9 d6 a1 8e c2 1b 70 3f 3d |.....mT......p?=| +000000b0 a2 2e 0f a5 37 96 e1 68 66 69 cc f8 e9 06 4d bc |....7..hfi....M.| +000000c0 c2 9a 6e 0f ea d4 73 59 6a 59 28 79 7f 44 0c 32 |..n...sYjY(y.D.2| +000000d0 29 22 51 d1 fb 00 c7 33 44 8b 19 71 98 8a 03 44 |)"Q....3D..q...D| +000000e0 e0 95 ad 8f 91 66 e6 15 b8 99 b3 f8 2f 02 e9 a0 |.....f....../...| +000000f0 4a 25 ec 3f 36 56 0c eb 0a a3 e0 d3 79 a1 b3 9e |J%.?6V......y...| +00000100 dc 42 08 76 a4 c3 55 91 06 11 e7 0c 94 dd 71 fc |.B.v..U.......q.| +00000110 bf 8a 87 d2 97 07 a3 b9 36 7e 58 ff ef b3 a3 f4 |........6~X.....| +00000120 6e f1 23 d6 50 e3 23 d3 dc e7 20 ce 9d 84 17 cf |n.#.P.#... .....| +00000130 2d 5f b1 f9 8d 36 41 7d ba 3b 93 63 2f bc be f0 |-_...6A}.;.c/...| +00000140 a1 3a bb 5f b3 99 03 13 fb d2 2c 1a 8c cc 32 02 |.:._......,...2.| +00000150 ef 93 b4 58 a8 f8 b1 42 52 24 c2 73 01 cb 5a fb |...X...BR$.s..Z.| +00000160 9f fc 38 08 d7 f9 0d d7 20 fa dc 8b 1a 8c 73 0f |..8..... .....s.| +00000170 f8 79 b2 84 e1 49 2d 8e 6d 46 16 38 0e 02 2a 2c |.y...I-.mF.8..*,| +00000180 f4 44 89 da f1 7a 01 55 9e 93 a8 d6 d5 f5 72 28 |.D...z.U......r(| +00000190 47 2b 4f 17 7e a5 01 fd ad 85 e0 6d f9 82 e8 cd |G+O.~......m....| +000001a0 09 18 84 8c 9d 4f 4e a1 43 ff d6 3d 55 05 fc 56 |.....ON.C..=U..V| +000001b0 e6 d6 b6 61 4a c7 c7 9c 62 64 26 1d 33 1e 4f d5 |...aJ...bd&.3.O.| +000001c0 5e ee 1f a9 ad 24 e4 7f 05 cc 02 7a f7 e0 c2 ce |^....$.....z....| +000001d0 b8 11 c9 a1 fd c5 d8 0e ef f8 c9 6a 2d 49 30 63 |...........j-I0c| +000001e0 e3 9b 43 bf 87 e1 5f 55 39 fa 80 ec 84 55 59 5d |..C..._U9....UY]| +000001f0 52 76 4c f4 70 eb 43 6a b2 07 d5 29 4c 58 39 04 |RvL.p.Cj...)LX9.| +00000200 46 42 70 8d 28 61 7c d5 7a 3a 2e a0 9f 74 49 2d |FBp.(a|.z:...tI-| +00000210 33 8d 39 18 70 8d 3c 50 4f 62 07 77 2d 15 1f 4b |3.9.p.<POb.w-..K| +00000220 22 01 c6 cb ac 2f 2d 9a cf a6 9b 0e 24 99 41 64 |"..../-.....$.Ad| +00000230 3e f2 9f 5f 17 7b d7 b8 3c b6 6d 24 5b 91 8c 13 |>.._.{..<.m$[...| +00000240 1a 40 4e 80 7f 44 12 57 c9 03 57 c6 9b 54 0d 39 |.@N..D.W..W..T.9| +00000250 91 88 72 3e c8 f9 18 eb 34 7c 0a eb 2d c8 56 1c |..r>....4|..-.V.| +00000260 84 8a 62 a2 3a 0a 52 b8 5a b6 5d 54 78 ae 05 b2 |..b.:.R.Z.]Tx...| +00000270 f4 6c 2d 5e 92 94 6b f3 1e 93 13 1a 65 74 60 e3 |.l-^..k.....et`.| +00000280 dd 15 36 62 2b 71 b1 bb 59 19 08 af 8e 9b d0 47 |..6b+q..Y......G| +00000290 05 7b a3 89 ac 68 cf a0 32 ba 4a 2b 9e 5f a5 dc |.{...h..2.J+._..| +000002a0 b3 00 79 a8 1c f6 11 b8 6d 9c 51 b7 f1 f6 b2 13 |..y.....m.Q.....| +000002b0 56 57 4e ac 97 ff 5a b8 52 33 0c c1 3d 52 81 6e |VWN...Z.R3..=R.n| +000002c0 85 ba b2 04 4b eb 41 aa 03 ff ae 63 93 72 3a 5f |....K.A....c.r:_| +000002d0 65 81 f9 6a 2a e4 70 f8 b3 59 31 51 62 ad 25 24 |e..j*.p..Y1Qb.%$| +000002e0 82 0c b5 ad 7c 87 21 97 07 c0 c1 6d f0 22 97 0d |....|.!....m."..| +000002f0 28 cf a7 4d 74 d2 9c ac d7 15 83 26 f7 2f 76 d4 |(..Mt......&./v.| +00000300 ad cf e7 ef 1c f4 3e 1f b4 f4 4f 76 6a 98 15 01 |......>...Ovj...| +00000310 cd 17 8b 17 03 03 00 99 0b 15 9d 16 c6 2a 52 53 |.............*RS| +00000320 33 d7 01 db 8a 49 1d d6 83 b7 28 a4 07 f0 73 5e |3....I....(...s^| +00000330 60 03 2c 6f 3f e0 88 a1 76 22 d6 23 0a df ca 86 |`.,o?...v".#....| +00000340 b0 44 b9 1d 9a d7 53 f2 2b 57 a1 65 01 d4 e7 b4 |.D....S.+W.e....| +00000350 9e 22 00 d2 20 da cd 55 7d 61 86 86 19 81 f9 ed |.".. ..U}a......| +00000360 f8 af c4 69 54 1d 35 0a 6f 9e 69 40 13 08 82 dd |...iT.5.o.i@....| +00000370 59 11 31 f2 81 a7 4b f1 bd d9 f2 5c 29 22 16 49 |Y.1...K....\)".I| +00000380 86 62 8c a8 b8 89 58 96 cc d1 e4 e8 5e ef 6c b7 |.b....X.....^.l.| +00000390 00 71 3d ab 92 b8 78 56 a7 25 5e a0 c4 d8 8c 02 |.q=...xV.%^.....| +000003a0 c4 c8 eb d3 be 68 21 05 5c 5f 9c b0 ec 20 99 ff |.....h!.\_... ..| +000003b0 00 17 03 03 00 35 c9 c1 5e 25 1c b9 64 8e c2 fd |.....5..^%..d...| +000003c0 50 87 48 e6 02 36 75 31 67 f6 82 3c 94 79 7d 0b |P.H..6u1g..<.y}.| +000003d0 cb 83 b1 f4 e1 00 5f a6 b6 2c 2d 63 40 ab 98 f9 |......_..,-c@...| +000003e0 e3 8e 4a 7e d4 77 3d 55 90 10 75 17 03 03 00 93 |..J~.w=U..u.....| +000003f0 47 c4 6e 19 29 c2 5e d5 93 b7 c2 cc 46 a9 49 9d |G.n.).^.....F.I.| +00000400 8a 3b 9a 35 bb 45 22 13 b6 eb c9 ec ba 44 3c 24 |.;.5.E"......D<$| +00000410 f2 ed bd 76 11 cc af 00 b3 89 63 5d 79 32 cc d7 |...v......c]y2..| +00000420 5c 34 f3 5e 64 36 92 5d ac ac 33 74 f4 3d c4 b8 |\4.^d6.]..3t.=..| +00000430 4d ac d0 49 4e 59 1c 16 74 8c 43 94 4b 13 b9 22 |M..INY..t.C.K.."| +00000440 de d7 ee 30 09 63 f3 32 5f a2 9d a1 20 ea ee 91 |...0.c.2_... ...| +00000450 ca d8 01 33 df 43 19 69 63 ee 6a 2c 80 99 ad f0 |...3.C.ic.j,....| +00000460 5e 20 b6 b6 81 28 b6 9d 4a 9a 91 30 30 04 c1 70 |^ ...(..J..00..p| +00000470 68 54 1e e0 72 00 4c fd 23 a8 41 a2 6a ab a3 01 |hT..r.L.#.A.j...| +00000480 7a 40 1a |z@.| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 17 03 03 00 35 20 1f 0d 20 a8 |..........5 .. .| +00000010 34 c4 dc fa f9 d6 2b fe 01 eb f1 54 f0 14 c2 2d |4.....+....T...-| +00000020 bb 59 db 04 96 f2 18 8b bd 7e b0 38 b7 15 b5 d8 |.Y.......~.8....| +00000030 6b f2 80 25 40 f6 97 67 fb 9e 5a 5c ad 33 c6 5f |k..%@..g..Z\.3._| +>>> Flow 4 (server to client) +00000000 17 03 03 00 1e 3a 8a fc 60 3a 99 ee b6 01 b7 fe |.....:..`:......| +00000010 54 a9 2d 34 28 ae af 3b 6a bd e0 32 6b df 87 fe |T.-4(..;j..2k...| +00000020 d0 97 8d 17 03 03 00 13 c6 89 d5 ae 4c fa d5 71 |............L..q| +00000030 66 6e 07 b5 9b 00 e8 50 7e b9 5f |fn.....P~._| diff --git a/libgo/go/crypto/tls/tls.go b/libgo/go/crypto/tls/tls.go index a389873..b529c70 100644 --- a/libgo/go/crypto/tls/tls.go +++ b/libgo/go/crypto/tls/tls.go @@ -25,7 +25,6 @@ import ( "net" "os" "strings" - "time" ) // Server returns a new TLS server side connection @@ -111,33 +110,24 @@ func (timeoutError) Temporary() bool { return true } // // DialWithDialer interprets a nil configuration as equivalent to the zero // configuration; see the documentation of Config for the defaults. +// +// DialWithDialer uses context.Background internally; to specify the context, +// use Dialer.DialContext with NetDialer set to the desired dialer. func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { return dial(context.Background(), dialer, network, addr, config) } func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { - // We want the Timeout and Deadline values from dialer to cover the - // whole process: TCP connection and TLS handshake. This means that we - // also need to start our own timers now. - timeout := netDialer.Timeout - - if !netDialer.Deadline.IsZero() { - deadlineTimeout := time.Until(netDialer.Deadline) - if timeout == 0 || deadlineTimeout < timeout { - timeout = deadlineTimeout - } + if netDialer.Timeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, netDialer.Timeout) + defer cancel() } - // hsErrCh is non-nil if we might not wait for Handshake to complete. - var hsErrCh chan error - if timeout != 0 || ctx.Done() != nil { - hsErrCh = make(chan error, 2) - } - if timeout != 0 { - timer := time.AfterFunc(timeout, func() { - hsErrCh <- timeoutError{} - }) - defer timer.Stop() + if !netDialer.Deadline.IsZero() { + var cancel context.CancelFunc + ctx, cancel = context.WithDeadline(ctx, netDialer.Deadline) + defer cancel() } rawConn, err := netDialer.DialContext(ctx, network, addr) @@ -164,34 +154,10 @@ func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, conf } conn := Client(rawConn, config) - - if hsErrCh == nil { - err = conn.Handshake() - } else { - go func() { - hsErrCh <- conn.Handshake() - }() - - select { - case <-ctx.Done(): - err = ctx.Err() - case err = <-hsErrCh: - if err != nil { - // If the error was due to the context - // closing, prefer the context's error, rather - // than some random network teardown error. - if e := ctx.Err(); e != nil { - err = e - } - } - } - } - - if err != nil { + if err := conn.HandshakeContext(ctx); err != nil { rawConn.Close() return nil, err } - return conn, nil } @@ -224,6 +190,9 @@ type Dialer struct { // handshake, returning the resulting TLS connection. // // The returned Conn, if any, will always be of type *Conn. +// +// Dial uses context.Background internally; to specify the context, +// use DialContext. func (d *Dialer) Dial(network, addr string) (net.Conn, error) { return d.DialContext(context.Background(), network, addr) } diff --git a/libgo/go/crypto/tls/tls_test.go b/libgo/go/crypto/tls/tls_test.go index 9995538..d8a43ad 100644 --- a/libgo/go/crypto/tls/tls_test.go +++ b/libgo/go/crypto/tls/tls_test.go @@ -18,6 +18,7 @@ import ( "net" "os" "reflect" + "sort" "strings" "testing" "time" @@ -1383,7 +1384,7 @@ func TestCipherSuites(t *testing.T) { } } - cipherSuiteByID := func(id uint16) *CipherSuite { + CipherSuiteByID := func(id uint16) *CipherSuite { for _, c := range CipherSuites() { if c.ID == id { return c @@ -1398,15 +1399,12 @@ func TestCipherSuites(t *testing.T) { } for _, c := range cipherSuites { - cc := cipherSuiteByID(c.id) + cc := CipherSuiteByID(c.id) if cc == nil { t.Errorf("%#04x: no CipherSuite entry", c.id) continue } - if defaultOff := c.flags&suiteDefaultOff != 0; defaultOff != cc.Insecure { - t.Errorf("%#04x: Insecure %v, expected %v", c.id, cc.Insecure, defaultOff) - } if tls12Only := c.flags&suiteTLS12 != 0; tls12Only && len(cc.SupportedVersions) != 1 { t.Errorf("%#04x: suite is TLS 1.2 only, but SupportedVersions is %v", c.id, cc.SupportedVersions) } else if !tls12Only && len(cc.SupportedVersions) != 3 { @@ -1418,7 +1416,7 @@ func TestCipherSuites(t *testing.T) { } } for _, c := range cipherSuitesTLS13 { - cc := cipherSuiteByID(c.id) + cc := CipherSuiteByID(c.id) if cc == nil { t.Errorf("%#04x: no CipherSuite entry", c.id) continue @@ -1439,6 +1437,143 @@ func TestCipherSuites(t *testing.T) { if got := CipherSuiteName(0xabc); got != "0x0ABC" { t.Errorf("unexpected fallback CipherSuiteName: got %q, expected 0x0ABC", got) } + + if len(cipherSuitesPreferenceOrder) != len(cipherSuites) { + t.Errorf("cipherSuitesPreferenceOrder is not the same size as cipherSuites") + } + if len(cipherSuitesPreferenceOrderNoAES) != len(cipherSuitesPreferenceOrder) { + t.Errorf("cipherSuitesPreferenceOrderNoAES is not the same size as cipherSuitesPreferenceOrder") + } + + // Check that disabled suites are at the end of the preference lists, and + // that they are marked insecure. + for i, id := range disabledCipherSuites { + offset := len(cipherSuitesPreferenceOrder) - len(disabledCipherSuites) + if cipherSuitesPreferenceOrder[offset+i] != id { + t.Errorf("disabledCipherSuites[%d]: not at the end of cipherSuitesPreferenceOrder", i) + } + if cipherSuitesPreferenceOrderNoAES[offset+i] != id { + t.Errorf("disabledCipherSuites[%d]: not at the end of cipherSuitesPreferenceOrderNoAES", i) + } + c := CipherSuiteByID(id) + if c == nil { + t.Errorf("%#04x: no CipherSuite entry", id) + continue + } + if !c.Insecure { + t.Errorf("%#04x: disabled by default but not marked insecure", id) + } + } + + for i, prefOrder := range [][]uint16{cipherSuitesPreferenceOrder, cipherSuitesPreferenceOrderNoAES} { + // Check that insecure and HTTP/2 bad cipher suites are at the end of + // the preference lists. + var sawInsecure, sawBad bool + for _, id := range prefOrder { + c := CipherSuiteByID(id) + if c == nil { + t.Errorf("%#04x: no CipherSuite entry", id) + continue + } + + if c.Insecure { + sawInsecure = true + } else if sawInsecure { + t.Errorf("%#04x: secure suite after insecure one(s)", id) + } + + if http2isBadCipher(id) { + sawBad = true + } else if sawBad { + t.Errorf("%#04x: non-bad suite after bad HTTP/2 one(s)", id) + } + } + + // Check that the list is sorted according to the documented criteria. + isBetter := func(a, b int) bool { + aSuite, bSuite := cipherSuiteByID(prefOrder[a]), cipherSuiteByID(prefOrder[b]) + aName, bName := CipherSuiteName(prefOrder[a]), CipherSuiteName(prefOrder[b]) + // * < RC4 + if !strings.Contains(aName, "RC4") && strings.Contains(bName, "RC4") { + return true + } else if strings.Contains(aName, "RC4") && !strings.Contains(bName, "RC4") { + return false + } + // * < CBC_SHA256 + if !strings.Contains(aName, "CBC_SHA256") && strings.Contains(bName, "CBC_SHA256") { + return true + } else if strings.Contains(aName, "CBC_SHA256") && !strings.Contains(bName, "CBC_SHA256") { + return false + } + // * < 3DES + if !strings.Contains(aName, "3DES") && strings.Contains(bName, "3DES") { + return true + } else if strings.Contains(aName, "3DES") && !strings.Contains(bName, "3DES") { + return false + } + // ECDHE < * + if aSuite.flags&suiteECDHE != 0 && bSuite.flags&suiteECDHE == 0 { + return true + } else if aSuite.flags&suiteECDHE == 0 && bSuite.flags&suiteECDHE != 0 { + return false + } + // AEAD < CBC + if aSuite.aead != nil && bSuite.aead == nil { + return true + } else if aSuite.aead == nil && bSuite.aead != nil { + return false + } + // AES < ChaCha20 + if strings.Contains(aName, "AES") && strings.Contains(bName, "CHACHA20") { + return i == 0 // true for cipherSuitesPreferenceOrder + } else if strings.Contains(aName, "CHACHA20") && strings.Contains(bName, "AES") { + return i != 0 // true for cipherSuitesPreferenceOrderNoAES + } + // AES-128 < AES-256 + if strings.Contains(aName, "AES_128") && strings.Contains(bName, "AES_256") { + return true + } else if strings.Contains(aName, "AES_256") && strings.Contains(bName, "AES_128") { + return false + } + // ECDSA < RSA + if aSuite.flags&suiteECSign != 0 && bSuite.flags&suiteECSign == 0 { + return true + } else if aSuite.flags&suiteECSign == 0 && bSuite.flags&suiteECSign != 0 { + return false + } + t.Fatalf("two ciphersuites are equal by all criteria: %v and %v", aName, bName) + panic("unreachable") + } + if !sort.SliceIsSorted(prefOrder, isBetter) { + t.Error("preference order is not sorted according to the rules") + } + } +} + +// http2isBadCipher is copied from net/http. +// TODO: if it ends up exposed somewhere, use that instead. +func http2isBadCipher(cipher uint16) bool { + switch cipher { + case TLS_RSA_WITH_RC4_128_SHA, + TLS_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_RSA_WITH_AES_128_CBC_SHA, + TLS_RSA_WITH_AES_256_CBC_SHA, + TLS_RSA_WITH_AES_128_CBC_SHA256, + TLS_RSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + TLS_ECDHE_RSA_WITH_RC4_128_SHA, + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + return true + default: + return false + } } type brokenSigner struct{ crypto.Signer } diff --git a/libgo/go/crypto/x509/internal/macos/corefoundation.go b/libgo/go/crypto/x509/internal/macos/corefoundation.go index 9b776d4..fcfbc1e 100644 --- a/libgo/go/crypto/x509/internal/macos/corefoundation.go +++ b/libgo/go/crypto/x509/internal/macos/corefoundation.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin && !ios // +build darwin,!ios // Package macOS provides cgo-less wrappers for Core Foundation and @@ -11,6 +12,7 @@ package macOS import ( "errors" + "internal/abi" "reflect" "runtime" "unsafe" @@ -39,24 +41,22 @@ type CFString CFRef const kCFAllocatorDefault = 0 const kCFStringEncodingUTF8 = 0x08000100 -//go:linkname x509_CFStringCreateWithBytes x509_CFStringCreateWithBytes //go:cgo_import_dynamic x509_CFStringCreateWithBytes CFStringCreateWithBytes "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" // StringToCFString returns a copy of the UTF-8 contents of s as a new CFString. func StringToCFString(s string) CFString { p := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&s)).Data) - ret := syscall(funcPC(x509_CFStringCreateWithBytes_trampoline), kCFAllocatorDefault, uintptr(p), + ret := syscall(abi.FuncPCABI0(x509_CFStringCreateWithBytes_trampoline), kCFAllocatorDefault, uintptr(p), uintptr(len(s)), uintptr(kCFStringEncodingUTF8), 0 /* isExternalRepresentation */, 0) runtime.KeepAlive(p) return CFString(ret) } func x509_CFStringCreateWithBytes_trampoline() -//go:linkname x509_CFDictionaryGetValueIfPresent x509_CFDictionaryGetValueIfPresent //go:cgo_import_dynamic x509_CFDictionaryGetValueIfPresent CFDictionaryGetValueIfPresent "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFDictionaryGetValueIfPresent(dict CFRef, key CFString) (value CFRef, ok bool) { - ret := syscall(funcPC(x509_CFDictionaryGetValueIfPresent_trampoline), uintptr(dict), uintptr(key), + ret := syscall(abi.FuncPCABI0(x509_CFDictionaryGetValueIfPresent_trampoline), uintptr(dict), uintptr(key), uintptr(unsafe.Pointer(&value)), 0, 0, 0) if ret == 0 { return 0, false @@ -67,12 +67,11 @@ func x509_CFDictionaryGetValueIfPresent_trampoline() const kCFNumberSInt32Type = 3 -//go:linkname x509_CFNumberGetValue x509_CFNumberGetValue //go:cgo_import_dynamic x509_CFNumberGetValue CFNumberGetValue "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFNumberGetValue(num CFRef) (int32, error) { var value int32 - ret := syscall(funcPC(x509_CFNumberGetValue_trampoline), uintptr(num), uintptr(kCFNumberSInt32Type), + ret := syscall(abi.FuncPCABI0(x509_CFNumberGetValue_trampoline), uintptr(num), uintptr(kCFNumberSInt32Type), uintptr(unsafe.Pointer(&value)), 0, 0, 0) if ret == 0 { return 0, errors.New("CFNumberGetValue call failed") @@ -81,65 +80,52 @@ func CFNumberGetValue(num CFRef) (int32, error) { } func x509_CFNumberGetValue_trampoline() -//go:linkname x509_CFDataGetLength x509_CFDataGetLength //go:cgo_import_dynamic x509_CFDataGetLength CFDataGetLength "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFDataGetLength(data CFRef) int { - ret := syscall(funcPC(x509_CFDataGetLength_trampoline), uintptr(data), 0, 0, 0, 0, 0) + ret := syscall(abi.FuncPCABI0(x509_CFDataGetLength_trampoline), uintptr(data), 0, 0, 0, 0, 0) return int(ret) } func x509_CFDataGetLength_trampoline() -//go:linkname x509_CFDataGetBytePtr x509_CFDataGetBytePtr //go:cgo_import_dynamic x509_CFDataGetBytePtr CFDataGetBytePtr "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFDataGetBytePtr(data CFRef) uintptr { - ret := syscall(funcPC(x509_CFDataGetBytePtr_trampoline), uintptr(data), 0, 0, 0, 0, 0) + ret := syscall(abi.FuncPCABI0(x509_CFDataGetBytePtr_trampoline), uintptr(data), 0, 0, 0, 0, 0) return ret } func x509_CFDataGetBytePtr_trampoline() -//go:linkname x509_CFArrayGetCount x509_CFArrayGetCount //go:cgo_import_dynamic x509_CFArrayGetCount CFArrayGetCount "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFArrayGetCount(array CFRef) int { - ret := syscall(funcPC(x509_CFArrayGetCount_trampoline), uintptr(array), 0, 0, 0, 0, 0) + ret := syscall(abi.FuncPCABI0(x509_CFArrayGetCount_trampoline), uintptr(array), 0, 0, 0, 0, 0) return int(ret) } func x509_CFArrayGetCount_trampoline() -//go:linkname x509_CFArrayGetValueAtIndex x509_CFArrayGetValueAtIndex //go:cgo_import_dynamic x509_CFArrayGetValueAtIndex CFArrayGetValueAtIndex "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFArrayGetValueAtIndex(array CFRef, index int) CFRef { - ret := syscall(funcPC(x509_CFArrayGetValueAtIndex_trampoline), uintptr(array), uintptr(index), 0, 0, 0, 0) + ret := syscall(abi.FuncPCABI0(x509_CFArrayGetValueAtIndex_trampoline), uintptr(array), uintptr(index), 0, 0, 0, 0) return CFRef(ret) } func x509_CFArrayGetValueAtIndex_trampoline() -//go:linkname x509_CFEqual x509_CFEqual //go:cgo_import_dynamic x509_CFEqual CFEqual "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFEqual(a, b CFRef) bool { - ret := syscall(funcPC(x509_CFEqual_trampoline), uintptr(a), uintptr(b), 0, 0, 0, 0) + ret := syscall(abi.FuncPCABI0(x509_CFEqual_trampoline), uintptr(a), uintptr(b), 0, 0, 0, 0) return ret == 1 } func x509_CFEqual_trampoline() -//go:linkname x509_CFRelease x509_CFRelease //go:cgo_import_dynamic x509_CFRelease CFRelease "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFRelease(ref CFRef) { - syscall(funcPC(x509_CFRelease_trampoline), uintptr(ref), 0, 0, 0, 0, 0) + syscall(abi.FuncPCABI0(x509_CFRelease_trampoline), uintptr(ref), 0, 0, 0, 0, 0) } func x509_CFRelease_trampoline() // syscall is implemented in the runtime package (runtime/sys_darwin.go) func syscall(fn, a1, a2, a3, a4, a5, a6 uintptr) uintptr - -// funcPC returns the entry point for f. See comments in runtime/proc.go -// for the function of the same name. -//go:nosplit -func funcPC(f func()) uintptr { - return **(**uintptr)(unsafe.Pointer(&f)) -} diff --git a/libgo/go/crypto/x509/internal/macos/security.go b/libgo/go/crypto/x509/internal/macos/security.go index 5e39e93..0f6fa42 100644 --- a/libgo/go/crypto/x509/internal/macos/security.go +++ b/libgo/go/crypto/x509/internal/macos/security.go @@ -2,12 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin && !ios // +build darwin,!ios package macOS import ( "errors" + "internal/abi" "strconv" "unsafe" ) @@ -63,11 +65,10 @@ var ErrNoTrustSettings = errors.New("no trust settings found") const errSecNoTrustSettings = -25263 -//go:linkname x509_SecTrustSettingsCopyCertificates x509_SecTrustSettingsCopyCertificates //go:cgo_import_dynamic x509_SecTrustSettingsCopyCertificates SecTrustSettingsCopyCertificates "/System/Library/Frameworks/Security.framework/Versions/A/Security" func SecTrustSettingsCopyCertificates(domain SecTrustSettingsDomain) (certArray CFRef, err error) { - ret := syscall(funcPC(x509_SecTrustSettingsCopyCertificates_trampoline), uintptr(domain), + ret := syscall(abi.FuncPCABI0(x509_SecTrustSettingsCopyCertificates_trampoline), uintptr(domain), uintptr(unsafe.Pointer(&certArray)), 0, 0, 0, 0) if int32(ret) == errSecNoTrustSettings { return 0, ErrNoTrustSettings @@ -80,11 +81,10 @@ func x509_SecTrustSettingsCopyCertificates_trampoline() const kSecFormatX509Cert int32 = 9 -//go:linkname x509_SecItemExport x509_SecItemExport //go:cgo_import_dynamic x509_SecItemExport SecItemExport "/System/Library/Frameworks/Security.framework/Versions/A/Security" func SecItemExport(cert CFRef) (data CFRef, err error) { - ret := syscall(funcPC(x509_SecItemExport_trampoline), uintptr(cert), uintptr(kSecFormatX509Cert), + ret := syscall(abi.FuncPCABI0(x509_SecItemExport_trampoline), uintptr(cert), uintptr(kSecFormatX509Cert), 0 /* flags */, 0 /* keyParams */, uintptr(unsafe.Pointer(&data)), 0) if ret != 0 { return 0, OSStatus{"SecItemExport", int32(ret)} @@ -95,11 +95,10 @@ func x509_SecItemExport_trampoline() const errSecItemNotFound = -25300 -//go:linkname x509_SecTrustSettingsCopyTrustSettings x509_SecTrustSettingsCopyTrustSettings //go:cgo_import_dynamic x509_SecTrustSettingsCopyTrustSettings SecTrustSettingsCopyTrustSettings "/System/Library/Frameworks/Security.framework/Versions/A/Security" func SecTrustSettingsCopyTrustSettings(cert CFRef, domain SecTrustSettingsDomain) (trustSettings CFRef, err error) { - ret := syscall(funcPC(x509_SecTrustSettingsCopyTrustSettings_trampoline), uintptr(cert), uintptr(domain), + ret := syscall(abi.FuncPCABI0(x509_SecTrustSettingsCopyTrustSettings_trampoline), uintptr(cert), uintptr(domain), uintptr(unsafe.Pointer(&trustSettings)), 0, 0, 0) if int32(ret) == errSecItemNotFound { return 0, ErrNoTrustSettings @@ -110,11 +109,10 @@ func SecTrustSettingsCopyTrustSettings(cert CFRef, domain SecTrustSettingsDomain } func x509_SecTrustSettingsCopyTrustSettings_trampoline() -//go:linkname x509_SecPolicyCopyProperties x509_SecPolicyCopyProperties //go:cgo_import_dynamic x509_SecPolicyCopyProperties SecPolicyCopyProperties "/System/Library/Frameworks/Security.framework/Versions/A/Security" func SecPolicyCopyProperties(policy CFRef) CFRef { - ret := syscall(funcPC(x509_SecPolicyCopyProperties_trampoline), uintptr(policy), 0, 0, 0, 0, 0) + ret := syscall(abi.FuncPCABI0(x509_SecPolicyCopyProperties_trampoline), uintptr(policy), 0, 0, 0, 0, 0) return CFRef(ret) } func x509_SecPolicyCopyProperties_trampoline() diff --git a/libgo/go/crypto/x509/name_constraints_test.go b/libgo/go/crypto/x509/name_constraints_test.go index 3826c82..c59a7dc 100644 --- a/libgo/go/crypto/x509/name_constraints_test.go +++ b/libgo/go/crypto/x509/name_constraints_test.go @@ -614,7 +614,8 @@ var nameConstraintsTests = []nameConstraintsTest{ }, }, - // #30: without SANs, a certificate with a CN is rejected in a constrained chain. + // #30: without SANs, a certificate with a CN is still accepted in a + // constrained chain, since we ignore the CN in VerifyHostname. { roots: []constraintsSpec{ { @@ -630,7 +631,6 @@ var nameConstraintsTests = []nameConstraintsTest{ sans: []string{}, cn: "foo.com", }, - expectedError: "leaf doesn't have a SAN extension", }, // #31: IPv6 addresses work in constraints: roots can permit them as @@ -1595,26 +1595,6 @@ var nameConstraintsTests = []nameConstraintsTest{ cn: "foo.bar", }, }, - - // #85: without SANs, a certificate with a valid CN is accepted in a - // constrained chain if x509ignoreCN is set. - { - roots: []constraintsSpec{ - { - ok: []string{"dns:foo.com", "dns:.foo.com"}, - }, - }, - intermediates: [][]constraintsSpec{ - { - {}, - }, - }, - leaf: leafSpec{ - sans: []string{}, - cn: "foo.com", - }, - ignoreCN: true, - }, } func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) { @@ -1865,10 +1845,6 @@ func parseEKUs(ekuStrs []string) (ekus []ExtKeyUsage, unknowns []asn1.ObjectIden } func TestConstraintCases(t *testing.T) { - defer func(savedIgnoreCN bool) { - ignoreCN = savedIgnoreCN - }(ignoreCN) - privateKeys := sync.Pool{ New: func() interface{} { priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) @@ -1960,7 +1936,6 @@ func TestConstraintCases(t *testing.T) { } } - ignoreCN = test.ignoreCN verifyOpts := VerifyOptions{ Roots: rootPool, Intermediates: intermediatePool, @@ -1999,7 +1974,6 @@ func TestConstraintCases(t *testing.T) { for _, key := range keys { privateKeys.Put(key) } - keys = keys[:0] } } diff --git a/libgo/go/crypto/x509/parser.go b/libgo/go/crypto/x509/parser.go new file mode 100644 index 0000000..f085162 --- /dev/null +++ b/libgo/go/crypto/x509/parser.go @@ -0,0 +1,1006 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package x509 + +import ( + "bytes" + "crypto/dsa" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rsa" + "crypto/x509/pkix" + "encoding/asn1" + "errors" + "fmt" + "math/big" + "net" + "net/url" + "strconv" + "strings" + "time" + "unicode/utf16" + "unicode/utf8" + + "golang.org/x/crypto/cryptobyte" + cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" +) + +// isPrintable reports whether the given b is in the ASN.1 PrintableString set. +// This is a simplified version of encoding/asn1.isPrintable. +func isPrintable(b byte) bool { + return 'a' <= b && b <= 'z' || + 'A' <= b && b <= 'Z' || + '0' <= b && b <= '9' || + '\'' <= b && b <= ')' || + '+' <= b && b <= '/' || + b == ' ' || + b == ':' || + b == '=' || + b == '?' || + // This is technically not allowed in a PrintableString. + // However, x509 certificates with wildcard strings don't + // always use the correct string type so we permit it. + b == '*' || + // This is not technically allowed either. However, not + // only is it relatively common, but there are also a + // handful of CA certificates that contain it. At least + // one of which will not expire until 2027. + b == '&' +} + +// parseASN1String parses the ASN.1 string types T61String, PrintableString, +// UTF8String, BMPString, and IA5String. This is mostly copied from the +// respective encoding/asn1.parse... methods, rather than just increasing +// the API surface of that package. +func parseASN1String(tag cryptobyte_asn1.Tag, value []byte) (string, error) { + switch tag { + case cryptobyte_asn1.T61String: + return string(value), nil + case cryptobyte_asn1.PrintableString: + for _, b := range value { + if !isPrintable(b) { + return "", errors.New("invalid PrintableString") + } + } + return string(value), nil + case cryptobyte_asn1.UTF8String: + if !utf8.Valid(value) { + return "", errors.New("invalid UTF-8 string") + } + return string(value), nil + case cryptobyte_asn1.Tag(asn1.TagBMPString): + if len(value)%2 != 0 { + return "", errors.New("invalid BMPString") + } + + // Strip terminator if present. + if l := len(value); l >= 2 && value[l-1] == 0 && value[l-2] == 0 { + value = value[:l-2] + } + + s := make([]uint16, 0, len(value)/2) + for len(value) > 0 { + s = append(s, uint16(value[0])<<8+uint16(value[1])) + value = value[2:] + } + + return string(utf16.Decode(s)), nil + case cryptobyte_asn1.IA5String: + s := string(value) + if isIA5String(s) != nil { + return "", errors.New("invalid IA5String") + } + return s, nil + } + return "", fmt.Errorf("unsupported string type: %v", tag) +} + +// parseName parses a DER encoded Name as defined in RFC 5280. We may +// want to export this function in the future for use in crypto/tls. +func parseName(raw cryptobyte.String) (*pkix.RDNSequence, error) { + if !raw.ReadASN1(&raw, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: invalid RDNSequence") + } + + var rdnSeq pkix.RDNSequence + for !raw.Empty() { + var rdnSet pkix.RelativeDistinguishedNameSET + var set cryptobyte.String + if !raw.ReadASN1(&set, cryptobyte_asn1.SET) { + return nil, errors.New("x509: invalid RDNSequence") + } + for !set.Empty() { + var atav cryptobyte.String + if !set.ReadASN1(&atav, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: invalid RDNSequence: invalid attribute") + } + var attr pkix.AttributeTypeAndValue + if !atav.ReadASN1ObjectIdentifier(&attr.Type) { + return nil, errors.New("x509: invalid RDNSequence: invalid attribute type") + } + var rawValue cryptobyte.String + var valueTag cryptobyte_asn1.Tag + if !atav.ReadAnyASN1(&rawValue, &valueTag) { + return nil, errors.New("x509: invalid RDNSequence: invalid attribute value") + } + var err error + attr.Value, err = parseASN1String(valueTag, rawValue) + if err != nil { + return nil, fmt.Errorf("x509: invalid RDNSequence: invalid attribute value: %s", err) + } + rdnSet = append(rdnSet, attr) + } + + rdnSeq = append(rdnSeq, rdnSet) + } + + return &rdnSeq, nil +} + +func parseAI(der cryptobyte.String) (pkix.AlgorithmIdentifier, error) { + ai := pkix.AlgorithmIdentifier{} + if !der.ReadASN1ObjectIdentifier(&ai.Algorithm) { + return ai, errors.New("x509: malformed OID") + } + if der.Empty() { + return ai, nil + } + var params cryptobyte.String + var tag cryptobyte_asn1.Tag + if !der.ReadAnyASN1Element(¶ms, &tag) { + return ai, errors.New("x509: malformed parameters") + } + ai.Parameters.Tag = int(tag) + ai.Parameters.FullBytes = params + return ai, nil +} + +func parseValidity(der cryptobyte.String) (time.Time, time.Time, error) { + extract := func() (time.Time, error) { + var t time.Time + switch { + case der.PeekASN1Tag(cryptobyte_asn1.UTCTime): + // TODO(rolandshoemaker): once #45411 is fixed, the following code + // should be replaced with a call to der.ReadASN1UTCTime. + var utc cryptobyte.String + if !der.ReadASN1(&utc, cryptobyte_asn1.UTCTime) { + return t, errors.New("x509: malformed UTCTime") + } + s := string(utc) + + formatStr := "0601021504Z0700" + var err error + t, err = time.Parse(formatStr, s) + if err != nil { + formatStr = "060102150405Z0700" + t, err = time.Parse(formatStr, s) + } + if err != nil { + return t, err + } + + if serialized := t.Format(formatStr); serialized != s { + return t, errors.New("x509: malformed UTCTime") + } + + if t.Year() >= 2050 { + // UTCTime only encodes times prior to 2050. See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 + t = t.AddDate(-100, 0, 0) + } + case der.PeekASN1Tag(cryptobyte_asn1.GeneralizedTime): + if !der.ReadASN1GeneralizedTime(&t) { + return t, errors.New("x509: malformed GeneralizedTime") + } + default: + return t, errors.New("x509: unsupported time format") + } + return t, nil + } + + notBefore, err := extract() + if err != nil { + return time.Time{}, time.Time{}, err + } + notAfter, err := extract() + if err != nil { + return time.Time{}, time.Time{}, err + } + + return notBefore, notAfter, nil +} + +func parseExtension(der cryptobyte.String) (pkix.Extension, error) { + var ext pkix.Extension + if !der.ReadASN1ObjectIdentifier(&ext.Id) { + return ext, errors.New("x509: malformed extention OID field") + } + if der.PeekASN1Tag(cryptobyte_asn1.BOOLEAN) { + if !der.ReadASN1Boolean(&ext.Critical) { + return ext, errors.New("x509: malformed extention critical field") + } + } + var val cryptobyte.String + if !der.ReadASN1(&val, cryptobyte_asn1.OCTET_STRING) { + return ext, errors.New("x509: malformed extention value field") + } + ext.Value = val + return ext, nil +} + +func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) { + der := cryptobyte.String(keyData.PublicKey.RightAlign()) + switch algo { + case RSA: + // RSA public keys must have a NULL in the parameters. + // See RFC 3279, Section 2.3.1. + if !bytes.Equal(keyData.Algorithm.Parameters.FullBytes, asn1.NullBytes) { + return nil, errors.New("x509: RSA key missing NULL parameters") + } + + p := &pkcs1PublicKey{N: new(big.Int)} + if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: invalid RSA public key") + } + if !der.ReadASN1Integer(p.N) { + return nil, errors.New("x509: invalid RSA modulus") + } + if !der.ReadASN1Integer(&p.E) { + return nil, errors.New("x509: invalid RSA public exponent") + } + + if p.N.Sign() <= 0 { + return nil, errors.New("x509: RSA modulus is not a positive number") + } + if p.E <= 0 { + return nil, errors.New("x509: RSA public exponent is not a positive number") + } + + pub := &rsa.PublicKey{ + E: p.E, + N: p.N, + } + return pub, nil + case ECDSA: + paramsDer := cryptobyte.String(keyData.Algorithm.Parameters.FullBytes) + namedCurveOID := new(asn1.ObjectIdentifier) + if !paramsDer.ReadASN1ObjectIdentifier(namedCurveOID) { + return nil, errors.New("x509: invalid ECDSA parameters") + } + namedCurve := namedCurveFromOID(*namedCurveOID) + if namedCurve == nil { + return nil, errors.New("x509: unsupported elliptic curve") + } + x, y := elliptic.Unmarshal(namedCurve, der) + if x == nil { + return nil, errors.New("x509: failed to unmarshal elliptic curve point") + } + pub := &ecdsa.PublicKey{ + Curve: namedCurve, + X: x, + Y: y, + } + return pub, nil + case Ed25519: + // RFC 8410, Section 3 + // > For all of the OIDs, the parameters MUST be absent. + if len(keyData.Algorithm.Parameters.FullBytes) != 0 { + return nil, errors.New("x509: Ed25519 key encoded with illegal parameters") + } + if len(der) != ed25519.PublicKeySize { + return nil, errors.New("x509: wrong Ed25519 public key size") + } + return ed25519.PublicKey(der), nil + case DSA: + y := new(big.Int) + if !der.ReadASN1Integer(y) { + return nil, errors.New("x509: invalid DSA public key") + } + pub := &dsa.PublicKey{ + Y: y, + Parameters: dsa.Parameters{ + P: new(big.Int), + Q: new(big.Int), + G: new(big.Int), + }, + } + paramsDer := cryptobyte.String(keyData.Algorithm.Parameters.FullBytes) + if !paramsDer.ReadASN1(¶msDer, cryptobyte_asn1.SEQUENCE) || + !paramsDer.ReadASN1Integer(pub.Parameters.P) || + !paramsDer.ReadASN1Integer(pub.Parameters.Q) || + !paramsDer.ReadASN1Integer(pub.Parameters.G) { + return nil, errors.New("x509: invalid DSA parameters") + } + if pub.Y.Sign() <= 0 || pub.Parameters.P.Sign() <= 0 || + pub.Parameters.Q.Sign() <= 0 || pub.Parameters.G.Sign() <= 0 { + return nil, errors.New("x509: zero or negative DSA parameter") + } + return pub, nil + default: + return nil, nil + } +} + +func parseKeyUsageExtension(der cryptobyte.String) (KeyUsage, error) { + var usageBits asn1.BitString + if !der.ReadASN1BitString(&usageBits) { + return 0, errors.New("x509: invalid key usage") + } + + var usage int + for i := 0; i < 9; i++ { + if usageBits.At(i) != 0 { + usage |= 1 << uint(i) + } + } + return KeyUsage(usage), nil +} + +func parseBasicConstraintsExtension(der cryptobyte.String) (bool, int, error) { + var isCA bool + if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) { + return false, 0, errors.New("x509: invalid basic constraints a") + } + if der.PeekASN1Tag(cryptobyte_asn1.BOOLEAN) { + if !der.ReadASN1Boolean(&isCA) { + return false, 0, errors.New("x509: invalid basic constraints b") + } + } + maxPathLen := -1 + if !der.Empty() && der.PeekASN1Tag(cryptobyte_asn1.INTEGER) { + if !der.ReadASN1Integer(&maxPathLen) { + return false, 0, errors.New("x509: invalid basic constraints c") + } + } + + // TODO: map out.MaxPathLen to 0 if it has the -1 default value? (Issue 19285) + return isCA, maxPathLen, nil +} + +func forEachSAN(der cryptobyte.String, callback func(tag int, data []byte) error) error { + if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) { + return errors.New("x509: invalid subject alternative names") + } + for !der.Empty() { + var san cryptobyte.String + var tag cryptobyte_asn1.Tag + if !der.ReadAnyASN1(&san, &tag) { + return errors.New("x509: invalid subject alternative name") + } + if err := callback(int(tag^0x80), san); err != nil { + return err + } + } + + return nil +} + +func parseSANExtension(der cryptobyte.String) (dnsNames, emailAddresses []string, ipAddresses []net.IP, uris []*url.URL, err error) { + err = forEachSAN(der, func(tag int, data []byte) error { + switch tag { + case nameTypeEmail: + email := string(data) + if err := isIA5String(email); err != nil { + return errors.New("x509: SAN rfc822Name is malformed") + } + emailAddresses = append(emailAddresses, email) + case nameTypeDNS: + name := string(data) + if err := isIA5String(name); err != nil { + return errors.New("x509: SAN dNSName is malformed") + } + dnsNames = append(dnsNames, string(name)) + case nameTypeURI: + uriStr := string(data) + if err := isIA5String(uriStr); err != nil { + return errors.New("x509: SAN uniformResourceIdentifier is malformed") + } + uri, err := url.Parse(uriStr) + if err != nil { + return fmt.Errorf("x509: cannot parse URI %q: %s", uriStr, err) + } + if len(uri.Host) > 0 { + if _, ok := domainToReverseLabels(uri.Host); !ok { + return fmt.Errorf("x509: cannot parse URI %q: invalid domain", uriStr) + } + } + uris = append(uris, uri) + case nameTypeIP: + switch len(data) { + case net.IPv4len, net.IPv6len: + ipAddresses = append(ipAddresses, data) + default: + return errors.New("x509: cannot parse IP address of length " + strconv.Itoa(len(data))) + } + } + + return nil + }) + + return +} + +func parseExtKeyUsageExtension(der cryptobyte.String) ([]ExtKeyUsage, []asn1.ObjectIdentifier, error) { + var extKeyUsages []ExtKeyUsage + var unknownUsages []asn1.ObjectIdentifier + if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) { + return nil, nil, errors.New("x509: invalid extended key usages") + } + for !der.Empty() { + var eku asn1.ObjectIdentifier + if !der.ReadASN1ObjectIdentifier(&eku) { + return nil, nil, errors.New("x509: invalid extended key usages") + } + if extKeyUsage, ok := extKeyUsageFromOID(eku); ok { + extKeyUsages = append(extKeyUsages, extKeyUsage) + } else { + unknownUsages = append(unknownUsages, eku) + } + } + return extKeyUsages, unknownUsages, nil +} + +func parseCertificatePoliciesExtension(der cryptobyte.String) ([]asn1.ObjectIdentifier, error) { + var oids []asn1.ObjectIdentifier + if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: invalid certificate policies") + } + for !der.Empty() { + var cp cryptobyte.String + if !der.ReadASN1(&cp, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: invalid certificate policies") + } + var oid asn1.ObjectIdentifier + if !cp.ReadASN1ObjectIdentifier(&oid) { + return nil, errors.New("x509: invalid certificate policies") + } + oids = append(oids, oid) + } + + return oids, nil +} + +// isValidIPMask reports whether mask consists of zero or more 1 bits, followed by zero bits. +func isValidIPMask(mask []byte) bool { + seenZero := false + + for _, b := range mask { + if seenZero { + if b != 0 { + return false + } + + continue + } + + switch b { + case 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe: + seenZero = true + case 0xff: + default: + return false + } + } + + return true +} + +func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandled bool, err error) { + // RFC 5280, 4.2.1.10 + + // NameConstraints ::= SEQUENCE { + // permittedSubtrees [0] GeneralSubtrees OPTIONAL, + // excludedSubtrees [1] GeneralSubtrees OPTIONAL } + // + // GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree + // + // GeneralSubtree ::= SEQUENCE { + // base GeneralName, + // minimum [0] BaseDistance DEFAULT 0, + // maximum [1] BaseDistance OPTIONAL } + // + // BaseDistance ::= INTEGER (0..MAX) + + outer := cryptobyte.String(e.Value) + var toplevel, permitted, excluded cryptobyte.String + var havePermitted, haveExcluded bool + if !outer.ReadASN1(&toplevel, cryptobyte_asn1.SEQUENCE) || + !outer.Empty() || + !toplevel.ReadOptionalASN1(&permitted, &havePermitted, cryptobyte_asn1.Tag(0).ContextSpecific().Constructed()) || + !toplevel.ReadOptionalASN1(&excluded, &haveExcluded, cryptobyte_asn1.Tag(1).ContextSpecific().Constructed()) || + !toplevel.Empty() { + return false, errors.New("x509: invalid NameConstraints extension") + } + + if !havePermitted && !haveExcluded || len(permitted) == 0 && len(excluded) == 0 { + // From RFC 5280, Section 4.2.1.10: + // “either the permittedSubtrees field + // or the excludedSubtrees MUST be + // present” + return false, errors.New("x509: empty name constraints extension") + } + + getValues := func(subtrees cryptobyte.String) (dnsNames []string, ips []*net.IPNet, emails, uriDomains []string, err error) { + for !subtrees.Empty() { + var seq, value cryptobyte.String + var tag cryptobyte_asn1.Tag + if !subtrees.ReadASN1(&seq, cryptobyte_asn1.SEQUENCE) || + !seq.ReadAnyASN1(&value, &tag) { + return nil, nil, nil, nil, fmt.Errorf("x509: invalid NameConstraints extension") + } + + var ( + dnsTag = cryptobyte_asn1.Tag(2).ContextSpecific() + emailTag = cryptobyte_asn1.Tag(1).ContextSpecific() + ipTag = cryptobyte_asn1.Tag(7).ContextSpecific() + uriTag = cryptobyte_asn1.Tag(6).ContextSpecific() + ) + + switch tag { + case dnsTag: + domain := string(value) + if err := isIA5String(domain); err != nil { + return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error()) + } + + trimmedDomain := domain + if len(trimmedDomain) > 0 && trimmedDomain[0] == '.' { + // constraints can have a leading + // period to exclude the domain + // itself, but that's not valid in a + // normal domain name. + trimmedDomain = trimmedDomain[1:] + } + if _, ok := domainToReverseLabels(trimmedDomain); !ok { + return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse dnsName constraint %q", domain) + } + dnsNames = append(dnsNames, domain) + + case ipTag: + l := len(value) + var ip, mask []byte + + switch l { + case 8: + ip = value[:4] + mask = value[4:] + + case 32: + ip = value[:16] + mask = value[16:] + + default: + return nil, nil, nil, nil, fmt.Errorf("x509: IP constraint contained value of length %d", l) + } + + if !isValidIPMask(mask) { + return nil, nil, nil, nil, fmt.Errorf("x509: IP constraint contained invalid mask %x", mask) + } + + ips = append(ips, &net.IPNet{IP: net.IP(ip), Mask: net.IPMask(mask)}) + + case emailTag: + constraint := string(value) + if err := isIA5String(constraint); err != nil { + return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error()) + } + + // If the constraint contains an @ then + // it specifies an exact mailbox name. + if strings.Contains(constraint, "@") { + if _, ok := parseRFC2821Mailbox(constraint); !ok { + return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint) + } + } else { + // Otherwise it's a domain name. + domain := constraint + if len(domain) > 0 && domain[0] == '.' { + domain = domain[1:] + } + if _, ok := domainToReverseLabels(domain); !ok { + return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint) + } + } + emails = append(emails, constraint) + + case uriTag: + domain := string(value) + if err := isIA5String(domain); err != nil { + return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error()) + } + + if net.ParseIP(domain) != nil { + return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q: cannot be IP address", domain) + } + + trimmedDomain := domain + if len(trimmedDomain) > 0 && trimmedDomain[0] == '.' { + // constraints can have a leading + // period to exclude the domain itself, + // but that's not valid in a normal + // domain name. + trimmedDomain = trimmedDomain[1:] + } + if _, ok := domainToReverseLabels(trimmedDomain); !ok { + return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q", domain) + } + uriDomains = append(uriDomains, domain) + + default: + unhandled = true + } + } + + return dnsNames, ips, emails, uriDomains, nil + } + + if out.PermittedDNSDomains, out.PermittedIPRanges, out.PermittedEmailAddresses, out.PermittedURIDomains, err = getValues(permitted); err != nil { + return false, err + } + if out.ExcludedDNSDomains, out.ExcludedIPRanges, out.ExcludedEmailAddresses, out.ExcludedURIDomains, err = getValues(excluded); err != nil { + return false, err + } + out.PermittedDNSDomainsCritical = e.Critical + + return unhandled, nil +} + +func processExtensions(out *Certificate) error { + var err error + for _, e := range out.Extensions { + unhandled := false + + if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 { + switch e.Id[3] { + case 15: + out.KeyUsage, err = parseKeyUsageExtension(e.Value) + if err != nil { + return err + } + case 19: + out.IsCA, out.MaxPathLen, err = parseBasicConstraintsExtension(e.Value) + if err != nil { + return err + } + out.BasicConstraintsValid = true + out.MaxPathLenZero = out.MaxPathLen == 0 + case 17: + out.DNSNames, out.EmailAddresses, out.IPAddresses, out.URIs, err = parseSANExtension(e.Value) + if err != nil { + return err + } + + if len(out.DNSNames) == 0 && len(out.EmailAddresses) == 0 && len(out.IPAddresses) == 0 && len(out.URIs) == 0 { + // If we didn't parse anything then we do the critical check, below. + unhandled = true + } + + case 30: + unhandled, err = parseNameConstraintsExtension(out, e) + if err != nil { + return err + } + + case 31: + // RFC 5280, 4.2.1.13 + + // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint + // + // DistributionPoint ::= SEQUENCE { + // distributionPoint [0] DistributionPointName OPTIONAL, + // reasons [1] ReasonFlags OPTIONAL, + // cRLIssuer [2] GeneralNames OPTIONAL } + // + // DistributionPointName ::= CHOICE { + // fullName [0] GeneralNames, + // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } + val := cryptobyte.String(e.Value) + if !val.ReadASN1(&val, cryptobyte_asn1.SEQUENCE) { + return errors.New("x509: invalid CRL distribution points") + } + for !val.Empty() { + var dpDER cryptobyte.String + if !val.ReadASN1(&dpDER, cryptobyte_asn1.SEQUENCE) { + return errors.New("x509: invalid CRL distribution point") + } + var dpNameDER cryptobyte.String + var dpNamePresent bool + if !dpDER.ReadOptionalASN1(&dpNameDER, &dpNamePresent, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific()) { + return errors.New("x509: invalid CRL distribution point") + } + if !dpNamePresent { + continue + } + if !dpNameDER.ReadASN1(&dpNameDER, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific()) { + return errors.New("x509: invalid CRL distribution point") + } + for !dpNameDER.Empty() { + if !dpNameDER.PeekASN1Tag(cryptobyte_asn1.Tag(6).ContextSpecific()) { + break + } + var uri cryptobyte.String + if !dpNameDER.ReadASN1(&uri, cryptobyte_asn1.Tag(6).ContextSpecific()) { + return errors.New("x509: invalid CRL distribution point") + } + out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(uri)) + } + } + + case 35: + // RFC 5280, 4.2.1.1 + val := cryptobyte.String(e.Value) + var akid cryptobyte.String + if !val.ReadASN1(&akid, cryptobyte_asn1.SEQUENCE) { + return errors.New("x509: invalid authority key identifier") + } + if akid.PeekASN1Tag(cryptobyte_asn1.Tag(0).ContextSpecific()) { + if !akid.ReadASN1(&akid, cryptobyte_asn1.Tag(0).ContextSpecific()) { + return errors.New("x509: invalid authority key identifier") + } + out.AuthorityKeyId = akid + } + case 37: + out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(e.Value) + if err != nil { + return err + } + case 14: + // RFC 5280, 4.2.1.2 + val := cryptobyte.String(e.Value) + var skid cryptobyte.String + if !val.ReadASN1(&skid, cryptobyte_asn1.OCTET_STRING) { + return errors.New("x509: invalid subject key identifier") + } + out.SubjectKeyId = skid + case 32: + out.PolicyIdentifiers, err = parseCertificatePoliciesExtension(e.Value) + if err != nil { + return err + } + default: + // Unknown extensions are recorded if critical. + unhandled = true + } + } else if e.Id.Equal(oidExtensionAuthorityInfoAccess) { + // RFC 5280 4.2.2.1: Authority Information Access + val := cryptobyte.String(e.Value) + if !val.ReadASN1(&val, cryptobyte_asn1.SEQUENCE) { + return errors.New("x509: invalid authority info access") + } + for !val.Empty() { + var aiaDER cryptobyte.String + if !val.ReadASN1(&aiaDER, cryptobyte_asn1.SEQUENCE) { + return errors.New("x509: invalid authority info access") + } + var method asn1.ObjectIdentifier + if !aiaDER.ReadASN1ObjectIdentifier(&method) { + return errors.New("x509: invalid authority info access") + } + if !aiaDER.PeekASN1Tag(cryptobyte_asn1.Tag(6).ContextSpecific()) { + continue + } + if !aiaDER.ReadASN1(&aiaDER, cryptobyte_asn1.Tag(6).ContextSpecific()) { + return errors.New("x509: invalid authority info access") + } + switch { + case method.Equal(oidAuthorityInfoAccessOcsp): + out.OCSPServer = append(out.OCSPServer, string(aiaDER)) + case method.Equal(oidAuthorityInfoAccessIssuers): + out.IssuingCertificateURL = append(out.IssuingCertificateURL, string(aiaDER)) + } + } + } else { + // Unknown extensions are recorded if critical. + unhandled = true + } + + if e.Critical && unhandled { + out.UnhandledCriticalExtensions = append(out.UnhandledCriticalExtensions, e.Id) + } + } + + return nil +} + +func parseCertificate(der []byte) (*Certificate, error) { + cert := &Certificate{} + + input := cryptobyte.String(der) + // we read the SEQUENCE including length and tag bytes so that + // we can populate Certificate.Raw, before unwrapping the + // SEQUENCE so it can be operated on + if !input.ReadASN1Element(&input, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed certificate") + } + cert.Raw = input + if !input.ReadASN1(&input, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed certificate") + } + + var tbs cryptobyte.String + // do the same trick again as above to extract the raw + // bytes for Certificate.RawTBSCertificate + if !input.ReadASN1Element(&tbs, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed tbs certificate") + } + cert.RawTBSCertificate = tbs + if !tbs.ReadASN1(&tbs, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed tbs certificate") + } + + if !tbs.ReadOptionalASN1Integer(&cert.Version, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific(), 0) { + return nil, errors.New("x509: malformed version") + } + if cert.Version < 0 { + return nil, errors.New("x509: malformed version") + } + // for backwards compat reasons Version is one-indexed, + // rather than zero-indexed as defined in 5280 + cert.Version++ + if cert.Version > 3 { + return nil, errors.New("x509: invalid version") + } + + serial := new(big.Int) + if !tbs.ReadASN1Integer(serial) { + return nil, errors.New("x509: malformed serial number") + } + // we ignore the presence of negative serial numbers because + // of their prevalence, despite them being invalid + // TODO(rolandshoemaker): revist this decision, there are currently + // only 10 trusted certificates with negative serial numbers + // according to censys.io. + cert.SerialNumber = serial + + var sigAISeq cryptobyte.String + if !tbs.ReadASN1(&sigAISeq, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed signature algorithm identifier") + } + // Before parsing the inner algorithm identifier, extract + // the outer algorithm identifier and make sure that they + // match. + var outerSigAISeq cryptobyte.String + if !input.ReadASN1(&outerSigAISeq, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed algorithm identifier") + } + if !bytes.Equal(outerSigAISeq, sigAISeq) { + return nil, errors.New("x509: inner and outer signature algorithm identifiers don't match") + } + sigAI, err := parseAI(sigAISeq) + if err != nil { + return nil, err + } + cert.SignatureAlgorithm = getSignatureAlgorithmFromAI(sigAI) + + var issuerSeq cryptobyte.String + if !tbs.ReadASN1Element(&issuerSeq, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed issuer") + } + cert.RawIssuer = issuerSeq + issuerRDNs, err := parseName(issuerSeq) + if err != nil { + return nil, err + } + cert.Issuer.FillFromRDNSequence(issuerRDNs) + + var validity cryptobyte.String + if !tbs.ReadASN1(&validity, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed validity") + } + cert.NotBefore, cert.NotAfter, err = parseValidity(validity) + if err != nil { + return nil, err + } + + var subjectSeq cryptobyte.String + if !tbs.ReadASN1Element(&subjectSeq, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed issuer") + } + cert.RawSubject = subjectSeq + subjectRDNs, err := parseName(subjectSeq) + if err != nil { + return nil, err + } + cert.Subject.FillFromRDNSequence(subjectRDNs) + + var spki cryptobyte.String + if !tbs.ReadASN1Element(&spki, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed spki") + } + cert.RawSubjectPublicKeyInfo = spki + if !spki.ReadASN1(&spki, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed spki") + } + var pkAISeq cryptobyte.String + if !spki.ReadASN1(&pkAISeq, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed public key algorithm identifier") + } + pkAI, err := parseAI(pkAISeq) + if err != nil { + return nil, err + } + cert.PublicKeyAlgorithm = getPublicKeyAlgorithmFromOID(pkAI.Algorithm) + var spk asn1.BitString + if !spki.ReadASN1BitString(&spk) { + return nil, errors.New("x509: malformed subjectPublicKey") + } + cert.PublicKey, err = parsePublicKey(cert.PublicKeyAlgorithm, &publicKeyInfo{ + Algorithm: pkAI, + PublicKey: spk, + }) + if err != nil { + return nil, err + } + + if cert.Version > 1 { + if !tbs.SkipOptionalASN1(cryptobyte_asn1.Tag(1).Constructed().ContextSpecific()) { + return nil, errors.New("x509: malformed issuerUniqueID") + } + if !tbs.SkipOptionalASN1(cryptobyte_asn1.Tag(2).Constructed().ContextSpecific()) { + return nil, errors.New("x509: malformed subjectUniqueID") + } + if cert.Version == 3 { + var extensions cryptobyte.String + var present bool + if !tbs.ReadOptionalASN1(&extensions, &present, cryptobyte_asn1.Tag(3).Constructed().ContextSpecific()) { + return nil, errors.New("x509: malformed extensions") + } + if present { + if !extensions.ReadASN1(&extensions, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed extensions") + } + for !extensions.Empty() { + var extension cryptobyte.String + if !extensions.ReadASN1(&extension, cryptobyte_asn1.SEQUENCE) { + return nil, errors.New("x509: malformed extension") + } + ext, err := parseExtension(extension) + if err != nil { + return nil, err + } + cert.Extensions = append(cert.Extensions, ext) + } + err = processExtensions(cert) + if err != nil { + return nil, err + } + } + } + } + + var signature asn1.BitString + if !input.ReadASN1BitString(&signature) { + return nil, errors.New("x509: malformed signature") + } + cert.Signature = signature.RightAlign() + + return cert, nil +} + +// ParseCertificate parses a single certificate from the given ASN.1 DER data. +func ParseCertificate(der []byte) (*Certificate, error) { + cert, err := parseCertificate(der) + if err != nil { + return nil, err + } + if len(der) != len(cert.Raw) { + return nil, errors.New("x509: trailing data") + } + return cert, err +} + +// ParseCertificates parses one or more certificates from the given ASN.1 DER +// data. The certificates must be concatenated with no intermediate padding. +func ParseCertificates(der []byte) ([]*Certificate, error) { + var certs []*Certificate + for len(der) > 0 { + cert, err := parseCertificate(der) + if err != nil { + return nil, err + } + certs = append(certs, cert) + der = der[len(cert.Raw):] + } + return certs, nil +} diff --git a/libgo/go/crypto/x509/root.go b/libgo/go/crypto/x509/root.go index cc53f7a..eef9c04 100644 --- a/libgo/go/crypto/x509/root.go +++ b/libgo/go/crypto/x509/root.go @@ -8,7 +8,7 @@ package x509 // argument to the latest security_certificates version from // https://opensource.apple.com/source/security_certificates/ // and run "go generate". See https://golang.org/issue/38843. -//go:generate go run root_ios_gen.go -version 55188.40.9 +//go:generate go run root_ios_gen.go -version 55188.120.1.0.1 import "sync" diff --git a/libgo/go/crypto/x509/root_bsd.go b/libgo/go/crypto/x509/root_bsd.go index f04b6bd..6712ea3 100644 --- a/libgo/go/crypto/x509/root_bsd.go +++ b/libgo/go/crypto/x509/root_bsd.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build dragonfly || freebsd || netbsd || openbsd // +build dragonfly freebsd netbsd openbsd package x509 @@ -17,6 +18,7 @@ var certFiles = []string{ // Possible directories with certificate files; stop after successfully // reading at least one file from a directory. var certDirectories = []string{ + "/etc/ssl/certs", // FreeBSD 12.2+ "/usr/local/share/certs", // FreeBSD "/etc/openssl/certs", // NetBSD } diff --git a/libgo/go/crypto/x509/root_darwin.go b/libgo/go/crypto/x509/root_darwin.go index c9ea7e8..05593bb 100644 --- a/libgo/go/crypto/x509/root_darwin.go +++ b/libgo/go/crypto/x509/root_darwin.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !ios // +build !ios package x509 diff --git a/libgo/go/crypto/x509/root_ios.go b/libgo/go/crypto/x509/root_ios.go index d2dfb62..9bc62f8 100644 --- a/libgo/go/crypto/x509/root_ios.go +++ b/libgo/go/crypto/x509/root_ios.go @@ -1,8 +1,8 @@ -// Code generated by root_ios_gen.go -version 55188.40.9; DO NOT EDIT. +// Code generated by root_ios_gen.go -version 55188.120.1.0.1; DO NOT EDIT. // Update the version in root.go and regenerate with "go generate". -// +build ios -// +build !x509omitbundledroots +//go:build ios && !x509omitbundledroots +// +build ios,!x509omitbundledroots package x509 @@ -2223,6 +2223,41 @@ uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs ewv4n4Q= -----END CERTIFICATE----- +# "GlobalSign" +# 2C AB EA FE 37 D0 6C A2 2A BA 73 91 C0 03 3D 25 +# 98 29 52 C4 53 64 73 49 76 3A 3A B5 AD 6C CF 69 +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg +MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh +bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx +MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET +MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI +xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k +ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD +aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw +LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw +1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX +k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2 +SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h +bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n +WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY +rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce +MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu +bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN +nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt +Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61 +55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj +vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf +cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz +oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp +nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs +pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v +JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R +8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 +5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= +-----END CERTIFICATE----- # "GlobalSign Root CA" # EB D4 10 40 E4 BB 3E C7 42 C9 E3 81 D3 1E F2 A4 # 1A 48 B6 68 5C 96 E7 CE F3 C1 DF 6C D4 33 1C 99 diff --git a/libgo/go/crypto/x509/root_ios_gen.go b/libgo/go/crypto/x509/root_ios_gen.go index 8bc6e7d..05bd672 100644 --- a/libgo/go/crypto/x509/root_ios_gen.go +++ b/libgo/go/crypto/x509/root_ios_gen.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // Generates root_ios.go. diff --git a/libgo/go/crypto/x509/root_js.go b/libgo/go/crypto/x509/root_js.go index 4e537a4..f2c2c0a 100644 --- a/libgo/go/crypto/x509/root_js.go +++ b/libgo/go/crypto/x509/root_js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package x509 diff --git a/libgo/go/crypto/x509/root_omit.go b/libgo/go/crypto/x509/root_omit.go index 0055b3b..81f2f11 100644 --- a/libgo/go/crypto/x509/root_omit.go +++ b/libgo/go/crypto/x509/root_omit.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ((darwin && arm64) || (darwin && amd64 && ios)) && x509omitbundledroots // +build darwin,arm64 darwin,amd64,ios // +build x509omitbundledroots diff --git a/libgo/go/crypto/x509/root_omit_test.go b/libgo/go/crypto/x509/root_omit_test.go index 5ab6c93..158bd7f 100644 --- a/libgo/go/crypto/x509/root_omit_test.go +++ b/libgo/go/crypto/x509/root_omit_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ((darwin && arm64) || (darwin && amd64 && ios)) && x509omitbundledroots // +build darwin,arm64 darwin,amd64,ios // +build x509omitbundledroots diff --git a/libgo/go/crypto/x509/root_plan9.go b/libgo/go/crypto/x509/root_plan9.go index 2dc4aaf..2bdb2fe 100644 --- a/libgo/go/crypto/x509/root_plan9.go +++ b/libgo/go/crypto/x509/root_plan9.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build plan9 // +build plan9 package x509 diff --git a/libgo/go/crypto/x509/root_unix.go b/libgo/go/crypto/x509/root_unix.go index 3d09663..4ed95e4 100644 --- a/libgo/go/crypto/x509/root_unix.go +++ b/libgo/go/crypto/x509/root_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package x509 diff --git a/libgo/go/crypto/x509/root_unix_test.go b/libgo/go/crypto/x509/root_unix_test.go index 878ed7c..7118f12 100644 --- a/libgo/go/crypto/x509/root_unix_test.go +++ b/libgo/go/crypto/x509/root_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build dragonfly || freebsd || linux || netbsd || openbsd || solaris // +build dragonfly freebsd linux netbsd openbsd solaris package x509 @@ -146,11 +147,7 @@ func TestLoadSystemCertsLoadColonSeparatedDirs(t *testing.T) { os.Setenv(certFileEnv, origFile) }() - tmpDir, err := os.MkdirTemp(os.TempDir(), "x509-issue35325") - if err != nil { - t.Fatalf("Failed to create temporary directory: %v", err) - } - defer os.RemoveAll(tmpDir) + tmpDir := t.TempDir() rootPEMs := []string{ geoTrustRoot, diff --git a/libgo/go/crypto/x509/verify.go b/libgo/go/crypto/x509/verify.go index 46afb26..9ef1146 100644 --- a/libgo/go/crypto/x509/verify.go +++ b/libgo/go/crypto/x509/verify.go @@ -10,7 +10,6 @@ import ( "fmt" "net" "net/url" - "os" "reflect" "runtime" "strings" @@ -18,9 +17,6 @@ import ( "unicode/utf8" ) -// ignoreCN disables interpreting Common Name as a hostname. See issue 24151. -var ignoreCN = !strings.Contains(os.Getenv("GODEBUG"), "x509ignoreCN=0") - type InvalidReason int const ( @@ -43,14 +39,7 @@ const ( // NameMismatch results when the subject name of a parent certificate // does not match the issuer name in the child. NameMismatch - // NameConstraintsWithoutSANs results when a leaf certificate doesn't - // contain a Subject Alternative Name extension, but a CA certificate - // contains name constraints, and the Common Name can be interpreted as - // a hostname. - // - // This error is only returned when legacy Common Name matching is enabled - // by setting the GODEBUG environment variable to "x509ignoreCN=1". This - // setting might be removed in the future. + // NameConstraintsWithoutSANs is a legacy error and is no longer returned. NameConstraintsWithoutSANs // UnconstrainedName results when a CA certificate contains permitted // name constraints, but leaf certificate contains a name of an @@ -110,15 +99,7 @@ func (h HostnameError) Error() string { c := h.Certificate if !c.hasSANExtension() && matchHostnames(c.Subject.CommonName, h.Host) { - if !ignoreCN && !validHostnamePattern(c.Subject.CommonName) { - // This would have validated, if it weren't for the validHostname check on Common Name. - return "x509: Common Name is not a valid hostname: " + c.Subject.CommonName - } - if ignoreCN && validHostnamePattern(c.Subject.CommonName) { - // This would have validated if x509ignoreCN=0 were set. - return "x509: certificate relies on legacy Common Name field, " + - "use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0" - } + return "x509: certificate relies on legacy Common Name field, use SANs instead" } var valid string @@ -134,11 +115,7 @@ func (h HostnameError) Error() string { valid += san.String() } } else { - if c.commonNameAsHostname() { - valid = c.Subject.CommonName - } else { - valid = strings.Join(c.DNSNames, ", ") - } + valid = strings.Join(c.DNSNames, ", ") } if len(valid) == 0 { @@ -620,15 +597,8 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V leaf = currentChain[0] } - checkNameConstraints := (certType == intermediateCertificate || certType == rootCertificate) && c.hasNameConstraints() - if checkNameConstraints && leaf.commonNameAsHostname() { - // This is the deprecated, legacy case of depending on the commonName as - // a hostname. We don't enforce name constraints against the CN, but - // VerifyHostname will look for hostnames in there if there are no SANs. - // In order to ensure VerifyHostname will not accept an unchecked name, - // return an error here. - return CertificateInvalidError{c, NameConstraintsWithoutSANs, ""} - } else if checkNameConstraints && leaf.hasSANExtension() { + if (certType == intermediateCertificate || certType == rootCertificate) && + c.hasNameConstraints() && leaf.hasSANExtension() { err := forEachSAN(leaf.getSANExtension(), func(tag int, data []byte) error { switch tag { case nameTypeEmail: @@ -837,7 +807,7 @@ func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate } // maxChainSignatureChecks is the maximum number of CheckSignatureFrom calls -// that an invocation of buildChains will (tranistively) make. Most chains are +// that an invocation of buildChains will (transitively) make. Most chains are // less than 15 certificates long, so this leaves space for multiple chains and // for failed checks due to different intermediates having the same Subject. const maxChainSignatureChecks = 100 @@ -960,18 +930,6 @@ func validHostname(host string, isPattern bool) bool { return true } -// commonNameAsHostname reports whether the Common Name field should be -// considered the hostname that the certificate is valid for. This is a legacy -// behavior, disabled by default or if the Subject Alt Name extension is present. -// -// It applies the strict validHostname check to the Common Name field, so that -// certificates without SANs can still be validated against CAs with name -// constraints if there is no risk the CN would be matched as a hostname. -// See NameConstraintsWithoutSANs and issue 24151. -func (c *Certificate) commonNameAsHostname() bool { - return !ignoreCN && !c.hasSANExtension() && validHostnamePattern(c.Subject.CommonName) -} - func matchExactly(hostA, hostB string) bool { if hostA == "" || hostA == "." || hostB == "" || hostB == "." { return false @@ -1046,10 +1004,7 @@ func toLowerCaseASCII(in string) string { // against the DNSNames field. If the names are valid hostnames, the certificate // fields can have a wildcard as the left-most label. // -// The legacy Common Name field is ignored unless it's a valid hostname, the -// certificate doesn't have any Subject Alternative Names, and the GODEBUG -// environment variable is set to "x509ignoreCN=0". Support for Common Name is -// deprecated will be entirely removed in the future. +// Note that the legacy Common Name field is ignored. func (c *Certificate) VerifyHostname(h string) error { // IP addresses may be written in [ ]. candidateIP := h @@ -1067,15 +1022,10 @@ func (c *Certificate) VerifyHostname(h string) error { return HostnameError{c, candidateIP} } - names := c.DNSNames - if c.commonNameAsHostname() { - names = []string{c.Subject.CommonName} - } - candidateName := toLowerCaseASCII(h) // Save allocations inside the loop. validCandidateName := validHostnameInput(candidateName) - for _, match := range names { + for _, match := range c.DNSNames { // Ideally, we'd only match valid hostnames according to RFC 6125 like // browsers (more or less) do, but in practice Go is used in a wider // array of contexts and can't even assume DNS resolution. Instead, diff --git a/libgo/go/crypto/x509/verify_test.go b/libgo/go/crypto/x509/verify_test.go index 8e0a7be..9954a67 100644 --- a/libgo/go/crypto/x509/verify_test.go +++ b/libgo/go/crypto/x509/verify_test.go @@ -30,7 +30,6 @@ type verifyTest struct { systemSkip bool systemLax bool keyUsages []ExtKeyUsage - ignoreCN bool errorCallback func(*testing.T, error) expectedChains [][]string @@ -297,8 +296,6 @@ var verifyTests = []verifyTest{ errorCallback: expectNotAuthorizedError, }, { - // If any SAN extension is present (even one without any DNS - // names), the CN should be ignored. name: "IgnoreCNWithSANs", leaf: ignoreCNWithSANLeaf, dnsName: "foo.example.com", @@ -325,7 +322,6 @@ var verifyTests = []verifyTest{ // verify error. name: "CriticalExtLeaf", leaf: criticalExtLeafWithExt, - dnsName: "example.com", intermediates: []string{criticalExtIntermediate}, roots: []string{criticalExtRoot}, currentTime: 1486684488, @@ -338,7 +334,6 @@ var verifyTests = []verifyTest{ // cause a verify error. name: "CriticalExtIntermediate", leaf: criticalExtLeaf, - dnsName: "example.com", intermediates: []string{criticalExtIntermediateWithExt}, roots: []string{criticalExtRoot}, currentTime: 1486684488, @@ -347,18 +342,6 @@ var verifyTests = []verifyTest{ errorCallback: expectUnhandledCriticalExtension, }, { - // Test that invalid CN are ignored. - name: "InvalidCN", - leaf: invalidCNWithoutSAN, - dnsName: "foo,invalid", - roots: []string{invalidCNRoot}, - currentTime: 1540000000, - systemSkip: true, // does not chain to a system root - - errorCallback: expectHostnameError("Common Name is not a valid hostname"), - }, - { - // Test that valid CN are respected. name: "ValidCN", leaf: validCNWithoutSAN, dnsName: "foo.example.com", @@ -366,42 +349,6 @@ var verifyTests = []verifyTest{ currentTime: 1540000000, systemSkip: true, // does not chain to a system root - expectedChains: [][]string{ - {"foo.example.com", "Test root"}, - }, - }, - // Replicate CN tests with ignoreCN = true - { - name: "IgnoreCNWithSANs/ignoreCN", - leaf: ignoreCNWithSANLeaf, - dnsName: "foo.example.com", - roots: []string{ignoreCNWithSANRoot}, - currentTime: 1486684488, - systemSkip: true, // does not chain to a system root - ignoreCN: true, - - errorCallback: expectHostnameError("certificate is not valid for any names"), - }, - { - name: "InvalidCN/ignoreCN", - leaf: invalidCNWithoutSAN, - dnsName: "foo,invalid", - roots: []string{invalidCNRoot}, - currentTime: 1540000000, - systemSkip: true, // does not chain to a system root - ignoreCN: true, - - errorCallback: expectHostnameError("certificate is not valid for any names"), - }, - { - name: "ValidCN/ignoreCN", - leaf: validCNWithoutSAN, - dnsName: "foo.example.com", - roots: []string{invalidCNRoot}, - currentTime: 1540000000, - systemSkip: true, // does not chain to a system root - ignoreCN: true, - errorCallback: expectHostnameError("certificate relies on legacy Common Name field"), }, { @@ -503,9 +450,6 @@ func certificateFromPEM(pemBytes string) (*Certificate, error) { } func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) { - defer func(savedIgnoreCN bool) { ignoreCN = savedIgnoreCN }(ignoreCN) - - ignoreCN = test.ignoreCN opts := VerifyOptions{ Intermediates: NewCertPool(), DNSName: test.dnsName, @@ -1589,16 +1533,6 @@ oCGMjNwwCgYIKoZIzj0EAwIDRwAwRAIgDSiwgIn8g1lpruYH0QD1GYeoWVunfmrI XzZZl0eW/ugCICgOfXeZ2GGy3wIC0352BaC3a8r5AAb2XSGNe+e9wNN6 -----END CERTIFICATE-----` -const invalidCNWithoutSAN = `-----BEGIN CERTIFICATE----- -MIIBJDCBywIUB7q8t9mrDAL+UB1OFaMN5BEWFKIwCgYIKoZIzj0EAwIwFDESMBAG -A1UECwwJVGVzdCByb290MB4XDTE4MDcxMTE4MzUyMVoXDTI4MDcwODE4MzUyMVow -FjEUMBIGA1UEAwwLZm9vLGludmFsaWQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC -AASnpnwiM6dHfwiTLV9hNS7aRWd28pdzGLABEkoa1bdvQTy7BWn0Bl3/6yunhQtM -90VOgUB6qcYdu7rZuSazylCQMAoGCCqGSM49BAMCA0gAMEUCIQCFlnW2cjxnEqB/ -hgSB0t3IZ1DXX4XAVFT85mtFCJPTKgIgYIY+1iimTtrdbpWJzAB2eBwDgIWmWgvr -xfOcLt/vbvo= ------END CERTIFICATE-----` - const validCNWithoutSAN = `-----BEGIN CERTIFICATE----- MIIBJzCBzwIUB7q8t9mrDAL+UB1OFaMN5BEWFKQwCgYIKoZIzj0EAwIwFDESMBAG A1UECwwJVGVzdCByb290MB4XDTE4MDcxMTE4NDcyNFoXDTI4MDcwODE4NDcyNFow diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go index 8c0299b..4304ab5 100644 --- a/libgo/go/crypto/x509/x509.go +++ b/libgo/go/crypto/x509/x509.go @@ -8,7 +8,6 @@ package x509 import ( "bytes" "crypto" - "crypto/dsa" "crypto/ecdsa" "crypto/ed25519" "crypto/elliptic" @@ -24,7 +23,6 @@ import ( "net" "net/url" "strconv" - "strings" "time" "unicode" @@ -914,676 +912,6 @@ type distributionPointName struct { RelativeName pkix.RDNSequence `asn1:"optional,tag:1"` } -func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) { - asn1Data := keyData.PublicKey.RightAlign() - switch algo { - case RSA: - // RSA public keys must have a NULL in the parameters. - // See RFC 3279, Section 2.3.1. - if !bytes.Equal(keyData.Algorithm.Parameters.FullBytes, asn1.NullBytes) { - return nil, errors.New("x509: RSA key missing NULL parameters") - } - - p := new(pkcs1PublicKey) - rest, err := asn1.Unmarshal(asn1Data, p) - if err != nil { - return nil, err - } - if len(rest) != 0 { - return nil, errors.New("x509: trailing data after RSA public key") - } - - if p.N.Sign() <= 0 { - return nil, errors.New("x509: RSA modulus is not a positive number") - } - if p.E <= 0 { - return nil, errors.New("x509: RSA public exponent is not a positive number") - } - - pub := &rsa.PublicKey{ - E: p.E, - N: p.N, - } - return pub, nil - case DSA: - var p *big.Int - rest, err := asn1.Unmarshal(asn1Data, &p) - if err != nil { - return nil, err - } - if len(rest) != 0 { - return nil, errors.New("x509: trailing data after DSA public key") - } - paramsData := keyData.Algorithm.Parameters.FullBytes - params := new(dsaAlgorithmParameters) - rest, err = asn1.Unmarshal(paramsData, params) - if err != nil { - return nil, err - } - if len(rest) != 0 { - return nil, errors.New("x509: trailing data after DSA parameters") - } - if p.Sign() <= 0 || params.P.Sign() <= 0 || params.Q.Sign() <= 0 || params.G.Sign() <= 0 { - return nil, errors.New("x509: zero or negative DSA parameter") - } - pub := &dsa.PublicKey{ - Parameters: dsa.Parameters{ - P: params.P, - Q: params.Q, - G: params.G, - }, - Y: p, - } - return pub, nil - case ECDSA: - paramsData := keyData.Algorithm.Parameters.FullBytes - namedCurveOID := new(asn1.ObjectIdentifier) - rest, err := asn1.Unmarshal(paramsData, namedCurveOID) - if err != nil { - return nil, errors.New("x509: failed to parse ECDSA parameters as named curve") - } - if len(rest) != 0 { - return nil, errors.New("x509: trailing data after ECDSA parameters") - } - namedCurve := namedCurveFromOID(*namedCurveOID) - if namedCurve == nil { - return nil, errors.New("x509: unsupported elliptic curve") - } - x, y := elliptic.Unmarshal(namedCurve, asn1Data) - if x == nil { - return nil, errors.New("x509: failed to unmarshal elliptic curve point") - } - pub := &ecdsa.PublicKey{ - Curve: namedCurve, - X: x, - Y: y, - } - return pub, nil - case Ed25519: - // RFC 8410, Section 3 - // > For all of the OIDs, the parameters MUST be absent. - if len(keyData.Algorithm.Parameters.FullBytes) != 0 { - return nil, errors.New("x509: Ed25519 key encoded with illegal parameters") - } - if len(asn1Data) != ed25519.PublicKeySize { - return nil, errors.New("x509: wrong Ed25519 public key size") - } - pub := make([]byte, ed25519.PublicKeySize) - copy(pub, asn1Data) - return ed25519.PublicKey(pub), nil - default: - return nil, nil - } -} - -func forEachSAN(extension []byte, callback func(tag int, data []byte) error) error { - // RFC 5280, 4.2.1.6 - - // SubjectAltName ::= GeneralNames - // - // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName - // - // GeneralName ::= CHOICE { - // otherName [0] OtherName, - // rfc822Name [1] IA5String, - // dNSName [2] IA5String, - // x400Address [3] ORAddress, - // directoryName [4] Name, - // ediPartyName [5] EDIPartyName, - // uniformResourceIdentifier [6] IA5String, - // iPAddress [7] OCTET STRING, - // registeredID [8] OBJECT IDENTIFIER } - var seq asn1.RawValue - rest, err := asn1.Unmarshal(extension, &seq) - if err != nil { - return err - } else if len(rest) != 0 { - return errors.New("x509: trailing data after X.509 extension") - } - if !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 { - return asn1.StructuralError{Msg: "bad SAN sequence"} - } - - rest = seq.Bytes - for len(rest) > 0 { - var v asn1.RawValue - rest, err = asn1.Unmarshal(rest, &v) - if err != nil { - return err - } - - if err := callback(v.Tag, v.Bytes); err != nil { - return err - } - } - - return nil -} - -func parseSANExtension(value []byte) (dnsNames, emailAddresses []string, ipAddresses []net.IP, uris []*url.URL, err error) { - err = forEachSAN(value, func(tag int, data []byte) error { - switch tag { - case nameTypeEmail: - email := string(data) - if err := isIA5String(email); err != nil { - return errors.New("x509: SAN rfc822Name is malformed") - } - emailAddresses = append(emailAddresses, email) - case nameTypeDNS: - name := string(data) - if err := isIA5String(name); err != nil { - return errors.New("x509: SAN dNSName is malformed") - } - dnsNames = append(dnsNames, string(name)) - case nameTypeURI: - uriStr := string(data) - if err := isIA5String(uriStr); err != nil { - return errors.New("x509: SAN uniformResourceIdentifier is malformed") - } - uri, err := url.Parse(uriStr) - if err != nil { - return fmt.Errorf("x509: cannot parse URI %q: %s", uriStr, err) - } - if len(uri.Host) > 0 { - if _, ok := domainToReverseLabels(uri.Host); !ok { - return fmt.Errorf("x509: cannot parse URI %q: invalid domain", uriStr) - } - } - uris = append(uris, uri) - case nameTypeIP: - switch len(data) { - case net.IPv4len, net.IPv6len: - ipAddresses = append(ipAddresses, data) - default: - return errors.New("x509: cannot parse IP address of length " + strconv.Itoa(len(data))) - } - } - - return nil - }) - - return -} - -// isValidIPMask reports whether mask consists of zero or more 1 bits, followed by zero bits. -func isValidIPMask(mask []byte) bool { - seenZero := false - - for _, b := range mask { - if seenZero { - if b != 0 { - return false - } - - continue - } - - switch b { - case 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe: - seenZero = true - case 0xff: - default: - return false - } - } - - return true -} - -func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandled bool, err error) { - // RFC 5280, 4.2.1.10 - - // NameConstraints ::= SEQUENCE { - // permittedSubtrees [0] GeneralSubtrees OPTIONAL, - // excludedSubtrees [1] GeneralSubtrees OPTIONAL } - // - // GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree - // - // GeneralSubtree ::= SEQUENCE { - // base GeneralName, - // minimum [0] BaseDistance DEFAULT 0, - // maximum [1] BaseDistance OPTIONAL } - // - // BaseDistance ::= INTEGER (0..MAX) - - outer := cryptobyte.String(e.Value) - var toplevel, permitted, excluded cryptobyte.String - var havePermitted, haveExcluded bool - if !outer.ReadASN1(&toplevel, cryptobyte_asn1.SEQUENCE) || - !outer.Empty() || - !toplevel.ReadOptionalASN1(&permitted, &havePermitted, cryptobyte_asn1.Tag(0).ContextSpecific().Constructed()) || - !toplevel.ReadOptionalASN1(&excluded, &haveExcluded, cryptobyte_asn1.Tag(1).ContextSpecific().Constructed()) || - !toplevel.Empty() { - return false, errors.New("x509: invalid NameConstraints extension") - } - - if !havePermitted && !haveExcluded || len(permitted) == 0 && len(excluded) == 0 { - // From RFC 5280, Section 4.2.1.10: - // “either the permittedSubtrees field - // or the excludedSubtrees MUST be - // present” - return false, errors.New("x509: empty name constraints extension") - } - - getValues := func(subtrees cryptobyte.String) (dnsNames []string, ips []*net.IPNet, emails, uriDomains []string, err error) { - for !subtrees.Empty() { - var seq, value cryptobyte.String - var tag cryptobyte_asn1.Tag - if !subtrees.ReadASN1(&seq, cryptobyte_asn1.SEQUENCE) || - !seq.ReadAnyASN1(&value, &tag) { - return nil, nil, nil, nil, fmt.Errorf("x509: invalid NameConstraints extension") - } - - var ( - dnsTag = cryptobyte_asn1.Tag(2).ContextSpecific() - emailTag = cryptobyte_asn1.Tag(1).ContextSpecific() - ipTag = cryptobyte_asn1.Tag(7).ContextSpecific() - uriTag = cryptobyte_asn1.Tag(6).ContextSpecific() - ) - - switch tag { - case dnsTag: - domain := string(value) - if err := isIA5String(domain); err != nil { - return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error()) - } - - trimmedDomain := domain - if len(trimmedDomain) > 0 && trimmedDomain[0] == '.' { - // constraints can have a leading - // period to exclude the domain - // itself, but that's not valid in a - // normal domain name. - trimmedDomain = trimmedDomain[1:] - } - if _, ok := domainToReverseLabels(trimmedDomain); !ok { - return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse dnsName constraint %q", domain) - } - dnsNames = append(dnsNames, domain) - - case ipTag: - l := len(value) - var ip, mask []byte - - switch l { - case 8: - ip = value[:4] - mask = value[4:] - - case 32: - ip = value[:16] - mask = value[16:] - - default: - return nil, nil, nil, nil, fmt.Errorf("x509: IP constraint contained value of length %d", l) - } - - if !isValidIPMask(mask) { - return nil, nil, nil, nil, fmt.Errorf("x509: IP constraint contained invalid mask %x", mask) - } - - ips = append(ips, &net.IPNet{IP: net.IP(ip), Mask: net.IPMask(mask)}) - - case emailTag: - constraint := string(value) - if err := isIA5String(constraint); err != nil { - return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error()) - } - - // If the constraint contains an @ then - // it specifies an exact mailbox name. - if strings.Contains(constraint, "@") { - if _, ok := parseRFC2821Mailbox(constraint); !ok { - return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint) - } - } else { - // Otherwise it's a domain name. - domain := constraint - if len(domain) > 0 && domain[0] == '.' { - domain = domain[1:] - } - if _, ok := domainToReverseLabels(domain); !ok { - return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint) - } - } - emails = append(emails, constraint) - - case uriTag: - domain := string(value) - if err := isIA5String(domain); err != nil { - return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error()) - } - - if net.ParseIP(domain) != nil { - return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q: cannot be IP address", domain) - } - - trimmedDomain := domain - if len(trimmedDomain) > 0 && trimmedDomain[0] == '.' { - // constraints can have a leading - // period to exclude the domain itself, - // but that's not valid in a normal - // domain name. - trimmedDomain = trimmedDomain[1:] - } - if _, ok := domainToReverseLabels(trimmedDomain); !ok { - return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q", domain) - } - uriDomains = append(uriDomains, domain) - - default: - unhandled = true - } - } - - return dnsNames, ips, emails, uriDomains, nil - } - - if out.PermittedDNSDomains, out.PermittedIPRanges, out.PermittedEmailAddresses, out.PermittedURIDomains, err = getValues(permitted); err != nil { - return false, err - } - if out.ExcludedDNSDomains, out.ExcludedIPRanges, out.ExcludedEmailAddresses, out.ExcludedURIDomains, err = getValues(excluded); err != nil { - return false, err - } - out.PermittedDNSDomainsCritical = e.Critical - - return unhandled, nil -} - -func parseCertificate(in *certificate) (*Certificate, error) { - out := new(Certificate) - out.Raw = in.Raw - out.RawTBSCertificate = in.TBSCertificate.Raw - out.RawSubjectPublicKeyInfo = in.TBSCertificate.PublicKey.Raw - out.RawSubject = in.TBSCertificate.Subject.FullBytes - out.RawIssuer = in.TBSCertificate.Issuer.FullBytes - - out.Signature = in.SignatureValue.RightAlign() - out.SignatureAlgorithm = - getSignatureAlgorithmFromAI(in.TBSCertificate.SignatureAlgorithm) - - out.PublicKeyAlgorithm = - getPublicKeyAlgorithmFromOID(in.TBSCertificate.PublicKey.Algorithm.Algorithm) - var err error - out.PublicKey, err = parsePublicKey(out.PublicKeyAlgorithm, &in.TBSCertificate.PublicKey) - if err != nil { - return nil, err - } - - out.Version = in.TBSCertificate.Version + 1 - out.SerialNumber = in.TBSCertificate.SerialNumber - - var issuer, subject pkix.RDNSequence - if rest, err := asn1.Unmarshal(in.TBSCertificate.Subject.FullBytes, &subject); err != nil { - return nil, err - } else if len(rest) != 0 { - return nil, errors.New("x509: trailing data after X.509 subject") - } - if rest, err := asn1.Unmarshal(in.TBSCertificate.Issuer.FullBytes, &issuer); err != nil { - return nil, err - } else if len(rest) != 0 { - return nil, errors.New("x509: trailing data after X.509 issuer") - } - - out.Issuer.FillFromRDNSequence(&issuer) - out.Subject.FillFromRDNSequence(&subject) - - out.NotBefore = in.TBSCertificate.Validity.NotBefore - out.NotAfter = in.TBSCertificate.Validity.NotAfter - - for _, e := range in.TBSCertificate.Extensions { - out.Extensions = append(out.Extensions, e) - unhandled := false - - if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 { - switch e.Id[3] { - case 15: - out.KeyUsage, err = parseKeyUsageExtension(e.Value) - if err != nil { - return nil, err - } - case 19: - out.IsCA, out.MaxPathLen, err = parseBasicConstraintsExtension(e.Value) - if err != nil { - return nil, err - } - out.BasicConstraintsValid = true - out.MaxPathLenZero = out.MaxPathLen == 0 - case 17: - out.DNSNames, out.EmailAddresses, out.IPAddresses, out.URIs, err = parseSANExtension(e.Value) - if err != nil { - return nil, err - } - - if len(out.DNSNames) == 0 && len(out.EmailAddresses) == 0 && len(out.IPAddresses) == 0 && len(out.URIs) == 0 { - // If we didn't parse anything then we do the critical check, below. - unhandled = true - } - - case 30: - unhandled, err = parseNameConstraintsExtension(out, e) - if err != nil { - return nil, err - } - - case 31: - // RFC 5280, 4.2.1.13 - - // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint - // - // DistributionPoint ::= SEQUENCE { - // distributionPoint [0] DistributionPointName OPTIONAL, - // reasons [1] ReasonFlags OPTIONAL, - // cRLIssuer [2] GeneralNames OPTIONAL } - // - // DistributionPointName ::= CHOICE { - // fullName [0] GeneralNames, - // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } - - var cdp []distributionPoint - if rest, err := asn1.Unmarshal(e.Value, &cdp); err != nil { - return nil, err - } else if len(rest) != 0 { - return nil, errors.New("x509: trailing data after X.509 CRL distribution point") - } - - for _, dp := range cdp { - // Per RFC 5280, 4.2.1.13, one of distributionPoint or cRLIssuer may be empty. - if len(dp.DistributionPoint.FullName) == 0 { - continue - } - - for _, fullName := range dp.DistributionPoint.FullName { - if fullName.Tag == 6 { - out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(fullName.Bytes)) - } - } - } - - case 35: - // RFC 5280, 4.2.1.1 - var a authKeyId - if rest, err := asn1.Unmarshal(e.Value, &a); err != nil { - return nil, err - } else if len(rest) != 0 { - return nil, errors.New("x509: trailing data after X.509 authority key-id") - } - out.AuthorityKeyId = a.Id - - case 37: - out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(e.Value) - if err != nil { - return nil, err - } - case 14: - out.SubjectKeyId, err = parseSubjectKeyIdExtension(e.Value) - if err != nil { - return nil, err - } - case 32: - out.PolicyIdentifiers, err = parseCertificatePoliciesExtension(e.Value) - if err != nil { - return nil, err - } - default: - // Unknown extensions are recorded if critical. - unhandled = true - } - } else if e.Id.Equal(oidExtensionAuthorityInfoAccess) { - // RFC 5280 4.2.2.1: Authority Information Access - var aia []authorityInfoAccess - if rest, err := asn1.Unmarshal(e.Value, &aia); err != nil { - return nil, err - } else if len(rest) != 0 { - return nil, errors.New("x509: trailing data after X.509 authority information") - } - - for _, v := range aia { - // GeneralName: uniformResourceIdentifier [6] IA5String - if v.Location.Tag != 6 { - continue - } - if v.Method.Equal(oidAuthorityInfoAccessOcsp) { - out.OCSPServer = append(out.OCSPServer, string(v.Location.Bytes)) - } else if v.Method.Equal(oidAuthorityInfoAccessIssuers) { - out.IssuingCertificateURL = append(out.IssuingCertificateURL, string(v.Location.Bytes)) - } - } - } else { - // Unknown extensions are recorded if critical. - unhandled = true - } - - if e.Critical && unhandled { - out.UnhandledCriticalExtensions = append(out.UnhandledCriticalExtensions, e.Id) - } - } - - return out, nil -} - -// parseKeyUsageExtension parses id-ce-keyUsage (2.5.29.15) from RFC 5280 -// Section 4.2.1.3 -func parseKeyUsageExtension(ext []byte) (KeyUsage, error) { - var usageBits asn1.BitString - if rest, err := asn1.Unmarshal(ext, &usageBits); err != nil { - return 0, err - } else if len(rest) != 0 { - return 0, errors.New("x509: trailing data after X.509 KeyUsage") - } - - var usage int - for i := 0; i < 9; i++ { - if usageBits.At(i) != 0 { - usage |= 1 << uint(i) - } - } - return KeyUsage(usage), nil -} - -// parseBasicConstraintsExtension parses id-ce-basicConstraints (2.5.29.19) -// from RFC 5280 Section 4.2.1.9 -func parseBasicConstraintsExtension(ext []byte) (isCA bool, maxPathLen int, err error) { - var constraints basicConstraints - if rest, err := asn1.Unmarshal(ext, &constraints); err != nil { - return false, 0, err - } else if len(rest) != 0 { - return false, 0, errors.New("x509: trailing data after X.509 BasicConstraints") - } - - // TODO: map out.MaxPathLen to 0 if it has the -1 default value? (Issue 19285) - return constraints.IsCA, constraints.MaxPathLen, nil -} - -// parseExtKeyUsageExtension parses id-ce-extKeyUsage (2.5.29.37) from -// RFC 5280 Section 4.2.1.12 -func parseExtKeyUsageExtension(ext []byte) ([]ExtKeyUsage, []asn1.ObjectIdentifier, error) { - var keyUsage []asn1.ObjectIdentifier - if rest, err := asn1.Unmarshal(ext, &keyUsage); err != nil { - return nil, nil, err - } else if len(rest) != 0 { - return nil, nil, errors.New("x509: trailing data after X.509 ExtendedKeyUsage") - } - - var extKeyUsages []ExtKeyUsage - var unknownUsages []asn1.ObjectIdentifier - for _, u := range keyUsage { - if extKeyUsage, ok := extKeyUsageFromOID(u); ok { - extKeyUsages = append(extKeyUsages, extKeyUsage) - } else { - unknownUsages = append(unknownUsages, u) - } - } - return extKeyUsages, unknownUsages, nil -} - -// parseSubjectKeyIdExtension parses id-ce-subjectKeyIdentifier (2.5.29.14) -// from RFC 5280 Section 4.2.1.2 -func parseSubjectKeyIdExtension(ext []byte) ([]byte, error) { - var keyid []byte - if rest, err := asn1.Unmarshal(ext, &keyid); err != nil { - return nil, err - } else if len(rest) != 0 { - return nil, errors.New("x509: trailing data after X.509 key-id") - } - return keyid, nil -} - -func parseCertificatePoliciesExtension(ext []byte) ([]asn1.ObjectIdentifier, error) { - var policies []policyInformation - if rest, err := asn1.Unmarshal(ext, &policies); err != nil { - return nil, err - } else if len(rest) != 0 { - return nil, errors.New("x509: trailing data after X.509 certificate policies") - } - oids := make([]asn1.ObjectIdentifier, len(policies)) - for i, policy := range policies { - oids[i] = policy.Policy - } - return oids, nil -} - -// ParseCertificate parses a single certificate from the given ASN.1 DER data. -func ParseCertificate(asn1Data []byte) (*Certificate, error) { - var cert certificate - rest, err := asn1.Unmarshal(asn1Data, &cert) - if err != nil { - return nil, err - } - if len(rest) > 0 { - return nil, asn1.SyntaxError{Msg: "trailing data"} - } - - return parseCertificate(&cert) -} - -// ParseCertificates parses one or more certificates from the given ASN.1 DER -// data. The certificates must be concatenated with no intermediate padding. -func ParseCertificates(asn1Data []byte) ([]*Certificate, error) { - var v []*certificate - - for len(asn1Data) > 0 { - cert := new(certificate) - var err error - asn1Data, err = asn1.Unmarshal(asn1Data, cert) - if err != nil { - return nil, err - } - v = append(v, cert) - } - - ret := make([]*Certificate, len(v)) - for i, ci := range v { - cert, err := parseCertificate(ci) - if err != nil { - return nil, err - } - ret[i] = cert - } - - return ret, nil -} - func reverseBitsInAByte(in byte) byte { b1 := in>>4 | in<<4 b2 := b1>>2&0x33 | b1<<2&0xcc @@ -2085,8 +1413,8 @@ func signingParamsForPublicKey(pub interface{}, requestedSigAlgo SignatureAlgori // just an empty SEQUENCE. var emptyASN1Subject = []byte{0x30, 0} -// CreateCertificate creates a new X.509v3 certificate based on a template. -// The following members of template are used: +// CreateCertificate creates a new X.509 v3 certificate based on a template. +// The following members of template are currently used: // // - AuthorityKeyId // - BasicConstraintsValid @@ -2123,7 +1451,7 @@ var emptyASN1Subject = []byte{0x30, 0} // // The certificate is signed by parent. If parent is equal to template then the // certificate is self-signed. The parameter pub is the public key of the -// signee and priv is the private key of the signer. +// certificate to be generated and priv is the private key of the signer. // // The returned slice is the certificate in DER encoding. // @@ -2137,7 +1465,7 @@ var emptyASN1Subject = []byte{0x30, 0} // // If SubjectKeyId from template is empty and the template is a CA, SubjectKeyId // will be generated from the hash of the public key. -func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv interface{}) (cert []byte, err error) { +func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv interface{}) ([]byte, error) { key, ok := priv.(crypto.Signer) if !ok { return nil, errors.New("x509: certificate private key does not implement crypto.Signer") @@ -2163,12 +1491,12 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv asn1Issuer, err := subjectBytes(parent) if err != nil { - return + return nil, err } asn1Subject, err := subjectBytes(template) if err != nil { - return + return nil, err } authorityKeyId := template.AuthorityKeyId @@ -2186,9 +1514,19 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv subjectKeyId = h[:] } + // Check that the signer's public key matches the private key, if available. + type privateKey interface { + Equal(crypto.PublicKey) bool + } + if privPub, ok := key.Public().(privateKey); !ok { + return nil, errors.New("x509: internal error: supported public key does not implement Equal") + } else if parent.PublicKey != nil && !privPub.Equal(parent.PublicKey) { + return nil, errors.New("x509: provided PrivateKey doesn't match parent's PublicKey") + } + extensions, err := buildCertExtensions(template, bytes.Equal(asn1Subject, emptyASN1Subject), authorityKeyId, subjectKeyId) if err != nil { - return + return nil, err } encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes} @@ -2205,7 +1543,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv tbsCertContents, err := asn1.Marshal(c) if err != nil { - return + return nil, err } c.Raw = tbsCertContents @@ -2227,7 +1565,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv var signature []byte signature, err = key.Sign(rand, signed, signerOpts) if err != nil { - return + return nil, err } signedCert, err := asn1.Marshal(certificate{ diff --git a/libgo/go/crypto/x509/x509_test.go b/libgo/go/crypto/x509/x509_test.go index 51dda16..a4053ab 100644 --- a/libgo/go/crypto/x509/x509_test.go +++ b/libgo/go/crypto/x509/x509_test.go @@ -2995,3 +2995,224 @@ func TestCertificateRequestRoundtripFields(t *testing.T) { t.Fatalf("Unexpected URIs: got %v, want %v", out.URIs, in.URIs) } } + +func BenchmarkParseCertificate(b *testing.B) { + cases := []struct { + name string + pem string + }{ + { + name: "ecdsa leaf", + pem: `-----BEGIN CERTIFICATE----- +MIIINjCCBx6gAwIBAgIQHdQ6oBMoe/MJAAAAAEHzmTANBgkqhkiG9w0BAQsFADBG +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzETMBEGA1UEAxMKR1RTIENBIDFDMzAeFw0yMDEyMDgwOTExMzZaFw0yMTAzMDIw +OTExMzVaMBcxFTATBgNVBAMMDCouZ29vZ2xlLmNvbTBZMBMGByqGSM49AgEGCCqG +SM49AwEHA0IABEFYegyHh1AHRS1nar5+zYJgMACcsIQMtg0YMyK/59ml8ERIt/JF +kXM3XIvQuCJhghUawZrrAcAs8djZF1U9M4mjggYYMIIGFDAOBgNVHQ8BAf8EBAMC +B4AwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU +6SWWF36XBsmXJ6iV0EHPXUFoMbwwHwYDVR0jBBgwFoAUinR/r4XN7pXNPZzQ4kYU +83E1HScwagYIKwYBBQUHAQEEXjBcMCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5w +a2kuZ29vZy9ndHMxYzMwMQYIKwYBBQUHMAKGJWh0dHA6Ly9wa2kuZ29vZy9yZXBv +L2NlcnRzL2d0czFjMy5kZXIwggTCBgNVHREEggS5MIIEtYIMKi5nb29nbGUuY29t +gg0qLmFuZHJvaWQuY29tghYqLmFwcGVuZ2luZS5nb29nbGUuY29tggkqLmJkbi5k +ZXaCEiouY2xvdWQuZ29vZ2xlLmNvbYIYKi5jcm93ZHNvdXJjZS5nb29nbGUuY29t +ghgqLmRhdGFjb21wdXRlLmdvb2dsZS5jb22CBiouZy5jb4IOKi5nY3AuZ3Z0Mi5j +b22CESouZ2NwY2RuLmd2dDEuY29tggoqLmdncGh0LmNugg4qLmdrZWNuYXBwcy5j +boIWKi5nb29nbGUtYW5hbHl0aWNzLmNvbYILKi5nb29nbGUuY2GCCyouZ29vZ2xl +LmNsgg4qLmdvb2dsZS5jby5pboIOKi5nb29nbGUuY28uanCCDiouZ29vZ2xlLmNv +LnVrgg8qLmdvb2dsZS5jb20uYXKCDyouZ29vZ2xlLmNvbS5hdYIPKi5nb29nbGUu +Y29tLmJygg8qLmdvb2dsZS5jb20uY2+CDyouZ29vZ2xlLmNvbS5teIIPKi5nb29n +bGUuY29tLnRygg8qLmdvb2dsZS5jb20udm6CCyouZ29vZ2xlLmRlggsqLmdvb2ds +ZS5lc4ILKi5nb29nbGUuZnKCCyouZ29vZ2xlLmh1ggsqLmdvb2dsZS5pdIILKi5n +b29nbGUubmyCCyouZ29vZ2xlLnBsggsqLmdvb2dsZS5wdIISKi5nb29nbGVhZGFw +aXMuY29tgg8qLmdvb2dsZWFwaXMuY26CESouZ29vZ2xlY25hcHBzLmNughQqLmdv +b2dsZWNvbW1lcmNlLmNvbYIRKi5nb29nbGV2aWRlby5jb22CDCouZ3N0YXRpYy5j +boINKi5nc3RhdGljLmNvbYISKi5nc3RhdGljY25hcHBzLmNuggoqLmd2dDEuY29t +ggoqLmd2dDIuY29tghQqLm1ldHJpYy5nc3RhdGljLmNvbYIMKi51cmNoaW4uY29t +ghAqLnVybC5nb29nbGUuY29tghMqLndlYXIuZ2tlY25hcHBzLmNughYqLnlvdXR1 +YmUtbm9jb29raWUuY29tgg0qLnlvdXR1YmUuY29tghYqLnlvdXR1YmVlZHVjYXRp +b24uY29tghEqLnlvdXR1YmVraWRzLmNvbYIHKi55dC5iZYILKi55dGltZy5jb22C +GmFuZHJvaWQuY2xpZW50cy5nb29nbGUuY29tggthbmRyb2lkLmNvbYIbZGV2ZWxv +cGVyLmFuZHJvaWQuZ29vZ2xlLmNughxkZXZlbG9wZXJzLmFuZHJvaWQuZ29vZ2xl +LmNuggRnLmNvgghnZ3BodC5jboIMZ2tlY25hcHBzLmNuggZnb28uZ2yCFGdvb2ds +ZS1hbmFseXRpY3MuY29tggpnb29nbGUuY29tgg9nb29nbGVjbmFwcHMuY26CEmdv +b2dsZWNvbW1lcmNlLmNvbYIYc291cmNlLmFuZHJvaWQuZ29vZ2xlLmNuggp1cmNo +aW4uY29tggp3d3cuZ29vLmdsggh5b3V0dS5iZYILeW91dHViZS5jb22CFHlvdXR1 +YmVlZHVjYXRpb24uY29tgg95b3V0dWJla2lkcy5jb22CBXl0LmJlMCEGA1UdIAQa +MBgwCAYGZ4EMAQIBMAwGCisGAQQB1nkCBQMwNQYDVR0fBC4wLDAqoCigJoYkaHR0 +cDovL2NybC5wa2kuZ29vZy9ndHNyMS9ndHMxYzMuY3JsMBMGCisGAQQB1nkCBAMB +Af8EAgUAMA0GCSqGSIb3DQEBCwUAA4IBAQAlDQm5zY7JcPxcJ9ulfTGsWV/m6Pro +gLYmAlBUPGKy313aetT4Zjz44ZseVtUOKsXVHh4avPA9O+ta1FgkASlbkgJ05ivb +j/+MMqkrLemdMv9Svvx3CNaAq2jJ2E+8GdrA1RzMkiNthJCiRafaPnXnN6hOHGNr +GtqYfMHsvrRHW8J2IPHW0/MUHmJ/NDu/vNchxke2OEfCPLtseo3hJt8l8HbH+yE8 +DFrt8YVRi1CLomEyuPJDF4og3O3ZsoXuxcPd9UPxULOCxycdolRw8Iv/Xgr082j3 +svXC3HUd3apM2Yy3xJAlk/mUkzVXfdJZ+Zy1huNsUoJ+gM8rmpyGhYyx +-----END CERTIFICATE-----`, + }, + { + name: "rsa leaf", + pem: `-----BEGIN CERTIFICATE----- +MIIJXjCCCEagAwIBAgIRAPYaTUsjP4iRBQAAAACHSSgwDQYJKoZIhvcNAQELBQAw +QjELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFUdvb2dsZSBUcnVzdCBTZXJ2aWNlczET +MBEGA1UEAxMKR1RTIENBIDFPMTAeFw0yMTAxMjYwODQ2MzRaFw0yMTA0MjAwODQ2 +MzNaMGYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH +Ew1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgTExDMRUwEwYDVQQDDAwq +Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC76xx0 +UdZ36/41rZNPfQ/yQ05vsBLUO0d+3uMOhvDlpst+XvIsG6L+vLDgf3RiQRFlei0h +KqqLOtWLDc/y0+OmaaC+8ft1zljBYdvQlAYoZrT79Cc5pAIDq7G1OZ7cC4ahDno/ +n46FHjT/UTUAMYa8cKWBaMPneMIsKvn8nMdZzHkfO2nUd6OEecn90XweMvNmx8De +6h5AlIgG3m66hkD/UCSdxn7yJHBQVdHgkfTqzv3sz2YyBQGNi288F1bn541f6khE +fYti1MvXRtkky7yLCQNUG6PtvuSU4cKaNvRklHigf5i1nVdGEuH61gAElZIklSia +OVK46UyU4DGtbdWNAgMBAAGjggYpMIIGJTAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU8zCvllLd3jhB +k//+Wdjo40Q+T3gwHwYDVR0jBBgwFoAUmNH4bhDrz5vsYJ8YkBug630J/SswaAYI +KwYBBQUHAQEEXDBaMCsGCCsGAQUFBzABhh9odHRwOi8vb2NzcC5wa2kuZ29vZy9n +dHMxbzFjb3JlMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2cvZ3NyMi9HVFMx +TzEuY3J0MIIE1wYDVR0RBIIEzjCCBMqCDCouZ29vZ2xlLmNvbYINKi5hbmRyb2lk +LmNvbYIWKi5hcHBlbmdpbmUuZ29vZ2xlLmNvbYIJKi5iZG4uZGV2ghIqLmNsb3Vk +Lmdvb2dsZS5jb22CGCouY3Jvd2Rzb3VyY2UuZ29vZ2xlLmNvbYIYKi5kYXRhY29t +cHV0ZS5nb29nbGUuY29tghMqLmZsYXNoLmFuZHJvaWQuY29tggYqLmcuY2+CDiou +Z2NwLmd2dDIuY29tghEqLmdjcGNkbi5ndnQxLmNvbYIKKi5nZ3BodC5jboIOKi5n +a2VjbmFwcHMuY26CFiouZ29vZ2xlLWFuYWx5dGljcy5jb22CCyouZ29vZ2xlLmNh +ggsqLmdvb2dsZS5jbIIOKi5nb29nbGUuY28uaW6CDiouZ29vZ2xlLmNvLmpwgg4q +Lmdvb2dsZS5jby51a4IPKi5nb29nbGUuY29tLmFygg8qLmdvb2dsZS5jb20uYXWC +DyouZ29vZ2xlLmNvbS5icoIPKi5nb29nbGUuY29tLmNvgg8qLmdvb2dsZS5jb20u +bXiCDyouZ29vZ2xlLmNvbS50coIPKi5nb29nbGUuY29tLnZuggsqLmdvb2dsZS5k +ZYILKi5nb29nbGUuZXOCCyouZ29vZ2xlLmZyggsqLmdvb2dsZS5odYILKi5nb29n +bGUuaXSCCyouZ29vZ2xlLm5sggsqLmdvb2dsZS5wbIILKi5nb29nbGUucHSCEiou +Z29vZ2xlYWRhcGlzLmNvbYIPKi5nb29nbGVhcGlzLmNughEqLmdvb2dsZWNuYXBw +cy5jboIUKi5nb29nbGVjb21tZXJjZS5jb22CESouZ29vZ2xldmlkZW8uY29tggwq +LmdzdGF0aWMuY26CDSouZ3N0YXRpYy5jb22CEiouZ3N0YXRpY2NuYXBwcy5jboIK +Ki5ndnQxLmNvbYIKKi5ndnQyLmNvbYIUKi5tZXRyaWMuZ3N0YXRpYy5jb22CDCou +dXJjaGluLmNvbYIQKi51cmwuZ29vZ2xlLmNvbYITKi53ZWFyLmdrZWNuYXBwcy5j +boIWKi55b3V0dWJlLW5vY29va2llLmNvbYINKi55b3V0dWJlLmNvbYIWKi55b3V0 +dWJlZWR1Y2F0aW9uLmNvbYIRKi55b3V0dWJla2lkcy5jb22CByoueXQuYmWCCyou +eXRpbWcuY29tghphbmRyb2lkLmNsaWVudHMuZ29vZ2xlLmNvbYILYW5kcm9pZC5j +b22CG2RldmVsb3Blci5hbmRyb2lkLmdvb2dsZS5jboIcZGV2ZWxvcGVycy5hbmRy +b2lkLmdvb2dsZS5jboIEZy5jb4IIZ2dwaHQuY26CDGdrZWNuYXBwcy5jboIGZ29v +LmdsghRnb29nbGUtYW5hbHl0aWNzLmNvbYIKZ29vZ2xlLmNvbYIPZ29vZ2xlY25h +cHBzLmNughJnb29nbGVjb21tZXJjZS5jb22CGHNvdXJjZS5hbmRyb2lkLmdvb2ds +ZS5jboIKdXJjaGluLmNvbYIKd3d3Lmdvby5nbIIIeW91dHUuYmWCC3lvdXR1YmUu +Y29tghR5b3V0dWJlZWR1Y2F0aW9uLmNvbYIPeW91dHViZWtpZHMuY29tggV5dC5i +ZTAhBgNVHSAEGjAYMAgGBmeBDAECAjAMBgorBgEEAdZ5AgUDMDMGA1UdHwQsMCow +KKAmoCSGImh0dHA6Ly9jcmwucGtpLmdvb2cvR1RTMU8xY29yZS5jcmwwEwYKKwYB +BAHWeQIEAwEB/wQCBQAwDQYJKoZIhvcNAQELBQADggEBAHh9/ozYUGRd+W5akWlM +4WvX808TK2oUISnagbxCCFZ2trpg2oi03CJf4o4o3Je5Qzzz10s22oQY6gPHAR0B +QHzrpqAveQw9D5vd8xjgtQ/SAujPzPKNQee5511rS7/EKW9I83ccd5XhhoEyx8A1 +/65RTS+2hKpJKTMkr0yHBPJV7kUW+n/KIef5YaSOA9VYK7hyH0niDpvm9EmoqvWS +U5xAFAe/Xrrq3sxTuDJPQA8alk6h/ql5Klkw6dL53csiPka/MevDqdifWkzuT/6n +YK/ePeJzPD17FA9V+N1rcuF3Wk29AZvCOSasdIkIuE82vGr3dfNrsrn9E9lWIbCr +Qc4= +-----END CERTIFICATE-----`, + }, + } + for _, c := range cases { + b.Run(c.name, func(b *testing.B) { + pemBlock, _ := pem.Decode([]byte(c.pem)) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := ParseCertificate(pemBlock.Bytes) + if err != nil { + b.Fatal(err) + } + } + }) + } +} + +func TestParseCertificateRawEquals(t *testing.T) { + p, _ := pem.Decode([]byte(pemCertificate)) + cert, err := ParseCertificate(p.Bytes) + if err != nil { + t.Fatalf("failed to parse certificate: %s", err) + } + if !bytes.Equal(p.Bytes, cert.Raw) { + t.Fatalf("unexpected Certificate.Raw\ngot: %x\nwant: %x\n", cert.Raw, p.Bytes) + } + fmt.Printf("in: %x\nout: %x\n", p.Bytes, cert.Raw) +} + +// mismatchingSigAlgIDPEM contains a certificate where the Certificate +// signatureAlgorithm and the TBSCertificate signature contain +// mismatching OIDs +const mismatchingSigAlgIDPEM = `-----BEGIN CERTIFICATE----- +MIIBBzCBrqADAgECAgEAMAoGCCqGSM49BAMCMAAwIhgPMDAwMTAxMDEwMDAwMDBa +GA8wMDAxMDEwMTAwMDAwMFowADBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOqV +EDuVXxwZgIU3+dOwv1SsMu0xuV48hf7xmK8n7sAMYgllB+96DnPqBeboJj4snYnx +0AcE0PDVQ1l4Z3YXsQWjFTATMBEGA1UdEQEB/wQHMAWCA2FzZDAKBggqhkjOPQQD +AwNIADBFAiBi1jz/T2HT5nAfrD7zsgR+68qh7Erc6Q4qlxYBOgKG4QIhAOtjIn+Q +tA+bq+55P3ntxTOVRq0nv1mwnkjwt9cQR9Fn +-----END CERTIFICATE-----` + +// mismatchingSigAlgParamPEM contains a certificate where the Certificate +// signatureAlgorithm and the TBSCertificate signature contain +// mismatching parameters +const mismatchingSigAlgParamPEM = `-----BEGIN CERTIFICATE----- +MIIBCTCBrqADAgECAgEAMAoGCCqGSM49BAMCMAAwIhgPMDAwMTAxMDEwMDAwMDBa +GA8wMDAxMDEwMTAwMDAwMFowADBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOqV +EDuVXxwZgIU3+dOwv1SsMu0xuV48hf7xmK8n7sAMYgllB+96DnPqBeboJj4snYnx +0AcE0PDVQ1l4Z3YXsQWjFTATMBEGA1UdEQEB/wQHMAWCA2FzZDAMBggqhkjOPQQD +AgUAA0gAMEUCIGLWPP9PYdPmcB+sPvOyBH7ryqHsStzpDiqXFgE6AobhAiEA62Mi +f5C0D5ur7nk/ee3FM5VGrSe/WbCeSPC31xBH0Wc= +-----END CERTIFICATE-----` + +func TestSigAlgMismatch(t *testing.T) { + for _, certPEM := range []string{mismatchingSigAlgIDPEM, mismatchingSigAlgParamPEM} { + b, _ := pem.Decode([]byte(certPEM)) + if b == nil { + t.Fatalf("couldn't decode test certificate") + } + _, err := ParseCertificate(b.Bytes) + if err == nil { + t.Fatalf("expected ParseCertificate to fail") + } + expected := "x509: inner and outer signature algorithm identifiers don't match" + if err.Error() != expected { + t.Errorf("unexpected error from ParseCertificate: got %q, want %q", err.Error(), expected) + } + } +} + +const optionalAuthKeyIDPEM = `-----BEGIN CERTIFICATE----- +MIIFEjCCBHugAwIBAgICAQwwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh +bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu +Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g +QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe +BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MzkxNloX +DTI0MDYyOTE3MzkxNlowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVs +ZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAy +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0A +MIIBCAKCAQEAtzLI/ulxpgSFrQwRZN/OTe/IAxiHP6Gr+zymn/DDodrU2G4rU5D7 +JKQ+hPCe6F/s5SdE9SimP3ve4CrwyK9TL57KBQGTHo9mHDmnTfpatnMEJWbrd3/n +WcZKmSUUVOsmx/N/GdUwcI+vsEYq/63rKe3Xn6oEh6PU+YmlNF/bQ5GCNtlmPLG4 +uYL9nDo+EMg77wZlZnqbGRg9/3FRPDAuX749d3OyXQZswyNWmiuFJpIcpwKz5D8N +rwh5grg2Peqc0zWzvGnK9cyd6P1kjReAM25eSl2ZyR6HtJ0awNVuEzUjXt+bXz3v +1vd2wuo+u3gNHEJnawTY+Nbab4vyRKABqwIBA6OCAfMwggHvMB0GA1UdDgQWBBS/ +X7fRzt0fhvRbVazc1xDCDqmI5zCB0gYDVR0jBIHKMIHHoYHBpIG+MIG7MSQwIgYD +VQQHExtWYWxpQ2VydCBWYWxpZGF0aW9uIE5ldHdvcmsxFzAVBgNVBAoTDlZhbGlD +ZXJ0LCBJbmMuMTUwMwYDVQQLEyxWYWxpQ2VydCBDbGFzcyAyIFBvbGljeSBWYWxp +ZGF0aW9uIEF1dGhvcml0eTEhMB8GA1UEAxMYaHR0cDovL3d3dy52YWxpY2VydC5j +b20vMSAwHgYJKoZIhvcNAQkBFhFpbmZvQHZhbGljZXJ0LmNvbYIBATAPBgNVHRMB +Af8EBTADAQH/MDkGCCsGAQUFBwEBBC0wKzApBggrBgEFBQcwAYYdaHR0cDovL29j +c3Auc3RhcmZpZWxkdGVjaC5jb20wSgYDVR0fBEMwQTA/oD2gO4Y5aHR0cDovL2Nl +cnRpZmljYXRlcy5zdGFyZmllbGR0ZWNoLmNvbS9yZXBvc2l0b3J5L3Jvb3QuY3Js +MFEGA1UdIARKMEgwRgYEVR0gADA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY2VydGlm +aWNhdGVzLnN0YXJmaWVsZHRlY2guY29tL3JlcG9zaXRvcnkwDgYDVR0PAQH/BAQD +AgEGMA0GCSqGSIb3DQEBBQUAA4GBAKVi8afCXSWlcD284ipxs33kDTcdVWptobCr +mADkhWBKIMuh8D1195TaQ39oXCUIuNJ9MxB73HZn8bjhU3zhxoNbKXuNSm8uf0So +GkVrMgfHeMpkksK0hAzc3S1fTbvdiuo43NlmouxBulVtWmQ9twPMHOKRUJ7jCUSV +FxdzPcwl +-----END CERTIFICATE-----` + +func TestAuthKeyIdOptional(t *testing.T) { + b, _ := pem.Decode([]byte(optionalAuthKeyIDPEM)) + if b == nil { + t.Fatalf("couldn't decode test certificate") + } + _, err := ParseCertificate(b.Bytes) + if err != nil { + t.Fatalf("ParseCertificate to failed to parse certificate with optional authority key identifier fields: %s", err) + } +} diff --git a/libgo/go/crypto/x509/x509_test_import.go b/libgo/go/crypto/x509/x509_test_import.go index b778df2..ef3ee80 100644 --- a/libgo/go/crypto/x509/x509_test_import.go +++ b/libgo/go/crypto/x509/x509_test_import.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // This file is run by the x509 tests to ensure that a program with minimal diff --git a/libgo/go/database/sql/driver/driver.go b/libgo/go/database/sql/driver/driver.go index 5bbcf20..f093961 100644 --- a/libgo/go/database/sql/driver/driver.go +++ b/libgo/go/database/sql/driver/driver.go @@ -115,6 +115,9 @@ type DriverContext interface { // DriverContext's OpenConnector method, to allow drivers // access to context and to avoid repeated parsing of driver // configuration. +// +// If a Connector implements io.Closer, the sql package's DB.Close +// method will call Close and return error (if any). type Connector interface { // Connect returns a connection to the database. // Connect may return a cached connection (one previously diff --git a/libgo/go/database/sql/fakedb_test.go b/libgo/go/database/sql/fakedb_test.go index 7605a2a..4b68f1c 100644 --- a/libgo/go/database/sql/fakedb_test.go +++ b/libgo/go/database/sql/fakedb_test.go @@ -56,6 +56,7 @@ type fakeConnector struct { name string waiter func(context.Context) + closed bool } func (c *fakeConnector) Connect(context.Context) (driver.Conn, error) { @@ -68,6 +69,14 @@ func (c *fakeConnector) Driver() driver.Driver { return fdriver } +func (c *fakeConnector) Close() error { + if c.closed { + return errors.New("fakedb: connector is closed") + } + c.closed = true + return nil +} + type fakeDriverCtx struct { fakeDriver } @@ -906,7 +915,7 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) ( parentMem: s.c, posRow: -1, rows: [][]*row{ - []*row{ + { { cols: []interface{}{ txStatus, @@ -915,12 +924,12 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) ( }, }, cols: [][]string{ - []string{ + { "tx_status", }, }, colType: [][]string{ - []string{ + { "string", }, }, @@ -1177,9 +1186,11 @@ func converterForType(typ string) driver.ValueConverter { return driver.Bool case "nullbool": return driver.Null{Converter: driver.Bool} + case "byte", "int16": + return driver.NotNull{Converter: driver.DefaultParameterConverter} case "int32": return driver.Int32 - case "nullint32": + case "nullbyte", "nullint32", "nullint16": return driver.Null{Converter: driver.DefaultParameterConverter} case "string": return driver.NotNull{Converter: fakeDriverString{}} @@ -1213,6 +1224,10 @@ func colTypeToReflectType(typ string) reflect.Type { return reflect.TypeOf(false) case "nullbool": return reflect.TypeOf(NullBool{}) + case "int16": + return reflect.TypeOf(int16(0)) + case "nullint16": + return reflect.TypeOf(NullInt16{}) case "int32": return reflect.TypeOf(int32(0)) case "nullint32": diff --git a/libgo/go/database/sql/sql.go b/libgo/go/database/sql/sql.go index 726aadb..68fb392 100644 --- a/libgo/go/database/sql/sql.go +++ b/libgo/go/database/sql/sql.go @@ -260,6 +260,60 @@ func (n NullInt32) Value() (driver.Value, error) { return int64(n.Int32), nil } +// NullInt16 represents an int16 that may be null. +// NullInt16 implements the Scanner interface so +// it can be used as a scan destination, similar to NullString. +type NullInt16 struct { + Int16 int16 + Valid bool // Valid is true if Int16 is not NULL +} + +// Scan implements the Scanner interface. +func (n *NullInt16) Scan(value interface{}) error { + if value == nil { + n.Int16, n.Valid = 0, false + return nil + } + err := convertAssign(&n.Int16, value) + n.Valid = err == nil + return err +} + +// Value implements the driver Valuer interface. +func (n NullInt16) Value() (driver.Value, error) { + if !n.Valid { + return nil, nil + } + return int64(n.Int16), nil +} + +// NullByte represents a byte that may be null. +// NullByte implements the Scanner interface so +// it can be used as a scan destination, similar to NullString. +type NullByte struct { + Byte byte + Valid bool // Valid is true if Byte is not NULL +} + +// Scan implements the Scanner interface. +func (n *NullByte) Scan(value interface{}) error { + if value == nil { + n.Byte, n.Valid = 0, false + return nil + } + err := convertAssign(&n.Byte, value) + n.Valid = err == nil + return err +} + +// Value implements the driver Valuer interface. +func (n NullByte) Value() (driver.Value, error) { + if !n.Valid { + return nil, nil + } + return int64(n.Byte), nil +} + // NullFloat64 represents a float64 that may be null. // NullFloat64 implements the Scanner interface so // it can be used as a scan destination, similar to NullString. @@ -813,6 +867,9 @@ func (db *DB) PingContext(ctx context.Context) error { // Ping verifies a connection to the database is still alive, // establishing a connection if necessary. +// +// Ping uses context.Background internally; to specify the context, use +// PingContext. func (db *DB) Ping() error { return db.PingContext(context.Background()) } @@ -850,6 +907,12 @@ func (db *DB) Close() error { } } db.stop() + if c, ok := db.connector.(io.Closer); ok { + err1 := c.Close() + if err1 != nil { + err = err1 + } + } return err } @@ -1475,6 +1538,9 @@ func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) { // returned statement. // The caller must call the statement's Close method // when the statement is no longer needed. +// +// Prepare uses context.Background internally; to specify the context, use +// PrepareContext. func (db *DB) Prepare(query string) (*Stmt, error) { return db.PrepareContext(context.Background(), query) } @@ -1545,6 +1611,9 @@ func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{} // Exec executes a query without returning any rows. // The args are for any placeholder parameters in the query. +// +// Exec uses context.Background internally; to specify the context, use +// ExecContext. func (db *DB) Exec(query string, args ...interface{}) (Result, error) { return db.ExecContext(context.Background(), query, args...) } @@ -1615,6 +1684,9 @@ func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{ // Query executes a query that returns rows, typically a SELECT. // The args are for any placeholder parameters in the query. +// +// Query uses context.Background internally; to specify the context, use +// QueryContext. func (db *DB) Query(query string, args ...interface{}) (*Rows, error) { return db.QueryContext(context.Background(), query, args...) } @@ -1713,6 +1785,9 @@ func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interfa // If the query selects no rows, the *Row's Scan will return ErrNoRows. // Otherwise, the *Row's Scan scans the first selected row and discards // the rest. +// +// QueryRow uses context.Background internally; to specify the context, use +// QueryRowContext. func (db *DB) QueryRow(query string, args ...interface{}) *Row { return db.QueryRowContext(context.Background(), query, args...) } @@ -1744,6 +1819,9 @@ func (db *DB) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error) { // Begin starts a transaction. The default isolation level is dependent on // the driver. +// +// Begin uses context.Background internally; to specify the context, use +// BeginTx. func (db *DB) Begin() (*Tx, error) { return db.BeginTx(context.Background(), nil) } @@ -1771,7 +1849,7 @@ func (db *DB) beginDC(ctx context.Context, dc *driverConn, release func(error), return nil, err } - // Schedule the transaction to rollback when the context is cancelled. + // Schedule the transaction to rollback when the context is canceled. // The cancel function in Tx will be called after done is set to true. ctx, cancel := context.WithCancel(ctx) tx = &Tx{ @@ -2249,6 +2327,9 @@ func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error) { // be used once the transaction has been committed or rolled back. // // To use an existing prepared statement on this transaction, see Tx.Stmt. +// +// Prepare uses context.Background internally; to specify the context, use +// PrepareContext. func (tx *Tx) Prepare(query string) (*Stmt, error) { return tx.PrepareContext(context.Background(), query) } @@ -2352,6 +2433,9 @@ func (tx *Tx) StmtContext(ctx context.Context, stmt *Stmt) *Stmt { // // The returned statement operates within the transaction and will be closed // when the transaction has been committed or rolled back. +// +// Stmt uses context.Background internally; to specify the context, use +// StmtContext. func (tx *Tx) Stmt(stmt *Stmt) *Stmt { return tx.StmtContext(context.Background(), stmt) } @@ -2368,6 +2452,9 @@ func (tx *Tx) ExecContext(ctx context.Context, query string, args ...interface{} // Exec executes a query that doesn't return rows. // For example: an INSERT and UPDATE. +// +// Exec uses context.Background internally; to specify the context, use +// ExecContext. func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) { return tx.ExecContext(context.Background(), query, args...) } @@ -2383,6 +2470,9 @@ func (tx *Tx) QueryContext(ctx context.Context, query string, args ...interface{ } // Query executes a query that returns rows, typically a SELECT. +// +// Query uses context.Background internally; to specify the context, use +// QueryContext. func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) { return tx.QueryContext(context.Background(), query, args...) } @@ -2404,6 +2494,9 @@ func (tx *Tx) QueryRowContext(ctx context.Context, query string, args ...interfa // If the query selects no rows, the *Row's Scan will return ErrNoRows. // Otherwise, the *Row's Scan scans the first selected row and discards // the rest. +// +// QueryRow uses context.Background internally; to specify the context, use +// QueryRowContext. func (tx *Tx) QueryRow(query string, args ...interface{}) *Row { return tx.QueryRowContext(context.Background(), query, args...) } @@ -2510,6 +2603,9 @@ func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (Result, er // Exec executes a prepared statement with the given arguments and // returns a Result summarizing the effect of the statement. +// +// Exec uses context.Background internally; to specify the context, use +// ExecContext. func (s *Stmt) Exec(args ...interface{}) (Result, error) { return s.ExecContext(context.Background(), args...) } @@ -2681,6 +2777,9 @@ func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, er // Query executes a prepared query statement with the given arguments // and returns the query results as a *Rows. +// +// Query uses context.Background internally; to specify the context, use +// QueryContext. func (s *Stmt) Query(args ...interface{}) (*Rows, error) { return s.QueryContext(context.Background(), args...) } @@ -2720,6 +2819,9 @@ func (s *Stmt) QueryRowContext(ctx context.Context, args ...interface{}) *Row { // // var name string // err := nameByUseridStmt.QueryRow(id).Scan(&name) +// +// QueryRow uses context.Background internally; to specify the context, use +// QueryRowContext. func (s *Stmt) QueryRow(args ...interface{}) *Row { return s.QueryRowContext(context.Background(), args...) } diff --git a/libgo/go/database/sql/sql_test.go b/libgo/go/database/sql/sql_test.go index c968852..f771dee 100644 --- a/libgo/go/database/sql/sql_test.go +++ b/libgo/go/database/sql/sql_test.go @@ -431,25 +431,24 @@ func TestTxContextWait(t *testing.T) { db := newTestDB(t, "people") defer closeDB(t, db) - ctx, cancel := context.WithTimeout(context.Background(), 15*time.Millisecond) - defer cancel() + ctx, cancel := context.WithCancel(context.Background()) tx, err := db.BeginTx(ctx, nil) if err != nil { - // Guard against the context being canceled before BeginTx completes. - if err == context.DeadlineExceeded { - t.Skip("tx context canceled prior to first use") - } t.Fatal(err) } tx.keepConnOnRollback = false + go func() { + time.Sleep(15 * time.Millisecond) + cancel() + }() // This will trigger the *fakeConn.Prepare method which will take time // performing the query. The ctxDriverPrepare func will check the context // after this and close the rows and return an error. _, err = tx.QueryContext(ctx, "WAIT|1s|SELECT|people|age,name|") - if err != context.DeadlineExceeded { - t.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err) + if err != context.Canceled { + t.Fatalf("expected QueryContext to error with context canceled but returned %v", err) } waitForFree(t, db, 5*time.Second, 0) @@ -657,7 +656,7 @@ func TestPoolExhaustOnCancel(t *testing.T) { db.SetMaxOpenConns(max) // First saturate the connection pool. - // Then start new requests for a connection that is cancelled after it is requested. + // Then start new requests for a connection that is canceled after it is requested. state = 1 for i := 0; i < max; i++ { @@ -1820,6 +1819,30 @@ func TestNullInt32Param(t *testing.T) { nullTestRun(t, spec) } +func TestNullInt16Param(t *testing.T) { + spec := nullTestSpec{"nullint16", "int16", [6]nullTestRow{ + {NullInt16{31, true}, 1, NullInt16{31, true}}, + {NullInt16{-22, false}, 1, NullInt16{0, false}}, + {22, 1, NullInt16{22, true}}, + {NullInt16{33, true}, 1, NullInt16{33, true}}, + {NullInt16{222, false}, 1, NullInt16{0, false}}, + {0, NullInt16{31, false}, nil}, + }} + nullTestRun(t, spec) +} + +func TestNullByteParam(t *testing.T) { + spec := nullTestSpec{"nullbyte", "byte", [6]nullTestRow{ + {NullByte{31, true}, 1, NullByte{31, true}}, + {NullByte{0, false}, 1, NullByte{0, false}}, + {22, 1, NullByte{22, true}}, + {NullByte{33, true}, 1, NullByte{33, true}}, + {NullByte{222, false}, 1, NullByte{0, false}}, + {0, NullByte{31, false}, nil}, + }} + nullTestRun(t, spec) +} + func TestNullFloat64Param(t *testing.T) { spec := nullTestSpec{"nullfloat64", "float64", [6]nullTestRow{ {NullFloat64{31.2, true}, 1, NullFloat64{31.2, true}}, @@ -2785,7 +2808,7 @@ func TestTxCannotCommitAfterRollback(t *testing.T) { // 3. Check if 2.A has committed in Tx (pass) or outside of Tx (fail). sendQuery := make(chan struct{}) // The Tx status is returned through the row results, ensure - // that the rows results are not cancelled. + // that the rows results are not canceled. bypassRowsAwaitDone = true hookTxGrabConn = func() { cancel() @@ -2815,7 +2838,7 @@ func TestTxStmtDeadlock(t *testing.T) { db := newTestDB(t, "people") defer closeDB(t, db) - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond) + ctx, cancel := context.WithCancel(context.Background()) defer cancel() tx, err := db.BeginTx(ctx, nil) if err != nil { @@ -2826,6 +2849,7 @@ func TestTxStmtDeadlock(t *testing.T) { if err != nil { t.Fatal(err) } + cancel() // Run number of stmt queries to reproduce deadlock from context cancel for i := 0; i < 1e3; i++ { // Encounter any close related errors (e.g. ErrTxDone, stmt is closed) @@ -4060,9 +4084,18 @@ func TestOpenConnector(t *testing.T) { } defer db.Close() - if _, is := db.connector.(*fakeConnector); !is { + c, ok := db.connector.(*fakeConnector) + if !ok { t.Fatal("not using *fakeConnector") } + + if err := db.Close(); err != nil { + t.Fatal(err) + } + + if !c.closed { + t.Fatal("connector is not closed") + } } type ctxOnlyDriver struct { diff --git a/libgo/go/debug/dwarf/const.go b/libgo/go/debug/dwarf/const.go index c607091..c0a74b0 100644 --- a/libgo/go/debug/dwarf/const.go +++ b/libgo/go/debug/dwarf/const.go @@ -427,7 +427,7 @@ const ( lneSetDiscriminator = 4 ) -// Line table directory directory and file name entry formats. +// Line table directory and file name entry formats. // These are new in DWARF 5. const ( lnctPath = 0x01 diff --git a/libgo/go/debug/dwarf/entry.go b/libgo/go/debug/dwarf/entry.go index 3fc73b8..9f5ac57 100644 --- a/libgo/go/debug/dwarf/entry.go +++ b/libgo/go/debug/dwarf/entry.go @@ -317,7 +317,7 @@ const ( // the "mac" section. ClassMacPtr - // ClassMacPtr represents values that are an int64 offset into + // ClassRangeListPtr represents values that are an int64 offset into // the "rangelist" section. ClassRangeListPtr @@ -355,7 +355,7 @@ const ( // into the "loclists" section. ClassLocList - // ClassRngList represents values that are an int64 offset + // ClassRngList represents values that are a uint64 offset // from the base of the "rnglists" section. ClassRngList @@ -464,6 +464,35 @@ func (b *buf) entry(cu *Entry, atab abbrevTable, ubase Offset, vers int) *Entry return val } + resolveRnglistx := func(rnglistsBase, off uint64) uint64 { + is64, _ := b.format.dwarf64() + if is64 { + off *= 8 + } else { + off *= 4 + } + off += rnglistsBase + if uint64(int(off)) != off { + b.error("DW_FORM_rnglistx offset out of range") + } + + b1 := makeBuf(b.dwarf, b.format, "rnglists", 0, b.dwarf.rngLists) + b1.skip(int(off)) + if is64 { + off = b1.uint64() + } else { + off = uint64(b1.uint32()) + } + if b1.err != nil { + b.err = b1.err + return 0 + } + if uint64(int(off)) != off { + b.error("DW_FORM_rnglistx indirect offset out of range") + } + return rnglistsBase + off + } + for i := range e.Field { e.Field[i].Attr = a.field[i].attr e.Field[i].Class = a.field[i].class @@ -709,7 +738,21 @@ func (b *buf) entry(cu *Entry, atab abbrevTable, ubase Offset, vers int) *Entry // rnglist case formRnglistx: - val = b.uint() + off := b.uint() + + // We have to adjust by the rnglists_base of + // the compilation unit. This won't work if + // the program uses Reader.Seek to skip over + // the unit. Not much we can do about that. + var rnglistsBase int64 + if cu != nil { + rnglistsBase, _ = cu.Val(AttrRnglistsBase).(int64) + } else if a.tag == TagCompileUnit { + delay = append(delay, delayed{i, off, formRnglistx}) + break + } + + val = resolveRnglistx(uint64(rnglistsBase), off) } e.Field[i].Val = val @@ -734,6 +777,12 @@ func (b *buf) entry(cu *Entry, atab abbrevTable, ubase Offset, vers int) *Entry if b.err != nil { return nil } + case formRnglistx: + rnglistsBase, _ := e.Val(AttrRnglistsBase).(int64) + e.Field[del.idx].Val = resolveRnglistx(uint64(rnglistsBase), del.off) + if b.err != nil { + return nil + } } } @@ -993,8 +1042,15 @@ func (d *Data) Ranges(e *Entry) ([][2]uint64, error) { return d.dwarf5Ranges(u, cu, base, ranges, ret) case ClassRngList: - // TODO: support DW_FORM_rnglistx - return ret, nil + rnglist, ok := field.Val.(uint64) + if !ok { + return ret, nil + } + cu, base, err := d.baseAddressForEntry(e) + if err != nil { + return nil, err + } + return d.dwarf5Ranges(u, cu, base, int64(rnglist), ret) default: return ret, nil diff --git a/libgo/go/debug/dwarf/entry_test.go b/libgo/go/debug/dwarf/entry_test.go index b54f8b4..1f41d74 100644 --- a/libgo/go/debug/dwarf/entry_test.go +++ b/libgo/go/debug/dwarf/entry_test.go @@ -84,6 +84,19 @@ func TestRangesSection(t *testing.T) { testRanges(t, "testdata/ranges.elf", want) } +func TestRangesRnglistx(t *testing.T) { + want := []wantRange{ + {0x401000, [][2]uint64{{0x401020, 0x40102c}, {0x401000, 0x40101d}}}, + {0x40101c, [][2]uint64{{0x401020, 0x40102c}, {0x401000, 0x40101d}}}, + {0x40101d, nil}, + {0x40101f, nil}, + {0x401020, [][2]uint64{{0x401020, 0x40102c}, {0x401000, 0x40101d}}}, + {0x40102b, [][2]uint64{{0x401020, 0x40102c}, {0x401000, 0x40101d}}}, + {0x40102c, nil}, + } + testRanges(t, "testdata/rnglistx.elf", want) +} + func testRanges(t *testing.T, name string, want []wantRange) { d := elfData(t, name) r := d.Reader() diff --git a/libgo/go/debug/dwarf/line_test.go b/libgo/go/debug/dwarf/line_test.go index b13818e..9c6b6ff 100644 --- a/libgo/go/debug/dwarf/line_test.go +++ b/libgo/go/debug/dwarf/line_test.go @@ -117,6 +117,29 @@ func TestLineELFClang(t *testing.T) { testLineTable(t, want, files, elfData(t, "testdata/line-clang.elf")) } +func TestLineRnglists(t *testing.T) { + // Test a newer file, generated by clang. + file := &LineFile{Name: "/usr/local/google/home/iant/foo.c"} + want := []LineEntry{ + {Address: 0x401020, File: file, Line: 12, IsStmt: true}, + {Address: 0x401020, File: file, Line: 13, Column: 12, IsStmt: true, PrologueEnd: true}, + {Address: 0x401022, File: file, Line: 13, Column: 7}, + {Address: 0x401024, File: file, Line: 17, Column: 1, IsStmt: true}, + {Address: 0x401027, File: file, Line: 16, Column: 10, IsStmt: true}, + {Address: 0x40102c, EndSequence: true}, + {Address: 0x401000, File: file, Line: 2, IsStmt: true}, + {Address: 0x401000, File: file, Line: 6, Column: 17, IsStmt: true, PrologueEnd: true}, + {Address: 0x401002, File: file, Line: 6, Column: 3}, + {Address: 0x401019, File: file, Line: 9, Column: 3, IsStmt: true}, + {Address: 0x40101a, File: file, Line: 0, Column: 3}, + {Address: 0x40101c, File: file, Line: 9, Column: 3}, + {Address: 0x40101d, EndSequence: true}, + } + files := [][]*LineFile{{file}} + + testLineTable(t, want, files, elfData(t, "testdata/rnglistx.elf")) +} + func TestLineSeek(t *testing.T) { d := elfData(t, "testdata/line-gcc.elf") diff --git a/libgo/go/debug/dwarf/testdata/rnglistx.c b/libgo/go/debug/dwarf/testdata/rnglistx.c new file mode 100644 index 0000000..8770435 --- /dev/null +++ b/libgo/go/debug/dwarf/testdata/rnglistx.c @@ -0,0 +1,19 @@ +// clang -gdwarf-5 -O2 -nostdlib + +__attribute__((noinline, cold)) +static int sum(int i) { + int j, s; + + s = 0; + for (j = 0; j < i; j++) { + s += j * i; + } + return s; +} + +int main(int argc, char** argv) { + if (argc == 0) { + return 0; + } + return sum(argc); +} diff --git a/libgo/go/debug/dwarf/testdata/rnglistx.elf b/libgo/go/debug/dwarf/testdata/rnglistx.elf Binary files differnew file mode 100755 index 0000000..c2d7f55 --- /dev/null +++ b/libgo/go/debug/dwarf/testdata/rnglistx.elf diff --git a/libgo/go/debug/dwarf/type.go b/libgo/go/debug/dwarf/type.go index 316db25..eb5a666 100644 --- a/libgo/go/debug/dwarf/type.go +++ b/libgo/go/debug/dwarf/type.go @@ -292,11 +292,35 @@ func (d *Data) Type(off Offset) (Type, error) { return d.readType("info", d.Reader(), off, d.typeCache, nil) } +type typeFixer struct { + typedefs []*TypedefType + arraytypes []*Type +} + +func (tf *typeFixer) recordArrayType(t *Type) { + if t == nil { + return + } + _, ok := (*t).(*ArrayType) + if ok { + tf.arraytypes = append(tf.arraytypes, t) + } +} + +func (tf *typeFixer) apply() { + for _, t := range tf.typedefs { + t.Common().ByteSize = t.Type.Size() + } + for _, t := range tf.arraytypes { + zeroArray(t) + } +} + // readType reads a type from r at off of name. It adds types to the // type cache, appends new typedef types to typedefs, and computes the // sizes of types. Callers should pass nil for typedefs; this is used // for internal recursion. -func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Offset]Type, typedefs *[]*TypedefType) (Type, error) { +func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Offset]Type, fixups *typeFixer) (Type, error) { if t, ok := typeCache[off]; ok { return t, nil } @@ -311,18 +335,16 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off } // If this is the root of the recursion, prepare to resolve - // typedef sizes once the recursion is done. This must be done - // after the type graph is constructed because it may need to - // resolve cycles in a different order than readType - // encounters them. - if typedefs == nil { - var typedefList []*TypedefType + // typedef sizes and perform other fixups once the recursion is + // done. This must be done after the type graph is constructed + // because it may need to resolve cycles in a different order than + // readType encounters them. + if fixups == nil { + var fixer typeFixer defer func() { - for _, t := range typedefList { - t.Common().ByteSize = t.Type.Size() - } + fixer.apply() }() - typedefs = &typedefList + fixups = &fixer } // Parse type from Entry. @@ -376,7 +398,7 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off var t Type switch toff := tval.(type) { case Offset: - if t, err = d.readType(name, r.clone(), toff, typeCache, typedefs); err != nil { + if t, err = d.readType(name, r.clone(), toff, typeCache, fixups); err != nil { return nil } case uint64: @@ -567,7 +589,7 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off if bito == lastFieldBitOffset && t.Kind != "union" { // Last field was zero width. Fix array length. // (DWARF writes out 0-length arrays as if they were 1-length arrays.) - zeroArray(lastFieldType) + fixups.recordArrayType(lastFieldType) } lastFieldType = &f.Type lastFieldBitOffset = bito @@ -576,7 +598,7 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off b, ok := e.Val(AttrByteSize).(int64) if ok && b*8 == lastFieldBitOffset { // Final field must be zero width. Fix array length. - zeroArray(lastFieldType) + fixups.recordArrayType(lastFieldType) } } @@ -719,7 +741,7 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off // Record that we need to resolve this // type's size once the type graph is // constructed. - *typedefs = append(*typedefs, t) + fixups.typedefs = append(fixups.typedefs, t) case *PtrType: b = int64(addressSize) } @@ -737,11 +759,8 @@ Error: } func zeroArray(t *Type) { - if t == nil { - return - } - at, ok := (*t).(*ArrayType) - if !ok || at.Type.Size() == 0 { + at := (*t).(*ArrayType) + if at.Type.Size() == 0 { return } // Make a copy to avoid invalidating typeCache. diff --git a/libgo/go/debug/dwarf/unit.go b/libgo/go/debug/dwarf/unit.go index 29a744f..9b3d6e9 100644 --- a/libgo/go/debug/dwarf/unit.go +++ b/libgo/go/debug/dwarf/unit.go @@ -48,7 +48,9 @@ func (d *Data) parseUnits() ([]unit, error) { break } b.skip(int(len)) - nunit++ + if len > 0 { + nunit++ + } } if b.err != nil { return nil, b.err @@ -61,7 +63,9 @@ func (d *Data) parseUnits() ([]unit, error) { u := &units[i] u.base = b.off var n Offset - n, u.is64 = b.unitLength() + for n == 0 { + n, u.is64 = b.unitLength() + } dataOff := b.off vers := b.uint16() if vers < 2 || vers > 5 { diff --git a/libgo/go/debug/elf/elf.go b/libgo/go/debug/elf/elf.go index 2b777ea..9f8399d 100644 --- a/libgo/go/debug/elf/elf.go +++ b/libgo/go/debug/elf/elf.go @@ -123,8 +123,8 @@ const ( ELFOSABI_NONE OSABI = 0 /* UNIX System V ABI */ ELFOSABI_HPUX OSABI = 1 /* HP-UX operating system */ ELFOSABI_NETBSD OSABI = 2 /* NetBSD */ - ELFOSABI_LINUX OSABI = 3 /* GNU/Linux */ - ELFOSABI_HURD OSABI = 4 /* GNU/Hurd */ + ELFOSABI_LINUX OSABI = 3 /* Linux */ + ELFOSABI_HURD OSABI = 4 /* Hurd */ ELFOSABI_86OPEN OSABI = 5 /* 86Open common IA32 ABI */ ELFOSABI_SOLARIS OSABI = 6 /* Solaris */ ELFOSABI_AIX OSABI = 7 /* AIX */ @@ -644,6 +644,7 @@ const ( SHT_GNU_VERSYM SectionType = 0x6fffffff /* GNU version symbol table */ SHT_HIOS SectionType = 0x6fffffff /* Last of OS specific semantics */ SHT_LOPROC SectionType = 0x70000000 /* reserved range for processor */ + SHT_MIPS_ABIFLAGS SectionType = 0x7000002a /* .MIPS.abiflags */ SHT_HIPROC SectionType = 0x7fffffff /* specific section header types */ SHT_LOUSER SectionType = 0x80000000 /* reserved range for application */ SHT_HIUSER SectionType = 0xffffffff /* specific indexes */ @@ -675,6 +676,7 @@ var shtStrings = []intName{ {0x6ffffffe, "SHT_GNU_VERNEED"}, {0x6fffffff, "SHT_GNU_VERSYM"}, {0x70000000, "SHT_LOPROC"}, + {0x7000002a, "SHT_MIPS_ABIFLAGS"}, {0x7fffffff, "SHT_HIPROC"}, {0x80000000, "SHT_LOUSER"}, {0xffffffff, "SHT_HIUSER"}, diff --git a/libgo/go/debug/elf/file.go b/libgo/go/debug/elf/file.go index b409167..38a9313 100644 --- a/libgo/go/debug/elf/file.go +++ b/libgo/go/debug/elf/file.go @@ -1299,6 +1299,13 @@ func (f *File) DWARF() (*dwarf.Data, error) { b = dbuf } + if f.Type == ET_EXEC { + // Do not apply relocations to DWARF sections for ET_EXEC binaries. + // Relocations should already be applied, and .rela sections may + // contain incorrect data. + return b, nil + } + for _, r := range f.Sections { if r.Type != SHT_RELA && r.Type != SHT_REL { continue diff --git a/libgo/go/debug/macho/macho.go b/libgo/go/debug/macho/macho.go index 49e107e..9fa9f95 100644 --- a/libgo/go/debug/macho/macho.go +++ b/libgo/go/debug/macho/macho.go @@ -4,7 +4,7 @@ // Mach-O header data structures // Originally at: -// http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html (since deleted by Apply) +// http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html (since deleted by Apple) // Archived copy at: // https://web.archive.org/web/20090819232456/http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/index.html // For cloned PDF see: diff --git a/libgo/go/debug/pe/file.go b/libgo/go/debug/pe/file.go index 7d763ff..e50229e 100644 --- a/libgo/go/debug/pe/file.go +++ b/libgo/go/debug/pe/file.go @@ -75,7 +75,7 @@ func NewFile(r io.ReaderAt) (*File, error) { var sign [4]byte r.ReadAt(sign[:], signoff) if !(sign[0] == 'P' && sign[1] == 'E' && sign[2] == 0 && sign[3] == 0) { - return nil, fmt.Errorf("Invalid PE COFF file signature of %v.", sign) + return nil, fmt.Errorf("invalid PE file signature: % x", sign) } base = signoff + 4 } else { @@ -86,9 +86,14 @@ func NewFile(r io.ReaderAt) (*File, error) { return nil, err } switch f.FileHeader.Machine { - case IMAGE_FILE_MACHINE_UNKNOWN, IMAGE_FILE_MACHINE_ARMNT, IMAGE_FILE_MACHINE_AMD64, IMAGE_FILE_MACHINE_I386: + case IMAGE_FILE_MACHINE_AMD64, + IMAGE_FILE_MACHINE_ARM64, + IMAGE_FILE_MACHINE_ARMNT, + IMAGE_FILE_MACHINE_I386, + IMAGE_FILE_MACHINE_UNKNOWN: + // ok default: - return nil, fmt.Errorf("Unrecognised COFF file header machine value of 0x%x.", f.FileHeader.Machine) + return nil, fmt.Errorf("unrecognized PE machine: %#x", f.FileHeader.Machine) } var err error @@ -112,7 +117,7 @@ func NewFile(r io.ReaderAt) (*File, error) { // Seek past file header. _, err = sr.Seek(base+int64(binary.Size(f.FileHeader)), seekStart) if err != nil { - return nil, fmt.Errorf("failure to seek past the file header: %v", err) + return nil, err } // Read optional header. @@ -309,7 +314,7 @@ func (f *File) ImportedSymbols() ([]string, error) { return nil, nil } - pe64 := f.Machine == IMAGE_FILE_MACHINE_AMD64 + pe64 := f.Machine == IMAGE_FILE_MACHINE_AMD64 || f.Machine == IMAGE_FILE_MACHINE_ARM64 // grab the number of data directory entries var dd_length uint32 diff --git a/libgo/go/debug/pe/file_cgo_test.go b/libgo/go/debug/pe/file_cgo_test.go index 739671d..13eb4e6 100644 --- a/libgo/go/debug/pe/file_cgo_test.go +++ b/libgo/go/debug/pe/file_cgo_test.go @@ -2,12 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cgo // +build cgo package pe import ( "os/exec" + "runtime" "testing" ) @@ -23,6 +25,9 @@ func TestDefaultLinkerDWARF(t *testing.T) { } func TestInternalLinkerDWARF(t *testing.T) { + if runtime.GOARCH == "arm64" { + t.Skip("internal linker disabled on windows/arm64") + } testCgoDWARF(t, linkCgoInternal) } diff --git a/libgo/go/debug/pe/file_test.go b/libgo/go/debug/pe/file_test.go index 58deff1..8964b4f 100644 --- a/libgo/go/debug/pe/file_test.go +++ b/libgo/go/debug/pe/file_test.go @@ -353,11 +353,7 @@ func testDWARF(t *testing.T, linktype int) { } testenv.MustHaveGoRun(t) - tmpdir, err := os.MkdirTemp("", "TestDWARF") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) + tmpdir := t.TempDir() src := filepath.Join(tmpdir, "a.go") file, err := os.Create(src) @@ -472,11 +468,7 @@ func TestBSSHasZeros(t *testing.T) { t.Skip("skipping test: gcc is missing") } - tmpdir, err := os.MkdirTemp("", "TestBSSHasZeros") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) + tmpdir := t.TempDir() srcpath := filepath.Join(tmpdir, "a.c") src := ` @@ -596,15 +588,10 @@ func TestBuildingWindowsGUI(t *testing.T) { if runtime.GOOS != "windows" { t.Skip("skipping windows only test") } - tmpdir, err := os.MkdirTemp("", "TestBuildingWindowsGUI") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) + tmpdir := t.TempDir() src := filepath.Join(tmpdir, "a.go") - err = os.WriteFile(src, []byte(`package main; func main() {}`), 0644) - if err != nil { + if err := os.WriteFile(src, []byte(`package main; func main() {}`), 0644); err != nil { t.Fatal(err) } exe := filepath.Join(tmpdir, "a.exe") diff --git a/libgo/go/embed/embed.go b/libgo/go/embed/embed.go index 98da870..851cc21 100644 --- a/libgo/go/embed/embed.go +++ b/libgo/go/embed/embed.go @@ -143,7 +143,7 @@ import ( // See the package documentation for more details about initializing an FS. type FS struct { // The compiler knows the layout of this struct. - // See cmd/compile/internal/gc's initEmbed. + // See cmd/compile/internal/staticdata's WriteEmbed. // // The files list is sorted by name but not by simple string comparison. // Instead, each file's name takes the form "dir/elem" or "dir/elem/". @@ -213,7 +213,7 @@ var ( // It implements fs.FileInfo and fs.DirEntry. type file struct { // The compiler knows the layout of this struct. - // See cmd/compile/internal/gc's initEmbed. + // See cmd/compile/internal/staticdata's WriteEmbed. name string data string hash [16]byte // truncated SHA256 hash @@ -386,15 +386,15 @@ func (d *openDir) Read([]byte) (int, error) { func (d *openDir) ReadDir(count int) ([]fs.DirEntry, error) { n := len(d.files) - d.offset - if count > 0 && n > count { - n = count - } if n == 0 { if count <= 0 { return nil, nil } return nil, io.EOF } + if count > 0 && n > count { + n = count + } list := make([]fs.DirEntry, n) for i := range list { list[i] = &d.files[d.offset+i] diff --git a/libgo/go/embed/internal/embedtest/embed_test.go b/libgo/go/embed/internal/embedtest/embed_test.go index 43ae5c7..2d50f5e 100644 --- a/libgo/go/embed/internal/embedtest/embed_test.go +++ b/libgo/go/embed/internal/embedtest/embed_test.go @@ -102,12 +102,12 @@ func TestHidden(t *testing.T) { t.Logf("//go:embed testdata") testDir(t, dir, "testdata", - "ascii.txt", "glass.txt", "hello.txt", "i/", "ken.txt") + "-not-hidden/", "ascii.txt", "glass.txt", "hello.txt", "i/", "ken.txt") t.Logf("//go:embed testdata/*") testDir(t, star, "testdata", - ".hidden/", "_hidden/", "ascii.txt", "glass.txt", "hello.txt", "i/", "ken.txt") + "-not-hidden/", ".hidden/", "_hidden/", "ascii.txt", "glass.txt", "hello.txt", "i/", "ken.txt") testDir(t, star, "testdata/.hidden", "fortune.txt", "more/") // but not .more or _more diff --git a/libgo/go/embed/internal/embedtest/testdata/-not-hidden/fortune.txt b/libgo/go/embed/internal/embedtest/testdata/-not-hidden/fortune.txt new file mode 100644 index 0000000..31f2013 --- /dev/null +++ b/libgo/go/embed/internal/embedtest/testdata/-not-hidden/fortune.txt @@ -0,0 +1,2 @@ +WARNING: terminal is not fully functional + - (press RETURN) diff --git a/libgo/go/encoding/asn1/asn1.go b/libgo/go/encoding/asn1/asn1.go index f9b9cb4..cffc06d 100644 --- a/libgo/go/encoding/asn1/asn1.go +++ b/libgo/go/encoding/asn1/asn1.go @@ -914,7 +914,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam structType := fieldType for i := 0; i < structType.NumField(); i++ { - if structType.Field(i).PkgPath != "" { + if !structType.Field(i).IsExported() { err = StructuralError{"struct contains unexported fields"} return } diff --git a/libgo/go/encoding/asn1/marshal.go b/libgo/go/encoding/asn1/marshal.go index 0d34d5a..5b4d786 100644 --- a/libgo/go/encoding/asn1/marshal.go +++ b/libgo/go/encoding/asn1/marshal.go @@ -488,7 +488,7 @@ func makeBody(value reflect.Value, params fieldParameters) (e encoder, err error t := v.Type() for i := 0; i < t.NumField(); i++ { - if t.Field(i).PkgPath != "" { + if !t.Field(i).IsExported() { return nil, StructuralError{"struct contains unexported fields"} } } diff --git a/libgo/go/encoding/asn1/marshal_test.go b/libgo/go/encoding/asn1/marshal_test.go index e3a7d8f..f0217ba 100644 --- a/libgo/go/encoding/asn1/marshal_test.go +++ b/libgo/go/encoding/asn1/marshal_test.go @@ -306,7 +306,7 @@ func TestIssue11130(t *testing.T) { return } if !reflect.DeepEqual(v, v1) { - t.Errorf("got: %#v data=%q , want : %#v data=%q\n ", v1, data1, v, data) + t.Errorf("got: %#v data=%q, want : %#v data=%q\n ", v1, data1, v, data) } } diff --git a/libgo/go/encoding/binary/varint.go b/libgo/go/encoding/binary/varint.go index 1fa325d..8fe20b5 100644 --- a/libgo/go/encoding/binary/varint.go +++ b/libgo/go/encoding/binary/varint.go @@ -61,8 +61,13 @@ func Uvarint(buf []byte) (uint64, int) { var x uint64 var s uint for i, b := range buf { + if i == MaxVarintLen64 { + // Catch byte reads past MaxVarintLen64. + // See issue https://golang.org/issues/41185 + return 0, -(i + 1) // overflow + } if b < 0x80 { - if i >= MaxVarintLen64 || i == MaxVarintLen64-1 && b > 1 { + if i == MaxVarintLen64-1 && b > 1 { return 0, -(i + 1) // overflow } return x | uint64(b)<<s, i + 1 diff --git a/libgo/go/encoding/binary/varint_test.go b/libgo/go/encoding/binary/varint_test.go index 6ef4c99..d025a67 100644 --- a/libgo/go/encoding/binary/varint_test.go +++ b/libgo/go/encoding/binary/varint_test.go @@ -7,6 +7,7 @@ package binary import ( "bytes" "io" + "math" "testing" ) @@ -121,10 +122,66 @@ func TestBufferTooSmall(t *testing.T) { } } +// Ensure that we catch overflows of bytes going past MaxVarintLen64. +// See issue https://golang.org/issues/41185 +func TestBufferTooBigWithOverflow(t *testing.T) { + tests := []struct { + in []byte + name string + wantN int + wantValue uint64 + }{ + { + name: "invalid: 1000 bytes", + in: func() []byte { + b := make([]byte, 1000) + for i := range b { + b[i] = 0xff + } + b[999] = 0 + return b + }(), + wantN: -11, + wantValue: 0, + }, + { + name: "valid: math.MaxUint64-40", + in: []byte{0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}, + wantValue: math.MaxUint64 - 40, + wantN: 10, + }, + { + name: "invalid: with more than MaxVarintLen64 bytes", + in: []byte{0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}, + wantN: -11, + wantValue: 0, + }, + { + name: "invalid: 10th byte", + in: []byte{0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, + wantN: -10, + wantValue: 0, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + value, n := Uvarint(tt.in) + if g, w := n, tt.wantN; g != w { + t.Errorf("bytes returned=%d, want=%d", g, w) + } + if g, w := value, tt.wantValue; g != w { + t.Errorf("value=%d, want=%d", g, w) + } + }) + } +} + func testOverflow(t *testing.T, buf []byte, x0 uint64, n0 int, err0 error) { x, n := Uvarint(buf) if x != 0 || n != n0 { - t.Errorf("Uvarint(%v): got x = %d, n = %d; want 0, %d", buf, x, n, n0) + t.Errorf("Uvarint(% X): got x = %d, n = %d; want 0, %d", buf, x, n, n0) } r := bytes.NewReader(buf) @@ -140,8 +197,8 @@ func testOverflow(t *testing.T, buf []byte, x0 uint64, n0 int, err0 error) { func TestOverflow(t *testing.T) { testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x2}, 0, -10, overflow) - testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1, 0, 0}, 0, -13, overflow) - testOverflow(t, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 1<<64-1, 0, overflow) // 11 bytes, should overflow + testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1, 0, 0}, 0, -11, overflow) + testOverflow(t, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 1<<64-1, -11, overflow) // 11 bytes, should overflow } func TestNonCanonicalZero(t *testing.T) { diff --git a/libgo/go/encoding/csv/fuzz.go b/libgo/go/encoding/csv/fuzz.go index 8be21d5..a03fa83 100644 --- a/libgo/go/encoding/csv/fuzz.go +++ b/libgo/go/encoding/csv/fuzz.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gofuzz // +build gofuzz package csv diff --git a/libgo/go/encoding/csv/reader.go b/libgo/go/encoding/csv/reader.go index c40aa50..f860f4f 100644 --- a/libgo/go/encoding/csv/reader.go +++ b/libgo/go/encoding/csv/reader.go @@ -66,7 +66,7 @@ import ( type ParseError struct { StartLine int // Line where the record starts Line int // Line where the error occurred - Column int // Column (rune index) where the error occurred + Column int // Column (1-based byte index) where the error occurred Err error // The actual error } @@ -162,6 +162,10 @@ type Reader struct { // The i'th field ends at offset fieldIndexes[i] in recordBuffer. fieldIndexes []int + // fieldPositions is an index of field positions for the + // last record returned by Read. + fieldPositions []position + // lastRecord is a record cache and only used when ReuseRecord == true. lastRecord []string } @@ -192,6 +196,25 @@ func (r *Reader) Read() (record []string, err error) { return record, err } +// FieldPos returns the line and column corresponding to +// the start of the field with the given index in the slice most recently +// returned by Read. Numbering of lines and columns starts at 1; +// columns are counted in bytes, not runes. +// +// If this is called with an out-of-bounds index, it panics. +func (r *Reader) FieldPos(field int) (line, column int) { + if field < 0 || field >= len(r.fieldPositions) { + panic("out of range index passed to FieldPos") + } + p := &r.fieldPositions[field] + return p.line, p.col +} + +// pos holds the position of a field in the current line. +type position struct { + line, col int +} + // ReadAll reads all the remaining records from r. // Each record is a slice of fields. // A successful call returns err == nil, not err == io.EOF. Because ReadAll is @@ -260,7 +283,7 @@ func (r *Reader) readRecord(dst []string) ([]string, error) { } // Read line (automatically skipping past empty lines and any comments). - var line, fullLine []byte + var line []byte var errRead error for errRead == nil { line, errRead = r.readLine() @@ -272,7 +295,6 @@ func (r *Reader) readRecord(dst []string) ([]string, error) { line = nil continue // Skip empty lines } - fullLine = line break } if errRead == io.EOF { @@ -286,10 +308,20 @@ func (r *Reader) readRecord(dst []string) ([]string, error) { recLine := r.numLine // Starting line for record r.recordBuffer = r.recordBuffer[:0] r.fieldIndexes = r.fieldIndexes[:0] + r.fieldPositions = r.fieldPositions[:0] + pos := position{line: r.numLine, col: 1} parseField: for { if r.TrimLeadingSpace { - line = bytes.TrimLeftFunc(line, unicode.IsSpace) + i := bytes.IndexFunc(line, func(r rune) bool { + return !unicode.IsSpace(r) + }) + if i < 0 { + i = len(line) + pos.col -= lengthNL(line) + } + line = line[i:] + pos.col += i } if len(line) == 0 || line[0] != '"' { // Non-quoted string field @@ -303,48 +335,56 @@ parseField: // Check to make sure a quote does not appear in field. if !r.LazyQuotes { if j := bytes.IndexByte(field, '"'); j >= 0 { - col := utf8.RuneCount(fullLine[:len(fullLine)-len(line[j:])]) + col := pos.col + j err = &ParseError{StartLine: recLine, Line: r.numLine, Column: col, Err: ErrBareQuote} break parseField } } r.recordBuffer = append(r.recordBuffer, field...) r.fieldIndexes = append(r.fieldIndexes, len(r.recordBuffer)) + r.fieldPositions = append(r.fieldPositions, pos) if i >= 0 { line = line[i+commaLen:] + pos.col += i + commaLen continue parseField } break parseField } else { // Quoted string field + fieldPos := pos line = line[quoteLen:] + pos.col += quoteLen for { i := bytes.IndexByte(line, '"') if i >= 0 { // Hit next quote. r.recordBuffer = append(r.recordBuffer, line[:i]...) line = line[i+quoteLen:] + pos.col += i + quoteLen switch rn := nextRune(line); { case rn == '"': // `""` sequence (append quote). r.recordBuffer = append(r.recordBuffer, '"') line = line[quoteLen:] + pos.col += quoteLen case rn == r.Comma: // `",` sequence (end of field). line = line[commaLen:] + pos.col += commaLen r.fieldIndexes = append(r.fieldIndexes, len(r.recordBuffer)) + r.fieldPositions = append(r.fieldPositions, fieldPos) continue parseField case lengthNL(line) == len(line): // `"\n` sequence (end of line). r.fieldIndexes = append(r.fieldIndexes, len(r.recordBuffer)) + r.fieldPositions = append(r.fieldPositions, fieldPos) break parseField case r.LazyQuotes: // `"` sequence (bare quote). r.recordBuffer = append(r.recordBuffer, '"') default: // `"*` sequence (invalid non-escaped quote). - col := utf8.RuneCount(fullLine[:len(fullLine)-len(line)-quoteLen]) - err = &ParseError{StartLine: recLine, Line: r.numLine, Column: col, Err: ErrQuote} + err = &ParseError{StartLine: recLine, Line: r.numLine, Column: pos.col - quoteLen, Err: ErrQuote} break parseField } } else if len(line) > 0 { @@ -353,19 +393,23 @@ parseField: if errRead != nil { break parseField } + pos.col += len(line) line, errRead = r.readLine() + if len(line) > 0 { + pos.line++ + pos.col = 1 + } if errRead == io.EOF { errRead = nil } - fullLine = line } else { // Abrupt end of file (EOF or error). if !r.LazyQuotes && errRead == nil { - col := utf8.RuneCount(fullLine) - err = &ParseError{StartLine: recLine, Line: r.numLine, Column: col, Err: ErrQuote} + err = &ParseError{StartLine: recLine, Line: pos.line, Column: pos.col, Err: ErrQuote} break parseField } r.fieldIndexes = append(r.fieldIndexes, len(r.recordBuffer)) + r.fieldPositions = append(r.fieldPositions, fieldPos) break parseField } } @@ -392,7 +436,12 @@ parseField: // Check or update the expected fields per record. if r.FieldsPerRecord > 0 { if len(dst) != r.FieldsPerRecord && err == nil { - err = &ParseError{StartLine: recLine, Line: recLine, Err: ErrFieldCount} + err = &ParseError{ + StartLine: recLine, + Line: recLine, + Column: 1, + Err: ErrFieldCount, + } } } else if r.FieldsPerRecord == 0 { r.FieldsPerRecord = len(dst) diff --git a/libgo/go/encoding/csv/reader_test.go b/libgo/go/encoding/csv/reader_test.go index 5121791..abe3fdf 100644 --- a/libgo/go/encoding/csv/reader_test.go +++ b/libgo/go/encoding/csv/reader_test.go @@ -5,6 +5,8 @@ package csv import ( + "errors" + "fmt" "io" "reflect" "strings" @@ -12,405 +14,544 @@ import ( "unicode/utf8" ) -func TestRead(t *testing.T) { - tests := []struct { - Name string - Input string - Output [][]string - Error error +type readTest struct { + Name string + Input string + Output [][]string + Positions [][][2]int + Errors []error + + // These fields are copied into the Reader + Comma rune + Comment rune + UseFieldsPerRecord bool // false (default) means FieldsPerRecord is -1 + FieldsPerRecord int + LazyQuotes bool + TrimLeadingSpace bool + ReuseRecord bool +} - // These fields are copied into the Reader - Comma rune - Comment rune - UseFieldsPerRecord bool // false (default) means FieldsPerRecord is -1 - FieldsPerRecord int - LazyQuotes bool - TrimLeadingSpace bool - ReuseRecord bool - }{{ - Name: "Simple", - Input: "a,b,c\n", - Output: [][]string{{"a", "b", "c"}}, - }, { - Name: "CRLF", - Input: "a,b\r\nc,d\r\n", - Output: [][]string{{"a", "b"}, {"c", "d"}}, - }, { - Name: "BareCR", - Input: "a,b\rc,d\r\n", - Output: [][]string{{"a", "b\rc", "d"}}, - }, { - Name: "RFC4180test", - Input: `#field1,field2,field3 -"aaa","bb -b","ccc" -"a,a","b""bb","ccc" -zzz,yyy,xxx +// In these tests, the §, ¶ and ∑ characters in readTest.Input are used to denote +// the start of a field, a record boundary and the position of an error respectively. +// They are removed before parsing and are used to verify the position +// information reported by FieldPos. + +var readTests = []readTest{{ + Name: "Simple", + Input: "§a,§b,§c\n", + Output: [][]string{{"a", "b", "c"}}, +}, { + Name: "CRLF", + Input: "§a,§b\r\n¶§c,§d\r\n", + Output: [][]string{{"a", "b"}, {"c", "d"}}, +}, { + Name: "BareCR", + Input: "§a,§b\rc,§d\r\n", + Output: [][]string{{"a", "b\rc", "d"}}, +}, { + Name: "RFC4180test", + Input: `§#field1,§field2,§field3 +¶§"aaa",§"bb +b",§"ccc" +¶§"a,a",§"b""bb",§"ccc" +¶§zzz,§yyy,§xxx `, - Output: [][]string{ - {"#field1", "field2", "field3"}, - {"aaa", "bb\nb", "ccc"}, - {"a,a", `b"bb`, "ccc"}, - {"zzz", "yyy", "xxx"}, - }, - UseFieldsPerRecord: true, - FieldsPerRecord: 0, - }, { - Name: "NoEOLTest", - Input: "a,b,c", - Output: [][]string{{"a", "b", "c"}}, - }, { - Name: "Semicolon", - Input: "a;b;c\n", - Output: [][]string{{"a", "b", "c"}}, - Comma: ';', - }, { - Name: "MultiLine", - Input: `"two -line","one line","three + Output: [][]string{ + {"#field1", "field2", "field3"}, + {"aaa", "bb\nb", "ccc"}, + {"a,a", `b"bb`, "ccc"}, + {"zzz", "yyy", "xxx"}, + }, + UseFieldsPerRecord: true, + FieldsPerRecord: 0, +}, { + Name: "NoEOLTest", + Input: "§a,§b,§c", + Output: [][]string{{"a", "b", "c"}}, +}, { + Name: "Semicolon", + Input: "§a;§b;§c\n", + Output: [][]string{{"a", "b", "c"}}, + Comma: ';', +}, { + Name: "MultiLine", + Input: `§"two +line",§"one line",§"three line field"`, - Output: [][]string{{"two\nline", "one line", "three\nline\nfield"}}, - }, { - Name: "BlankLine", - Input: "a,b,c\n\nd,e,f\n\n", - Output: [][]string{ - {"a", "b", "c"}, - {"d", "e", "f"}, - }, - }, { - Name: "BlankLineFieldCount", - Input: "a,b,c\n\nd,e,f\n\n", - Output: [][]string{ - {"a", "b", "c"}, - {"d", "e", "f"}, - }, - UseFieldsPerRecord: true, - FieldsPerRecord: 0, - }, { - Name: "TrimSpace", - Input: " a, b, c\n", - Output: [][]string{{"a", "b", "c"}}, - TrimLeadingSpace: true, - }, { - Name: "LeadingSpace", - Input: " a, b, c\n", - Output: [][]string{{" a", " b", " c"}}, - }, { - Name: "Comment", - Input: "#1,2,3\na,b,c\n#comment", - Output: [][]string{{"a", "b", "c"}}, - Comment: '#', - }, { - Name: "NoComment", - Input: "#1,2,3\na,b,c", - Output: [][]string{{"#1", "2", "3"}, {"a", "b", "c"}}, - }, { - Name: "LazyQuotes", - Input: `a "word","1"2",a","b`, - Output: [][]string{{`a "word"`, `1"2`, `a"`, `b`}}, - LazyQuotes: true, - }, { - Name: "BareQuotes", - Input: `a "word","1"2",a"`, - Output: [][]string{{`a "word"`, `1"2`, `a"`}}, - LazyQuotes: true, - }, { - Name: "BareDoubleQuotes", - Input: `a""b,c`, - Output: [][]string{{`a""b`, `c`}}, - LazyQuotes: true, - }, { - Name: "BadDoubleQuotes", - Input: `a""b,c`, - Error: &ParseError{StartLine: 1, Line: 1, Column: 1, Err: ErrBareQuote}, - }, { - Name: "TrimQuote", - Input: ` "a"," b",c`, - Output: [][]string{{"a", " b", "c"}}, - TrimLeadingSpace: true, - }, { - Name: "BadBareQuote", - Input: `a "word","b"`, - Error: &ParseError{StartLine: 1, Line: 1, Column: 2, Err: ErrBareQuote}, - }, { - Name: "BadTrailingQuote", - Input: `"a word",b"`, - Error: &ParseError{StartLine: 1, Line: 1, Column: 10, Err: ErrBareQuote}, - }, { - Name: "ExtraneousQuote", - Input: `"a "word","b"`, - Error: &ParseError{StartLine: 1, Line: 1, Column: 3, Err: ErrQuote}, - }, { - Name: "BadFieldCount", - Input: "a,b,c\nd,e", - Error: &ParseError{StartLine: 2, Line: 2, Err: ErrFieldCount}, - UseFieldsPerRecord: true, - FieldsPerRecord: 0, - }, { - Name: "BadFieldCount1", - Input: `a,b,c`, - Error: &ParseError{StartLine: 1, Line: 1, Err: ErrFieldCount}, - UseFieldsPerRecord: true, - FieldsPerRecord: 2, - }, { - Name: "FieldCount", - Input: "a,b,c\nd,e", - Output: [][]string{{"a", "b", "c"}, {"d", "e"}}, - }, { - Name: "TrailingCommaEOF", - Input: "a,b,c,", - Output: [][]string{{"a", "b", "c", ""}}, - }, { - Name: "TrailingCommaEOL", - Input: "a,b,c,\n", - Output: [][]string{{"a", "b", "c", ""}}, - }, { - Name: "TrailingCommaSpaceEOF", - Input: "a,b,c, ", - Output: [][]string{{"a", "b", "c", ""}}, - TrimLeadingSpace: true, - }, { - Name: "TrailingCommaSpaceEOL", - Input: "a,b,c, \n", - Output: [][]string{{"a", "b", "c", ""}}, - TrimLeadingSpace: true, - }, { - Name: "TrailingCommaLine3", - Input: "a,b,c\nd,e,f\ng,hi,", - Output: [][]string{{"a", "b", "c"}, {"d", "e", "f"}, {"g", "hi", ""}}, - TrimLeadingSpace: true, - }, { - Name: "NotTrailingComma3", - Input: "a,b,c, \n", - Output: [][]string{{"a", "b", "c", " "}}, - }, { - Name: "CommaFieldTest", - Input: `x,y,z,w -x,y,z, -x,y,, -x,,, -,,, -"x","y","z","w" -"x","y","z","" -"x","y","","" -"x","","","" -"","","","" + Output: [][]string{{"two\nline", "one line", "three\nline\nfield"}}, +}, { + Name: "BlankLine", + Input: "§a,§b,§c\n\n¶§d,§e,§f\n\n", + Output: [][]string{ + {"a", "b", "c"}, + {"d", "e", "f"}, + }, +}, { + Name: "BlankLineFieldCount", + Input: "§a,§b,§c\n\n¶§d,§e,§f\n\n", + Output: [][]string{ + {"a", "b", "c"}, + {"d", "e", "f"}, + }, + UseFieldsPerRecord: true, + FieldsPerRecord: 0, +}, { + Name: "TrimSpace", + Input: " §a, §b, §c\n", + Output: [][]string{{"a", "b", "c"}}, + TrimLeadingSpace: true, +}, { + Name: "LeadingSpace", + Input: "§ a,§ b,§ c\n", + Output: [][]string{{" a", " b", " c"}}, +}, { + Name: "Comment", + Input: "#1,2,3\n§a,§b,§c\n#comment", + Output: [][]string{{"a", "b", "c"}}, + Comment: '#', +}, { + Name: "NoComment", + Input: "§#1,§2,§3\n¶§a,§b,§c", + Output: [][]string{{"#1", "2", "3"}, {"a", "b", "c"}}, +}, { + Name: "LazyQuotes", + Input: `§a "word",§"1"2",§a",§"b`, + Output: [][]string{{`a "word"`, `1"2`, `a"`, `b`}}, + LazyQuotes: true, +}, { + Name: "BareQuotes", + Input: `§a "word",§"1"2",§a"`, + Output: [][]string{{`a "word"`, `1"2`, `a"`}}, + LazyQuotes: true, +}, { + Name: "BareDoubleQuotes", + Input: `§a""b,§c`, + Output: [][]string{{`a""b`, `c`}}, + LazyQuotes: true, +}, { + Name: "BadDoubleQuotes", + Input: `§a∑""b,c`, + Errors: []error{&ParseError{Err: ErrBareQuote}}, +}, { + Name: "TrimQuote", + Input: ` §"a",§" b",§c`, + Output: [][]string{{"a", " b", "c"}}, + TrimLeadingSpace: true, +}, { + Name: "BadBareQuote", + Input: `§a ∑"word","b"`, + Errors: []error{&ParseError{Err: ErrBareQuote}}, +}, { + Name: "BadTrailingQuote", + Input: `§"a word",b∑"`, + Errors: []error{&ParseError{Err: ErrBareQuote}}, +}, { + Name: "ExtraneousQuote", + Input: `§"a ∑"word","b"`, + Errors: []error{&ParseError{Err: ErrQuote}}, +}, { + Name: "BadFieldCount", + Input: "§a,§b,§c\n¶∑§d,§e", + Errors: []error{nil, &ParseError{Err: ErrFieldCount}}, + Output: [][]string{{"a", "b", "c"}, {"d", "e"}}, + UseFieldsPerRecord: true, + FieldsPerRecord: 0, +}, { + Name: "BadFieldCountMultiple", + Input: "§a,§b,§c\n¶∑§d,§e\n¶∑§f", + Errors: []error{nil, &ParseError{Err: ErrFieldCount}, &ParseError{Err: ErrFieldCount}}, + Output: [][]string{{"a", "b", "c"}, {"d", "e"}, {"f"}}, + UseFieldsPerRecord: true, + FieldsPerRecord: 0, +}, { + Name: "BadFieldCount1", + Input: `§∑a,§b,§c`, + Errors: []error{&ParseError{Err: ErrFieldCount}}, + Output: [][]string{{"a", "b", "c"}}, + UseFieldsPerRecord: true, + FieldsPerRecord: 2, +}, { + Name: "FieldCount", + Input: "§a,§b,§c\n¶§d,§e", + Output: [][]string{{"a", "b", "c"}, {"d", "e"}}, +}, { + Name: "TrailingCommaEOF", + Input: "§a,§b,§c,§", + Output: [][]string{{"a", "b", "c", ""}}, +}, { + Name: "TrailingCommaEOL", + Input: "§a,§b,§c,§\n", + Output: [][]string{{"a", "b", "c", ""}}, +}, { + Name: "TrailingCommaSpaceEOF", + Input: "§a,§b,§c, §", + Output: [][]string{{"a", "b", "c", ""}}, + TrimLeadingSpace: true, +}, { + Name: "TrailingCommaSpaceEOL", + Input: "§a,§b,§c, §\n", + Output: [][]string{{"a", "b", "c", ""}}, + TrimLeadingSpace: true, +}, { + Name: "TrailingCommaLine3", + Input: "§a,§b,§c\n¶§d,§e,§f\n¶§g,§hi,§", + Output: [][]string{{"a", "b", "c"}, {"d", "e", "f"}, {"g", "hi", ""}}, + TrimLeadingSpace: true, +}, { + Name: "NotTrailingComma3", + Input: "§a,§b,§c,§ \n", + Output: [][]string{{"a", "b", "c", " "}}, +}, { + Name: "CommaFieldTest", + Input: `§x,§y,§z,§w +¶§x,§y,§z,§ +¶§x,§y,§,§ +¶§x,§,§,§ +¶§,§,§,§ +¶§"x",§"y",§"z",§"w" +¶§"x",§"y",§"z",§"" +¶§"x",§"y",§"",§"" +¶§"x",§"",§"",§"" +¶§"",§"",§"",§"" `, - Output: [][]string{ - {"x", "y", "z", "w"}, - {"x", "y", "z", ""}, - {"x", "y", "", ""}, - {"x", "", "", ""}, - {"", "", "", ""}, - {"x", "y", "z", "w"}, - {"x", "y", "z", ""}, - {"x", "y", "", ""}, - {"x", "", "", ""}, - {"", "", "", ""}, - }, - }, { - Name: "TrailingCommaIneffective1", - Input: "a,b,\nc,d,e", - Output: [][]string{ - {"a", "b", ""}, - {"c", "d", "e"}, - }, - TrimLeadingSpace: true, - }, { - Name: "ReadAllReuseRecord", - Input: "a,b\nc,d", - Output: [][]string{ - {"a", "b"}, - {"c", "d"}, - }, - ReuseRecord: true, - }, { - Name: "StartLine1", // Issue 19019 - Input: "a,\"b\nc\"d,e", - Error: &ParseError{StartLine: 1, Line: 2, Column: 1, Err: ErrQuote}, - }, { - Name: "StartLine2", - Input: "a,b\n\"d\n\n,e", - Error: &ParseError{StartLine: 2, Line: 5, Column: 0, Err: ErrQuote}, - }, { - Name: "CRLFInQuotedField", // Issue 21201 - Input: "A,\"Hello\r\nHi\",B\r\n", - Output: [][]string{ - {"A", "Hello\nHi", "B"}, - }, - }, { - Name: "BinaryBlobField", // Issue 19410 - Input: "x09\x41\xb4\x1c,aktau", - Output: [][]string{{"x09A\xb4\x1c", "aktau"}}, - }, { - Name: "TrailingCR", - Input: "field1,field2\r", - Output: [][]string{{"field1", "field2"}}, - }, { - Name: "QuotedTrailingCR", - Input: "\"field\"\r", - Output: [][]string{{"field"}}, - }, { - Name: "QuotedTrailingCRCR", - Input: "\"field\"\r\r", - Error: &ParseError{StartLine: 1, Line: 1, Column: 6, Err: ErrQuote}, - }, { - Name: "FieldCR", - Input: "field\rfield\r", - Output: [][]string{{"field\rfield"}}, - }, { - Name: "FieldCRCR", - Input: "field\r\rfield\r\r", - Output: [][]string{{"field\r\rfield\r"}}, - }, { - Name: "FieldCRCRLF", - Input: "field\r\r\nfield\r\r\n", - Output: [][]string{{"field\r"}, {"field\r"}}, - }, { - Name: "FieldCRCRLFCR", - Input: "field\r\r\n\rfield\r\r\n\r", - Output: [][]string{{"field\r"}, {"\rfield\r"}}, - }, { - Name: "FieldCRCRLFCRCR", - Input: "field\r\r\n\r\rfield\r\r\n\r\r", - Output: [][]string{{"field\r"}, {"\r\rfield\r"}, {"\r"}}, - }, { - Name: "MultiFieldCRCRLFCRCR", - Input: "field1,field2\r\r\n\r\rfield1,field2\r\r\n\r\r,", - Output: [][]string{ - {"field1", "field2\r"}, - {"\r\rfield1", "field2\r"}, - {"\r\r", ""}, - }, - }, { - Name: "NonASCIICommaAndComment", - Input: "a£b,c£ \td,e\n€ comment\n", - Output: [][]string{{"a", "b,c", "d,e"}}, - TrimLeadingSpace: true, - Comma: '£', - Comment: '€', - }, { - Name: "NonASCIICommaAndCommentWithQuotes", - Input: "a€\" b,\"€ c\nλ comment\n", - Output: [][]string{{"a", " b,", " c"}}, - Comma: '€', - Comment: 'λ', - }, { - // λ and θ start with the same byte. - // This tests that the parser doesn't confuse such characters. - Name: "NonASCIICommaConfusion", - Input: "\"abθcd\"λefθgh", - Output: [][]string{{"abθcd", "efθgh"}}, - Comma: 'λ', - Comment: '€', - }, { - Name: "NonASCIICommentConfusion", - Input: "λ\nλ\nθ\nλ\n", - Output: [][]string{{"λ"}, {"λ"}, {"λ"}}, - Comment: 'θ', - }, { - Name: "QuotedFieldMultipleLF", - Input: "\"\n\n\n\n\"", - Output: [][]string{{"\n\n\n\n"}}, - }, { - Name: "MultipleCRLF", - Input: "\r\n\r\n\r\n\r\n", - }, { - // The implementation may read each line in several chunks if it doesn't fit entirely - // in the read buffer, so we should test the code to handle that condition. - Name: "HugeLines", - Input: strings.Repeat("#ignore\n", 10000) + strings.Repeat("@", 5000) + "," + strings.Repeat("*", 5000), - Output: [][]string{{strings.Repeat("@", 5000), strings.Repeat("*", 5000)}}, - Comment: '#', - }, { - Name: "QuoteWithTrailingCRLF", - Input: "\"foo\"bar\"\r\n", - Error: &ParseError{StartLine: 1, Line: 1, Column: 4, Err: ErrQuote}, - }, { - Name: "LazyQuoteWithTrailingCRLF", - Input: "\"foo\"bar\"\r\n", - Output: [][]string{{`foo"bar`}}, - LazyQuotes: true, - }, { - Name: "DoubleQuoteWithTrailingCRLF", - Input: "\"foo\"\"bar\"\r\n", - Output: [][]string{{`foo"bar`}}, - }, { - Name: "EvenQuotes", - Input: `""""""""`, - Output: [][]string{{`"""`}}, - }, { - Name: "OddQuotes", - Input: `"""""""`, - Error: &ParseError{StartLine: 1, Line: 1, Column: 7, Err: ErrQuote}, - }, { - Name: "LazyOddQuotes", - Input: `"""""""`, - Output: [][]string{{`"""`}}, - LazyQuotes: true, - }, { - Name: "BadComma1", - Comma: '\n', - Error: errInvalidDelim, - }, { - Name: "BadComma2", - Comma: '\r', - Error: errInvalidDelim, - }, { - Name: "BadComma3", - Comma: '"', - Error: errInvalidDelim, - }, { - Name: "BadComma4", - Comma: utf8.RuneError, - Error: errInvalidDelim, - }, { - Name: "BadComment1", - Comment: '\n', - Error: errInvalidDelim, - }, { - Name: "BadComment2", - Comment: '\r', - Error: errInvalidDelim, - }, { - Name: "BadComment3", - Comment: utf8.RuneError, - Error: errInvalidDelim, - }, { - Name: "BadCommaComment", - Comma: 'X', - Comment: 'X', - Error: errInvalidDelim, - }} + Output: [][]string{ + {"x", "y", "z", "w"}, + {"x", "y", "z", ""}, + {"x", "y", "", ""}, + {"x", "", "", ""}, + {"", "", "", ""}, + {"x", "y", "z", "w"}, + {"x", "y", "z", ""}, + {"x", "y", "", ""}, + {"x", "", "", ""}, + {"", "", "", ""}, + }, +}, { + Name: "TrailingCommaIneffective1", + Input: "§a,§b,§\n¶§c,§d,§e", + Output: [][]string{ + {"a", "b", ""}, + {"c", "d", "e"}, + }, + TrimLeadingSpace: true, +}, { + Name: "ReadAllReuseRecord", + Input: "§a,§b\n¶§c,§d", + Output: [][]string{ + {"a", "b"}, + {"c", "d"}, + }, + ReuseRecord: true, +}, { + Name: "StartLine1", // Issue 19019 + Input: "§a,\"b\nc∑\"d,e", + Errors: []error{&ParseError{Err: ErrQuote}}, +}, { + Name: "StartLine2", + Input: "§a,§b\n¶§\"d\n\n,e∑", + Errors: []error{nil, &ParseError{Err: ErrQuote}}, + Output: [][]string{{"a", "b"}}, +}, { + Name: "CRLFInQuotedField", // Issue 21201 + Input: "§A,§\"Hello\r\nHi\",§B\r\n", + Output: [][]string{ + {"A", "Hello\nHi", "B"}, + }, +}, { + Name: "BinaryBlobField", // Issue 19410 + Input: "§x09\x41\xb4\x1c,§aktau", + Output: [][]string{{"x09A\xb4\x1c", "aktau"}}, +}, { + Name: "TrailingCR", + Input: "§field1,§field2\r", + Output: [][]string{{"field1", "field2"}}, +}, { + Name: "QuotedTrailingCR", + Input: "§\"field\"\r", + Output: [][]string{{"field"}}, +}, { + Name: "QuotedTrailingCRCR", + Input: "§\"field∑\"\r\r", + Errors: []error{&ParseError{Err: ErrQuote}}, +}, { + Name: "FieldCR", + Input: "§field\rfield\r", + Output: [][]string{{"field\rfield"}}, +}, { + Name: "FieldCRCR", + Input: "§field\r\rfield\r\r", + Output: [][]string{{"field\r\rfield\r"}}, +}, { + Name: "FieldCRCRLF", + Input: "§field\r\r\n¶§field\r\r\n", + Output: [][]string{{"field\r"}, {"field\r"}}, +}, { + Name: "FieldCRCRLFCR", + Input: "§field\r\r\n¶§\rfield\r\r\n\r", + Output: [][]string{{"field\r"}, {"\rfield\r"}}, +}, { + Name: "FieldCRCRLFCRCR", + Input: "§field\r\r\n¶§\r\rfield\r\r\n¶§\r\r", + Output: [][]string{{"field\r"}, {"\r\rfield\r"}, {"\r"}}, +}, { + Name: "MultiFieldCRCRLFCRCR", + Input: "§field1,§field2\r\r\n¶§\r\rfield1,§field2\r\r\n¶§\r\r,§", + Output: [][]string{ + {"field1", "field2\r"}, + {"\r\rfield1", "field2\r"}, + {"\r\r", ""}, + }, +}, { + Name: "NonASCIICommaAndComment", + Input: "§a£§b,c£ \t§d,e\n€ comment\n", + Output: [][]string{{"a", "b,c", "d,e"}}, + TrimLeadingSpace: true, + Comma: '£', + Comment: '€', +}, { + Name: "NonASCIICommaAndCommentWithQuotes", + Input: "§a€§\" b,\"€§ c\nλ comment\n", + Output: [][]string{{"a", " b,", " c"}}, + Comma: '€', + Comment: 'λ', +}, { + // λ and θ start with the same byte. + // This tests that the parser doesn't confuse such characters. + Name: "NonASCIICommaConfusion", + Input: "§\"abθcd\"λ§efθgh", + Output: [][]string{{"abθcd", "efθgh"}}, + Comma: 'λ', + Comment: '€', +}, { + Name: "NonASCIICommentConfusion", + Input: "§λ\n¶§λ\nθ\n¶§λ\n", + Output: [][]string{{"λ"}, {"λ"}, {"λ"}}, + Comment: 'θ', +}, { + Name: "QuotedFieldMultipleLF", + Input: "§\"\n\n\n\n\"", + Output: [][]string{{"\n\n\n\n"}}, +}, { + Name: "MultipleCRLF", + Input: "\r\n\r\n\r\n\r\n", +}, { + // The implementation may read each line in several chunks if it doesn't fit entirely + // in the read buffer, so we should test the code to handle that condition. + Name: "HugeLines", + Input: strings.Repeat("#ignore\n", 10000) + "§" + strings.Repeat("@", 5000) + ",§" + strings.Repeat("*", 5000), + Output: [][]string{{strings.Repeat("@", 5000), strings.Repeat("*", 5000)}}, + Comment: '#', +}, { + Name: "QuoteWithTrailingCRLF", + Input: "§\"foo∑\"bar\"\r\n", + Errors: []error{&ParseError{Err: ErrQuote}}, +}, { + Name: "LazyQuoteWithTrailingCRLF", + Input: "§\"foo\"bar\"\r\n", + Output: [][]string{{`foo"bar`}}, + LazyQuotes: true, +}, { + Name: "DoubleQuoteWithTrailingCRLF", + Input: "§\"foo\"\"bar\"\r\n", + Output: [][]string{{`foo"bar`}}, +}, { + Name: "EvenQuotes", + Input: `§""""""""`, + Output: [][]string{{`"""`}}, +}, { + Name: "OddQuotes", + Input: `§"""""""∑`, + Errors: []error{&ParseError{Err: ErrQuote}}, +}, { + Name: "LazyOddQuotes", + Input: `§"""""""`, + Output: [][]string{{`"""`}}, + LazyQuotes: true, +}, { + Name: "BadComma1", + Comma: '\n', + Errors: []error{errInvalidDelim}, +}, { + Name: "BadComma2", + Comma: '\r', + Errors: []error{errInvalidDelim}, +}, { + Name: "BadComma3", + Comma: '"', + Errors: []error{errInvalidDelim}, +}, { + Name: "BadComma4", + Comma: utf8.RuneError, + Errors: []error{errInvalidDelim}, +}, { + Name: "BadComment1", + Comment: '\n', + Errors: []error{errInvalidDelim}, +}, { + Name: "BadComment2", + Comment: '\r', + Errors: []error{errInvalidDelim}, +}, { + Name: "BadComment3", + Comment: utf8.RuneError, + Errors: []error{errInvalidDelim}, +}, { + Name: "BadCommaComment", + Comma: 'X', + Comment: 'X', + Errors: []error{errInvalidDelim}, +}} - for _, tt := range tests { - t.Run(tt.Name, func(t *testing.T) { - r := NewReader(strings.NewReader(tt.Input)) +func TestRead(t *testing.T) { + newReader := func(tt readTest) (*Reader, [][][2]int, map[int][2]int) { + positions, errPositions, input := makePositions(tt.Input) + r := NewReader(strings.NewReader(input)) - if tt.Comma != 0 { - r.Comma = tt.Comma - } - r.Comment = tt.Comment - if tt.UseFieldsPerRecord { - r.FieldsPerRecord = tt.FieldsPerRecord + if tt.Comma != 0 { + r.Comma = tt.Comma + } + r.Comment = tt.Comment + if tt.UseFieldsPerRecord { + r.FieldsPerRecord = tt.FieldsPerRecord + } else { + r.FieldsPerRecord = -1 + } + r.LazyQuotes = tt.LazyQuotes + r.TrimLeadingSpace = tt.TrimLeadingSpace + r.ReuseRecord = tt.ReuseRecord + return r, positions, errPositions + } + + for _, tt := range readTests { + t.Run(tt.Name, func(t *testing.T) { + r, positions, errPositions := newReader(tt) + out, err := r.ReadAll() + if wantErr := firstError(tt.Errors, positions, errPositions); wantErr != nil { + if !reflect.DeepEqual(err, wantErr) { + t.Fatalf("ReadAll() error mismatch:\ngot %v (%#v)\nwant %v (%#v)", err, err, wantErr, wantErr) + } + if out != nil { + t.Fatalf("ReadAll() output:\ngot %q\nwant nil", out) + } } else { - r.FieldsPerRecord = -1 + if err != nil { + t.Fatalf("unexpected Readall() error: %v", err) + } + if !reflect.DeepEqual(out, tt.Output) { + t.Fatalf("ReadAll() output:\ngot %q\nwant %q", out, tt.Output) + } } - r.LazyQuotes = tt.LazyQuotes - r.TrimLeadingSpace = tt.TrimLeadingSpace - r.ReuseRecord = tt.ReuseRecord - out, err := r.ReadAll() - if !reflect.DeepEqual(err, tt.Error) { - t.Errorf("ReadAll() error:\ngot %v\nwant %v", err, tt.Error) - } else if !reflect.DeepEqual(out, tt.Output) { - t.Errorf("ReadAll() output:\ngot %q\nwant %q", out, tt.Output) + // Check field and error positions. + r, _, _ = newReader(tt) + for recNum := 0; ; recNum++ { + rec, err := r.Read() + var wantErr error + if recNum < len(tt.Errors) && tt.Errors[recNum] != nil { + wantErr = errorWithPosition(tt.Errors[recNum], recNum, positions, errPositions) + } else if recNum >= len(tt.Output) { + wantErr = io.EOF + } + if !reflect.DeepEqual(err, wantErr) { + t.Fatalf("Read() error at record %d:\ngot %v (%#v)\nwant %v (%#v)", recNum, err, err, wantErr, wantErr) + } + // ErrFieldCount is explicitly non-fatal. + if err != nil && !errors.Is(err, ErrFieldCount) { + if recNum < len(tt.Output) { + t.Fatalf("need more records; got %d want %d", recNum, len(tt.Output)) + } + break + } + if got, want := rec, tt.Output[recNum]; !reflect.DeepEqual(got, want) { + t.Errorf("Read vs ReadAll mismatch;\ngot %q\nwant %q", got, want) + } + pos := positions[recNum] + if len(pos) != len(rec) { + t.Fatalf("mismatched position length at record %d", recNum) + } + for i := range rec { + line, col := r.FieldPos(i) + if got, want := [2]int{line, col}, pos[i]; got != want { + t.Errorf("position mismatch at record %d, field %d;\ngot %v\nwant %v", recNum, i, got, want) + } + } } }) } } +// firstError returns the first non-nil error in errs, +// with the position adjusted according to the error's +// index inside positions. +func firstError(errs []error, positions [][][2]int, errPositions map[int][2]int) error { + for i, err := range errs { + if err != nil { + return errorWithPosition(err, i, positions, errPositions) + } + } + return nil +} + +func errorWithPosition(err error, recNum int, positions [][][2]int, errPositions map[int][2]int) error { + parseErr, ok := err.(*ParseError) + if !ok { + return err + } + if recNum >= len(positions) { + panic(fmt.Errorf("no positions found for error at record %d", recNum)) + } + errPos, ok := errPositions[recNum] + if !ok { + panic(fmt.Errorf("no error position found for error at record %d", recNum)) + } + parseErr1 := *parseErr + parseErr1.StartLine = positions[recNum][0][0] + parseErr1.Line = errPos[0] + parseErr1.Column = errPos[1] + return &parseErr1 +} + +// makePositions returns the expected field positions of all +// the fields in text, the positions of any errors, and the text with the position markers +// removed. +// +// The start of each field is marked with a § symbol; +// CSV lines are separated by ¶ symbols; +// Error positions are marked with ∑ symbols. +func makePositions(text string) ([][][2]int, map[int][2]int, string) { + buf := make([]byte, 0, len(text)) + var positions [][][2]int + errPositions := make(map[int][2]int) + line, col := 1, 1 + recNum := 0 + + for len(text) > 0 { + r, size := utf8.DecodeRuneInString(text) + switch r { + case '\n': + line++ + col = 1 + buf = append(buf, '\n') + case '§': + if len(positions) == 0 { + positions = append(positions, [][2]int{}) + } + positions[len(positions)-1] = append(positions[len(positions)-1], [2]int{line, col}) + case '¶': + positions = append(positions, [][2]int{}) + recNum++ + case '∑': + errPositions[recNum] = [2]int{line, col} + default: + buf = append(buf, text[:size]...) + col += size + } + text = text[size:] + } + return positions, errPositions, string(buf) +} + // nTimes is an io.Reader which yields the string s n times. type nTimes struct { s string diff --git a/libgo/go/encoding/gob/debug.go b/libgo/go/encoding/gob/debug.go index 8f93742..5965fea 100644 --- a/libgo/go/encoding/gob/debug.go +++ b/libgo/go/encoding/gob/debug.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. // Delete the next line to include in the gob package. +//go:build ignore // +build ignore package gob diff --git a/libgo/go/encoding/gob/decgen.go b/libgo/go/encoding/gob/decgen.go index 1c31e66..994be87 100644 --- a/libgo/go/encoding/gob/decgen.go +++ b/libgo/go/encoding/gob/decgen.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // encgen writes the helper functions for encoding. Intended to be diff --git a/libgo/go/encoding/gob/decoder.go b/libgo/go/encoding/gob/decoder.go index b52aabe..b476aaa 100644 --- a/libgo/go/encoding/gob/decoder.go +++ b/libgo/go/encoding/gob/decoder.go @@ -152,6 +152,9 @@ func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId { } // Type definition for (-id) follows. dec.recvType(-id) + if dec.err != nil { + break + } // When decoding an interface, after a type there may be a // DelimitedValue still in the buffer. Skip its count. // (Alternatively, the buffer is empty and the byte count @@ -215,7 +218,7 @@ func (dec *Decoder) DecodeValue(v reflect.Value) error { return dec.err } -// If debug.go is compiled into the program , debugFunc prints a human-readable +// If debug.go is compiled into the program, debugFunc prints a human-readable // representation of the gob data read from r by calling that file's Debug function. // Otherwise it is nil. var debugFunc func(io.Reader) diff --git a/libgo/go/encoding/gob/dump.go b/libgo/go/encoding/gob/dump.go index 17238c9..8c0bbc4 100644 --- a/libgo/go/encoding/gob/dump.go +++ b/libgo/go/encoding/gob/dump.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package main diff --git a/libgo/go/encoding/gob/encgen.go b/libgo/go/encoding/gob/encgen.go index 409b8c9..b562da1 100644 --- a/libgo/go/encoding/gob/encgen.go +++ b/libgo/go/encoding/gob/encgen.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // encgen writes the helper functions for encoding. Intended to be diff --git a/libgo/go/encoding/gob/encoder_test.go b/libgo/go/encoding/gob/encoder_test.go index fe27749..6183646 100644 --- a/libgo/go/encoding/gob/encoder_test.go +++ b/libgo/go/encoding/gob/encoder_test.go @@ -1127,3 +1127,28 @@ func TestBadData(t *testing.T) { } } } + +func TestDecodeErrorMultipleTypes(t *testing.T) { + type Test struct { + A string + B int + } + var b bytes.Buffer + NewEncoder(&b).Encode(Test{"one", 1}) + + var result, result2 Test + dec := NewDecoder(&b) + err := dec.Decode(&result) + if err != nil { + t.Errorf("decode: unexpected error %v", err) + } + + b.Reset() + NewEncoder(&b).Encode(Test{"two", 2}) + err = dec.Decode(&result2) + if err == nil { + t.Errorf("decode: expected duplicate type error, got nil") + } else if !strings.Contains(err.Error(), "duplicate type") { + t.Errorf("decode: expected duplicate type error, got %s", err.Error()) + } +} diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go index 86d8a69..a9917e7 100644 --- a/libgo/go/encoding/json/decode.go +++ b/libgo/go/encoding/json/decode.go @@ -200,16 +200,19 @@ func (n Number) Int64() (int64, error) { return strconv.ParseInt(string(n), 10, 64) } +// An errorContext provides context for type errors during decoding. +type errorContext struct { + Struct reflect.Type + FieldStack []string +} + // decodeState represents the state while decoding a JSON value. type decodeState struct { - data []byte - off int // next read offset in data - opcode int // last read result - scan scanner - errorContext struct { // provides context for type errors - Struct reflect.Type - FieldStack []string - } + data []byte + off int // next read offset in data + opcode int // last read result + scan scanner + errorContext *errorContext savedError error useNumber bool disallowUnknownFields bool @@ -229,10 +232,11 @@ func (d *decodeState) init(data []byte) *decodeState { d.data = data d.off = 0 d.savedError = nil - d.errorContext.Struct = nil - - // Reuse the allocated space for the FieldStack slice. - d.errorContext.FieldStack = d.errorContext.FieldStack[:0] + if d.errorContext != nil { + d.errorContext.Struct = nil + // Reuse the allocated space for the FieldStack slice. + d.errorContext.FieldStack = d.errorContext.FieldStack[:0] + } return d } @@ -246,12 +250,11 @@ func (d *decodeState) saveError(err error) { // addErrorContext returns a new error enhanced with information from d.errorContext func (d *decodeState) addErrorContext(err error) error { - if d.errorContext.Struct != nil || len(d.errorContext.FieldStack) > 0 { + if d.errorContext != nil && (d.errorContext.Struct != nil || len(d.errorContext.FieldStack) > 0) { switch err := err.(type) { case *UnmarshalTypeError: err.Struct = d.errorContext.Struct.Name() err.Field = strings.Join(d.errorContext.FieldStack, ".") - return err } } return err @@ -657,7 +660,10 @@ func (d *decodeState) object(v reflect.Value) error { } var mapElem reflect.Value - origErrorContext := d.errorContext + var origErrorContext errorContext + if d.errorContext != nil { + origErrorContext = *d.errorContext + } for { // Read opening " of string key or closing }. @@ -732,6 +738,9 @@ func (d *decodeState) object(v reflect.Value) error { } subv = subv.Field(i) } + if d.errorContext == nil { + d.errorContext = new(errorContext) + } d.errorContext.FieldStack = append(d.errorContext.FieldStack, f.name) d.errorContext.Struct = t } else if d.disallowUnknownFields { @@ -812,11 +821,13 @@ func (d *decodeState) object(v reflect.Value) error { if d.opcode == scanSkipSpace { d.scanWhile(scanSkipSpace) } - // Reset errorContext to its original state. - // Keep the same underlying array for FieldStack, to reuse the - // space and avoid unnecessary allocs. - d.errorContext.FieldStack = d.errorContext.FieldStack[:len(origErrorContext.FieldStack)] - d.errorContext.Struct = origErrorContext.Struct + if d.errorContext != nil { + // Reset errorContext to its original state. + // Keep the same underlying array for FieldStack, to reuse the + // space and avoid unnecessary allocs. + d.errorContext.FieldStack = d.errorContext.FieldStack[:len(origErrorContext.FieldStack)] + d.errorContext.Struct = origErrorContext.Struct + } if d.opcode == scanEndObject { break } diff --git a/libgo/go/encoding/json/encode.go b/libgo/go/encoding/json/encode.go index 483b9d8..e473e61 100644 --- a/libgo/go/encoding/json/encode.go +++ b/libgo/go/encoding/json/encode.go @@ -794,23 +794,24 @@ func (me mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) { e.WriteByte('{') // Extract and sort the keys. - keys := v.MapKeys() - sv := make([]reflectWithString, len(keys)) - for i, v := range keys { - sv[i].v = v + sv := make([]reflectWithString, v.Len()) + mi := v.MapRange() + for i := 0; mi.Next(); i++ { + sv[i].k = mi.Key() + sv[i].v = mi.Value() if err := sv[i].resolve(); err != nil { e.error(fmt.Errorf("json: encoding error for type %q: %q", v.Type().String(), err.Error())) } } - sort.Slice(sv, func(i, j int) bool { return sv[i].s < sv[j].s }) + sort.Slice(sv, func(i, j int) bool { return sv[i].ks < sv[j].ks }) for i, kv := range sv { if i > 0 { e.WriteByte(',') } - e.string(kv.s, opts.escapeHTML) + e.string(kv.ks, opts.escapeHTML) e.WriteByte(':') - me.elemEnc(e, v.MapIndex(kv.v), opts) + me.elemEnc(e, kv.v, opts) } e.WriteByte('}') e.ptrLevel-- @@ -997,29 +998,30 @@ func typeByIndex(t reflect.Type, index []int) reflect.Type { } type reflectWithString struct { - v reflect.Value - s string + k reflect.Value + v reflect.Value + ks string } func (w *reflectWithString) resolve() error { - if w.v.Kind() == reflect.String { - w.s = w.v.String() + if w.k.Kind() == reflect.String { + w.ks = w.k.String() return nil } - if tm, ok := w.v.Interface().(encoding.TextMarshaler); ok { - if w.v.Kind() == reflect.Ptr && w.v.IsNil() { + if tm, ok := w.k.Interface().(encoding.TextMarshaler); ok { + if w.k.Kind() == reflect.Ptr && w.k.IsNil() { return nil } buf, err := tm.MarshalText() - w.s = string(buf) + w.ks = string(buf) return err } - switch w.v.Kind() { + switch w.k.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - w.s = strconv.FormatInt(w.v.Int(), 10) + w.ks = strconv.FormatInt(w.k.Int(), 10) return nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - w.s = strconv.FormatUint(w.v.Uint(), 10) + w.ks = strconv.FormatUint(w.k.Uint(), 10) return nil } panic("unexpected map key type") @@ -1239,19 +1241,18 @@ func typeFields(t reflect.Type) structFields { // Scan f.typ for fields to include. for i := 0; i < f.typ.NumField(); i++ { sf := f.typ.Field(i) - isUnexported := sf.PkgPath != "" if sf.Anonymous { t := sf.Type if t.Kind() == reflect.Ptr { t = t.Elem() } - if isUnexported && t.Kind() != reflect.Struct { + if !sf.IsExported() && t.Kind() != reflect.Struct { // Ignore embedded fields of unexported non-struct types. continue } // Do not ignore embedded fields of unexported struct types // since they may have exported fields. - } else if isUnexported { + } else if !sf.IsExported() { // Ignore unexported non-embedded fields. continue } diff --git a/libgo/go/encoding/json/encode_test.go b/libgo/go/encoding/json/encode_test.go index 42bb09d..0dad951 100644 --- a/libgo/go/encoding/json/encode_test.go +++ b/libgo/go/encoding/json/encode_test.go @@ -245,6 +245,22 @@ func TestUnsupportedValues(t *testing.T) { } } +// Issue 43207 +func TestMarshalTextFloatMap(t *testing.T) { + m := map[textfloat]string{ + textfloat(math.NaN()): "1", + textfloat(math.NaN()): "1", + } + got, err := Marshal(m) + if err != nil { + t.Errorf("Marshal() error: %v", err) + } + want := `{"TF:NaN":"1","TF:NaN":"1"}` + if string(got) != want { + t.Errorf("Marshal() = %s, want %s", got, want) + } +} + // Ref has Marshaler and Unmarshaler methods with pointer receiver. type Ref int @@ -854,6 +870,10 @@ func tenc(format string, a ...interface{}) ([]byte, error) { return buf.Bytes(), nil } +type textfloat float64 + +func (f textfloat) MarshalText() ([]byte, error) { return tenc(`TF:%0.2f`, f) } + // Issue 13783 func TestEncodeBytekind(t *testing.T) { testdata := []struct { @@ -872,6 +892,7 @@ func TestEncodeBytekind(t *testing.T) { {[]jsonint{5, 4}, `[{"JI":5},{"JI":4}]`}, {[]textint{9, 3}, `["TI:9","TI:3"]`}, {[]int{9, 3}, `[9,3]`}, + {[]textfloat{12, 3}, `["TF:12.00","TF:3.00"]`}, } for _, d := range testdata { js, err := Marshal(d.data) diff --git a/libgo/go/encoding/json/fuzz.go b/libgo/go/encoding/json/fuzz.go index be03f0d..d3fa2d11 100644 --- a/libgo/go/encoding/json/fuzz.go +++ b/libgo/go/encoding/json/fuzz.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gofuzz // +build gofuzz package json diff --git a/libgo/go/encoding/xml/typeinfo.go b/libgo/go/encoding/xml/typeinfo.go index f30fe58..162724e 100644 --- a/libgo/go/encoding/xml/typeinfo.go +++ b/libgo/go/encoding/xml/typeinfo.go @@ -60,7 +60,7 @@ func getTypeInfo(typ reflect.Type) (*typeInfo, error) { n := typ.NumField() for i := 0; i < n; i++ { f := typ.Field(i) - if (f.PkgPath != "" && !f.Anonymous) || f.Tag.Get("xml") == "-" { + if (!f.IsExported() && !f.Anonymous) || f.Tag.Get("xml") == "-" { continue // Private field } diff --git a/libgo/go/encoding/xml/xml.go b/libgo/go/encoding/xml/xml.go index 6f9594d..c14954d 100644 --- a/libgo/go/encoding/xml/xml.go +++ b/libgo/go/encoding/xml/xml.go @@ -261,7 +261,7 @@ func NewTokenDecoder(t TokenReader) *Decoder { // call to Token. To acquire a copy of the bytes, call CopyToken // or the token's Copy method. // -// Token expands self-closing elements such as <br/> +// Token expands self-closing elements such as <br> // into separate start and end elements returned by successive calls. // // Token guarantees that the StartElement and EndElement @@ -768,6 +768,12 @@ func (d *Decoder) rawToken() (Token, error) { } b0, b1 = b1, b } + + // Replace the comment with a space in the returned Directive + // body, so that markup parts that were separated by the comment + // (like a "<" and a "!") don't get joined when re-encoding the + // Directive, taking new semantic meaning. + d.buf.WriteByte(' ') } } return Directive(d.buf.Bytes()), nil @@ -1156,8 +1162,9 @@ func (d *Decoder) nsname() (name Name, ok bool) { if !ok { return } - i := strings.Index(s, ":") - if i < 0 { + if strings.Count(s, ":") > 1 { + name.Local = s + } else if i := strings.Index(s, ":"); i < 1 || i > len(s)-2 { name.Local = s } else { name.Space = s[0:i] diff --git a/libgo/go/encoding/xml/xml_test.go b/libgo/go/encoding/xml/xml_test.go index 5672ebb..19152db 100644 --- a/libgo/go/encoding/xml/xml_test.go +++ b/libgo/go/encoding/xml/xml_test.go @@ -802,11 +802,11 @@ var directivesWithCommentsInput = ` var directivesWithCommentsTokens = []Token{ CharData("\n"), - Directive(`DOCTYPE [<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]`), + Directive(`DOCTYPE [ <!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">]`), CharData("\n"), - Directive(`DOCTYPE [<!ENTITY go "Golang">]`), + Directive(`DOCTYPE [<!ENTITY go "Golang"> ]`), CharData("\n"), - Directive(`DOCTYPE <!-> <!> [<!ENTITY go "Golang">]`), + Directive(`DOCTYPE <!-> <!> [<!ENTITY go "Golang"> ]`), CharData("\n"), } @@ -940,7 +940,7 @@ func (m mapper) Token() (Token, error) { } func TestNewTokenDecoderIdempotent(t *testing.T) { - d := NewDecoder(strings.NewReader(`<br/>`)) + d := NewDecoder(strings.NewReader(`<br>`)) d2 := NewTokenDecoder(d) if d != d2 { t.Error("NewTokenDecoder did not detect underlying Decoder") @@ -1003,3 +1003,60 @@ func TestTokenUnmarshaler(t *testing.T) { d := NewTokenDecoder(tokReader{}) d.Decode(&Failure{}) } + +func testRoundTrip(t *testing.T, input string) { + d := NewDecoder(strings.NewReader(input)) + var tokens []Token + var buf bytes.Buffer + e := NewEncoder(&buf) + for { + tok, err := d.Token() + if err == io.EOF { + break + } + if err != nil { + t.Fatalf("invalid input: %v", err) + } + if err := e.EncodeToken(tok); err != nil { + t.Fatalf("failed to re-encode input: %v", err) + } + tokens = append(tokens, CopyToken(tok)) + } + if err := e.Flush(); err != nil { + t.Fatal(err) + } + + d = NewDecoder(&buf) + for { + tok, err := d.Token() + if err == io.EOF { + break + } + if err != nil { + t.Fatalf("failed to decode output: %v", err) + } + if len(tokens) == 0 { + t.Fatalf("unexpected token: %#v", tok) + } + a, b := tokens[0], tok + if !reflect.DeepEqual(a, b) { + t.Fatalf("token mismatch: %#v vs %#v", a, b) + } + tokens = tokens[1:] + } + if len(tokens) > 0 { + t.Fatalf("lost tokens: %#v", tokens) + } +} + +func TestRoundTrip(t *testing.T) { + tests := map[string]string{ + "leading colon": `<::Test ::foo="bar"><:::Hello></:::Hello><Hello></Hello></::Test>`, + "trailing colon": `<foo abc:="x"></foo>`, + "double colon": `<x:y:foo></x:y:foo>`, + "comments in directives": `<!ENTITY x<!<!-- c1 [ " -->--x --> > <e></e> <!DOCTYPE xxx [ x<!-- c2 " -->--x ]>`, + } + for name, input := range tests { + t.Run(name, func(t *testing.T) { testRoundTrip(t, input) }) + } +} diff --git a/libgo/go/errors/wrap.go b/libgo/go/errors/wrap.go index 7928fe6..4eb4f9a 100644 --- a/libgo/go/errors/wrap.go +++ b/libgo/go/errors/wrap.go @@ -83,10 +83,10 @@ func As(err error, target interface{}) bool { if typ.Kind() != reflectlite.Ptr || val.IsNil() { panic("errors: target must be a non-nil pointer") } - if e := typ.Elem(); e.Kind() != reflectlite.Interface && !e.Implements(errorType) { + targetType := typ.Elem() + if targetType.Kind() != reflectlite.Interface && !targetType.Implements(errorType) { panic("errors: *target must be interface or implement error") } - targetType := typ.Elem() for err != nil { if reflectlite.TypeOf(err).AssignableTo(targetType) { val.Elem().Set(reflectlite.ValueOf(err)) diff --git a/libgo/go/flag/flag.go b/libgo/go/flag/flag.go index a8485f0..885a4c8 100644 --- a/libgo/go/flag/flag.go +++ b/libgo/go/flag/flag.go @@ -508,31 +508,33 @@ func UnquoteUsage(flag *Flag) (name string, usage string) { // documentation for the global function PrintDefaults for more information. func (f *FlagSet) PrintDefaults() { f.VisitAll(func(flag *Flag) { - s := fmt.Sprintf(" -%s", flag.Name) // Two spaces before -; see next two comments. + var b strings.Builder + fmt.Fprintf(&b, " -%s", flag.Name) // Two spaces before -; see next two comments. name, usage := UnquoteUsage(flag) if len(name) > 0 { - s += " " + name + b.WriteString(" ") + b.WriteString(name) } // Boolean flags of one ASCII letter are so common we // treat them specially, putting their usage on the same line. - if len(s) <= 4 { // space, space, '-', 'x'. - s += "\t" + if b.Len() <= 4 { // space, space, '-', 'x'. + b.WriteString("\t") } else { // Four spaces before the tab triggers good alignment // for both 4- and 8-space tab stops. - s += "\n \t" + b.WriteString("\n \t") } - s += strings.ReplaceAll(usage, "\n", "\n \t") + b.WriteString(strings.ReplaceAll(usage, "\n", "\n \t")) if !isZeroValue(flag, flag.DefValue) { if _, ok := flag.Value.(*stringValue); ok { // put quotes on the value - s += fmt.Sprintf(" (default %q)", flag.DefValue) + fmt.Fprintf(&b, " (default %q)", flag.DefValue) } else { - s += fmt.Sprintf(" (default %v)", flag.DefValue) + fmt.Fprintf(&b, " (default %v)", flag.DefValue) } } - fmt.Fprint(f.Output(), s, "\n") + fmt.Fprint(f.Output(), b.String(), "\n") }) } @@ -857,17 +859,23 @@ func Func(name, usage string, fn func(string) error) { // of strings by giving the slice the methods of Value; in particular, Set would // decompose the comma-separated string into the slice. func (f *FlagSet) Var(value Value, name string, usage string) { + // Flag must not begin "-" or contain "=". + if strings.HasPrefix(name, "-") { + panic(f.sprintf("flag %q begins with -", name)) + } else if strings.Contains(name, "=") { + panic(f.sprintf("flag %q contains =", name)) + } + // Remember the default value as a string; it won't change. flag := &Flag{name, usage, value, value.String()} _, alreadythere := f.formal[name] if alreadythere { var msg string if f.name == "" { - msg = fmt.Sprintf("flag redefined: %s", name) + msg = f.sprintf("flag redefined: %s", name) } else { - msg = fmt.Sprintf("%s flag redefined: %s", f.name, name) + msg = f.sprintf("%s flag redefined: %s", f.name, name) } - fmt.Fprintln(f.Output(), msg) panic(msg) // Happens only if flags are declared with identical names } if f.formal == nil { @@ -886,13 +894,19 @@ func Var(value Value, name string, usage string) { CommandLine.Var(value, name, usage) } +// sprintf formats the message, prints it to output, and returns it. +func (f *FlagSet) sprintf(format string, a ...interface{}) string { + msg := fmt.Sprintf(format, a...) + fmt.Fprintln(f.Output(), msg) + return msg +} + // failf prints to standard error a formatted error and usage message and // returns the error. func (f *FlagSet) failf(format string, a ...interface{}) error { - err := fmt.Errorf(format, a...) - fmt.Fprintln(f.Output(), err) + msg := f.sprintf(format, a...) f.usage() - return err + return errors.New(msg) } // usage calls the Usage method for the flag set if one is specified, diff --git a/libgo/go/flag/flag_test.go b/libgo/go/flag/flag_test.go index 06cab79..5835fcf 100644 --- a/libgo/go/flag/flag_test.go +++ b/libgo/go/flag/flag_test.go @@ -655,3 +655,86 @@ func TestExitCode(t *testing.T) { } } } + +func mustPanic(t *testing.T, testName string, expected string, f func()) { + t.Helper() + defer func() { + switch msg := recover().(type) { + case nil: + t.Errorf("%s\n: expected panic(%q), but did not panic", testName, expected) + case string: + if msg != expected { + t.Errorf("%s\n: expected panic(%q), but got panic(%q)", testName, expected, msg) + } + default: + t.Errorf("%s\n: expected panic(%q), but got panic(%T%v)", testName, expected, msg, msg) + } + }() + f() +} + +func TestInvalidFlags(t *testing.T) { + tests := []struct { + flag string + errorMsg string + }{ + { + flag: "-foo", + errorMsg: "flag \"-foo\" begins with -", + }, + { + flag: "foo=bar", + errorMsg: "flag \"foo=bar\" contains =", + }, + } + + for _, test := range tests { + testName := fmt.Sprintf("FlagSet.Var(&v, %q, \"\")", test.flag) + + fs := NewFlagSet("", ContinueOnError) + buf := bytes.NewBuffer(nil) + fs.SetOutput(buf) + + mustPanic(t, testName, test.errorMsg, func() { + var v flagVar + fs.Var(&v, test.flag, "") + }) + if msg := test.errorMsg + "\n"; msg != buf.String() { + t.Errorf("%s\n: unexpected output: expected %q, bug got %q", testName, msg, buf) + } + } +} + +func TestRedefinedFlags(t *testing.T) { + tests := []struct { + flagSetName string + errorMsg string + }{ + { + flagSetName: "", + errorMsg: "flag redefined: foo", + }, + { + flagSetName: "fs", + errorMsg: "fs flag redefined: foo", + }, + } + + for _, test := range tests { + testName := fmt.Sprintf("flag redefined in FlagSet(%q)", test.flagSetName) + + fs := NewFlagSet(test.flagSetName, ContinueOnError) + buf := bytes.NewBuffer(nil) + fs.SetOutput(buf) + + var v flagVar + fs.Var(&v, "foo", "") + + mustPanic(t, testName, test.errorMsg, func() { + fs.Var(&v, "foo", "") + }) + if msg := test.errorMsg + "\n"; msg != buf.String() { + t.Errorf("%s\n: unexpected output: expected %q, bug got %q", testName, msg, buf) + } + } +} diff --git a/libgo/go/fmt/doc.go b/libgo/go/fmt/doc.go index d05ee51..c584cc94 100644 --- a/libgo/go/fmt/doc.go +++ b/libgo/go/fmt/doc.go @@ -189,7 +189,7 @@ When printing a struct, fmt cannot and therefore does not invoke formatting methods such as Error or String on unexported fields. - Explicit argument indexes: + Explicit argument indexes In Printf, Sprintf, and Fprintf, the default behavior is for each formatting verb to format successive arguments passed in the call. @@ -211,7 +211,7 @@ fmt.Sprintf("%d %d %#[1]x %#x", 16, 17) will yield "16 17 0x10 0x11". - Format errors: + Format errors If an invalid argument is given for a verb, such as providing a string to %d, the generated string will contain a diff --git a/libgo/go/fmt/format.go b/libgo/go/fmt/format.go index 4d12f82..bd00e5a 100644 --- a/libgo/go/fmt/format.go +++ b/libgo/go/fmt/format.go @@ -320,7 +320,7 @@ func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, verb rune, digits st f.zero = oldZero } -// truncate truncates the string s to the specified precision, if present. +// truncateString truncates the string s to the specified precision, if present. func (f *fmt) truncateString(s string) string { if f.precPresent { n := f.prec diff --git a/libgo/go/go.mod b/libgo/go/go.mod index 798677b..379dcf5 100644 --- a/libgo/go/go.mod +++ b/libgo/go/go.mod @@ -1,10 +1,10 @@ module std -go 1.16 +go 1.17 require ( - golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 - 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 + golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e + golang.org/x/net v0.0.0-20210510120150-4163338589ed + golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect + golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f // indirect ) diff --git a/libgo/go/go/ast/ast.go b/libgo/go/go/ast/ast.go index 300966a..337c87f 100644 --- a/libgo/go/go/ast/ast.go +++ b/libgo/go/go/ast/ast.go @@ -193,11 +193,14 @@ func isDirective(c string) bool { // in a signature. // Field.Names is nil for unnamed parameters (parameter lists which only contain types) // and embedded struct fields. In the latter case, the field name is the type name. +// Field.Names contains a single name "type" for elements of interface type lists. +// Types belonging to the same type list share the same "type" identifier which also +// records the position of that keyword. // type Field struct { Doc *CommentGroup // associated documentation; or nil - Names []*Ident // field/method/parameter names; or nil - Type Expr // field/method/parameter type + Names []*Ident // field/method/(type) parameter names, or type "type"; or nil + Type Expr // field/method/parameter type, type list type; or nil Tag *BasicLit // field tag; or nil Comment *CommentGroup // line comments; or nil } @@ -206,14 +209,23 @@ func (f *Field) Pos() token.Pos { if len(f.Names) > 0 { return f.Names[0].Pos() } - return f.Type.Pos() + if f.Type != nil { + return f.Type.Pos() + } + return token.NoPos } func (f *Field) End() token.Pos { if f.Tag != nil { return f.Tag.End() } - return f.Type.End() + if f.Type != nil { + return f.Type.End() + } + if len(f.Names) > 0 { + return f.Names[len(f.Names)-1].End() + } + return token.NoPos } // A FieldList represents a list of Fields, enclosed by parentheses or braces. @@ -290,12 +302,6 @@ type ( } // A BasicLit node represents a literal of basic type. - // - // Note that for the CHAR and STRING kinds, the literal is stored - // with its quotes. For example, for a double-quoted STRING, the - // first and the last rune in the Value field will be ". The - // Unquote and UnquoteChar functions in the strconv package can be - // used to unquote STRING and CHAR values, respectively. BasicLit struct { ValuePos token.Pos // literal position Kind token.Token // token.INT, token.FLOAT, token.IMAG, token.CHAR, or token.STRING @@ -434,18 +440,11 @@ type ( // Pointer types are represented via StarExpr nodes. - // A FuncType node represents a function type. - FuncType struct { - Func token.Pos // position of "func" keyword (token.NoPos if there is no "func") - Params *FieldList // (incoming) parameters; non-nil - Results *FieldList // (outgoing) results; or nil - } - // An InterfaceType node represents an interface type. InterfaceType struct { Interface token.Pos // position of "interface" keyword - Methods *FieldList // list of methods - Incomplete bool // true if (source) methods are missing in the Methods list + Methods *FieldList // list of embedded interfaces, methods, or types + Incomplete bool // true if (source) methods or types are missing in the Methods list } // A MapType node represents a map type. @@ -893,15 +892,6 @@ type ( Values []Expr // initial values; or nil Comment *CommentGroup // line comments; or nil } - - // A TypeSpec node represents a type declaration (TypeSpec production). - TypeSpec struct { - Doc *CommentGroup // associated documentation; or nil - Name *Ident // type name - Assign token.Pos // position of '=', if any - Type Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes - Comment *CommentGroup // line comments; or nil - } ) // Pos and End implementations for spec nodes. @@ -965,7 +955,7 @@ type ( GenDecl struct { Doc *CommentGroup // associated documentation; or nil TokPos token.Pos // position of Tok - Tok token.Token // IMPORT, CONST, TYPE, VAR + Tok token.Token // IMPORT, CONST, TYPE, or VAR Lparen token.Pos // position of '(', if any Specs []Spec Rparen token.Pos // position of ')', if any @@ -976,8 +966,10 @@ type ( Doc *CommentGroup // associated documentation; or nil Recv *FieldList // receiver (methods); or nil (functions) Name *Ident // function/method name - Type *FuncType // function signature: parameters, results, and position of "func" keyword + Type *FuncType // function signature: type and value parameters, results, and position of "func" keyword Body *BlockStmt // function body; or nil for external (non-Go) function + // TODO(rFindley) consider storing TParams here, rather than FuncType, as + // they are only valid for declared functions } ) diff --git a/libgo/go/go/ast/ast_notypeparams.go b/libgo/go/go/ast/ast_notypeparams.go new file mode 100644 index 0000000..fa132fb --- /dev/null +++ b/libgo/go/go/ast/ast_notypeparams.go @@ -0,0 +1,28 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !typeparams +// +build !typeparams + +package ast + +import "go/token" + +type ( + // A FuncType node represents a function type. + FuncType struct { + Func token.Pos // position of "func" keyword (token.NoPos if there is no "func") + Params *FieldList // (incoming) parameters; non-nil + Results *FieldList // (outgoing) results; or nil + } + + // A TypeSpec node represents a type declaration (TypeSpec production). + TypeSpec struct { + Doc *CommentGroup // associated documentation; or nil + Name *Ident // type name + Assign token.Pos // position of '=', if any + Type Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes + Comment *CommentGroup // line comments; or nil + } +) diff --git a/libgo/go/go/ast/ast_typeparams.go b/libgo/go/go/ast/ast_typeparams.go new file mode 100644 index 0000000..24fdc5f --- /dev/null +++ b/libgo/go/go/ast/ast_typeparams.go @@ -0,0 +1,51 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build typeparams +// +build typeparams + +package ast + +import "go/token" + +type ( + // A FuncType node represents a function type. + FuncType struct { + Func token.Pos // position of "func" keyword (token.NoPos if there is no "func") + TParams *FieldList // type parameters; or nil + Params *FieldList // (incoming) parameters; non-nil + Results *FieldList // (outgoing) results; or nil + } + + // A TypeSpec node represents a type declaration (TypeSpec production). + TypeSpec struct { + Doc *CommentGroup // associated documentation; or nil + Name *Ident // type name + TParams *FieldList // type parameters; or nil + Assign token.Pos // position of '=', if any + Type Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes + Comment *CommentGroup // line comments; or nil + } + + // A ListExpr node represents a list of expressions separated by commas. + // ListExpr nodes are used as index in IndexExpr nodes representing type + // or function instantiations with more than one type argument. + ListExpr struct { + ElemList []Expr + } +) + +func (*ListExpr) exprNode() {} +func (x *ListExpr) Pos() token.Pos { + if len(x.ElemList) > 0 { + return x.ElemList[0].Pos() + } + return token.NoPos +} +func (x *ListExpr) End() token.Pos { + if len(x.ElemList) > 0 { + return x.ElemList[len(x.ElemList)-1].End() + } + return token.NoPos +} diff --git a/libgo/go/go/ast/commentmap.go b/libgo/go/go/ast/commentmap.go index 2a653a6..5161ea7 100644 --- a/libgo/go/go/ast/commentmap.go +++ b/libgo/go/go/ast/commentmap.go @@ -315,9 +315,17 @@ loop: } func (cmap CommentMap) String() string { + // print map entries in sorted order + var nodes []Node + for node := range cmap { + nodes = append(nodes, node) + } + sort.Sort(byInterval(nodes)) + var buf bytes.Buffer fmt.Fprintln(&buf, "CommentMap {") - for node, comment := range cmap { + for _, node := range nodes { + comment := cmap[node] // print name of identifiers; print node type for other nodes var s string if ident, ok := node.(*Ident); ok { diff --git a/libgo/go/go/ast/walk.go b/libgo/go/go/ast/walk.go index 8ca2195..9224264 100644 --- a/libgo/go/go/ast/walk.go +++ b/libgo/go/go/ast/walk.go @@ -4,8 +4,6 @@ package ast -import "fmt" - // A Visitor's Visit method is invoked for each node encountered by Walk. // If the result visitor w is not nil, Walk visits each of the children // of node with the visitor w, followed by a call of w.Visit(nil). @@ -71,7 +69,9 @@ func Walk(v Visitor, node Node) { Walk(v, n.Doc) } walkIdentList(v, n.Names) - Walk(v, n.Type) + if n.Type != nil { + Walk(v, n.Type) + } if n.Tag != nil { Walk(v, n.Tag) } @@ -161,6 +161,7 @@ func Walk(v Visitor, node Node) { Walk(v, n.Fields) case *FuncType: + walkFuncTypeParams(v, n) if n.Params != nil { Walk(v, n.Params) } @@ -315,6 +316,7 @@ func Walk(v Visitor, node Node) { Walk(v, n.Doc) } Walk(v, n.Name) + walkTypeSpecParams(v, n) Walk(v, n.Type) if n.Comment != nil { Walk(v, n.Comment) @@ -361,7 +363,7 @@ func Walk(v Visitor, node Node) { } default: - panic(fmt.Sprintf("ast.Walk: unexpected node type %T", n)) + walkOtherNodes(v, n) } v.Visit(nil) diff --git a/libgo/go/go/ast/walk_notypeparams.go b/libgo/go/go/ast/walk_notypeparams.go new file mode 100644 index 0000000..d43e13d --- /dev/null +++ b/libgo/go/go/ast/walk_notypeparams.go @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !typeparams +// +build !typeparams + +package ast + +import "fmt" + +func walkFuncTypeParams(v Visitor, n *FuncType) {} +func walkTypeSpecParams(v Visitor, n *TypeSpec) {} + +func walkOtherNodes(v Visitor, n Node) { + panic(fmt.Sprintf("ast.Walk: unexpected node type %T", n)) +} diff --git a/libgo/go/go/ast/walk_typeparams.go b/libgo/go/go/ast/walk_typeparams.go new file mode 100644 index 0000000..b662133 --- /dev/null +++ b/libgo/go/go/ast/walk_typeparams.go @@ -0,0 +1,36 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build typeparams +// +build typeparams + +package ast + +import ( + "fmt" +) + +func walkFuncTypeParams(v Visitor, n *FuncType) { + if n.TParams != nil { + Walk(v, n.TParams) + } +} + +func walkTypeSpecParams(v Visitor, n *TypeSpec) { + if n.TParams != nil { + Walk(v, n.TParams) + } +} + +func walkOtherNodes(v Visitor, n Node) { + if e, ok := n.(*ListExpr); ok { + if e != nil { + for _, elem := range e.ElemList { + Walk(v, elem) + } + } + } else { + panic(fmt.Sprintf("ast.Walk: unexpected node type %T", n)) + } +} diff --git a/libgo/go/go/build/build.go b/libgo/go/go/build/build.go index 3007cef..f19f3d4 100644 --- a/libgo/go/go/build/build.go +++ b/libgo/go/go/build/build.go @@ -9,8 +9,10 @@ import ( "errors" "fmt" "go/ast" + "go/build/constraint" "go/doc" "go/token" + "internal/buildcfg" exec "internal/execabs" "internal/goroot" "internal/goversion" @@ -47,16 +49,18 @@ type Context struct { UseAllFiles bool // use files regardless of +build lines, file names Compiler string // compiler to assume when computing target paths - // The build and release tags specify build constraints + // The build, tool, and release tags specify build constraints // that should be considered satisfied when processing +build lines. // Clients creating a new context may customize BuildTags, which - // defaults to empty, but it is usually an error to customize ReleaseTags, - // which defaults to the list of Go releases the current release is compatible with. + // defaults to empty, but it is usually an error to customize ToolTags or ReleaseTags. + // ToolTags defaults to build tags appropriate to the current Go toolchain configuration. + // ReleaseTags defaults to the list of Go releases the current release is compatible with. // BuildTags is not set for the Default build Context. - // In addition to the BuildTags and ReleaseTags, build constraints + // In addition to the BuildTags, ToolTags, and ReleaseTags, build constraints // consider the values of GOARCH and GOOS as satisfied tags. // The last element in ReleaseTags is assumed to be the current release. BuildTags []string + ToolTags []string ReleaseTags []string // The install suffix specifies a suffix to use in the name of the installation @@ -187,6 +191,7 @@ func (ctxt *Context) readDir(path string) ([]fs.FileInfo, error) { if f := ctxt.ReadDir; f != nil { return f(path) } + // TODO: use os.ReadDir return ioutil.ReadDir(path) } @@ -290,17 +295,27 @@ func defaultGOPATH() string { return "" } -var defaultReleaseTags []string +var defaultToolTags, defaultReleaseTags []string func defaultContext() Context { var c Context - c.GOARCH = envOr("GOARCH", runtime.GOARCH) - c.GOOS = envOr("GOOS", runtime.GOOS) + c.GOARCH = buildcfg.GOARCH + c.GOOS = buildcfg.GOOS c.GOROOT = pathpkg.Clean(runtime.GOROOT()) c.GOPATH = envOr("GOPATH", defaultGOPATH()) c.Compiler = runtime.Compiler + // For each experiment that has been enabled in the toolchain, define a + // build tag with the same name but prefixed by "goexperiment." which can be + // used for compiling alternative files for the experiment. This allows + // changes for the experiment, like extra struct fields in the runtime, + // without affecting the base non-experiment code at all. + for _, exp := range buildcfg.EnabledExperiments() { + c.ToolTags = append(c.ToolTags, "goexperiment."+exp) + } + defaultToolTags = append([]string{}, c.ToolTags...) // our own private copy + // Each major Go release in the Go 1.x series adds a new // "go1.x" release tag. That is, the go1.x tag is present in // all releases >= Go 1.x. Code that requires Go 1.x or later @@ -797,6 +812,17 @@ Found: } var badGoError error + badFiles := make(map[string]bool) + badFile := func(name string, err error) { + if badGoError == nil { + badGoError = err + } + if !badFiles[name] { + p.InvalidGoFiles = append(p.InvalidGoFiles, name) + badFiles[name] = true + } + } + var Sfiles []string // files with ".S"(capital S)/.sx(capital s equivalent for case insensitive filesystems) var firstFile, firstCommentFile string embedPos := make(map[string][]token.Position) @@ -821,16 +847,9 @@ Found: name := d.Name() ext := nameExt(name) - badFile := func(err error) { - if badGoError == nil { - badGoError = err - } - p.InvalidGoFiles = append(p.InvalidGoFiles, name) - } - info, err := ctxt.matchFile(p.Dir, name, allTags, &p.BinaryOnly, fset) if err != nil { - badFile(err) + badFile(name, err) continue } if info == nil { @@ -861,15 +880,18 @@ Found: } if info.parseErr != nil { - badFile(info.parseErr) - continue + badFile(name, info.parseErr) + // Fall through: we might still have a partial AST in info.parsed, + // and we want to list files with parse errors anyway. } - pf := info.parsed - pkg := pf.Name.Name - if pkg == "documentation" { - p.IgnoredGoFiles = append(p.IgnoredGoFiles, name) - continue + var pkg string + if info.parsed != nil { + pkg = info.parsed.Name.Name + if pkg == "documentation" { + p.IgnoredGoFiles = append(p.IgnoredGoFiles, name) + continue + } } isTest := strings.HasSuffix(name, "_test.go") @@ -883,16 +905,18 @@ Found: p.Name = pkg firstFile = name } else if pkg != p.Name { - badFile(&MultiplePackageError{ + // TODO(#45999): The choice of p.Name is arbitrary based on file iteration + // order. Instead of resolving p.Name arbitrarily, we should clear out the + // existing name and mark the existing files as also invalid. + badFile(name, &MultiplePackageError{ Dir: p.Dir, Packages: []string{p.Name, pkg}, Files: []string{firstFile, name}, }) - p.InvalidGoFiles = append(p.InvalidGoFiles, name) } // Grab the first package comment as docs, provided it is not from a test file. - if pf.Doc != nil && p.Doc == "" && !isTest && !isXTest { - p.Doc = doc.Synopsis(pf.Doc.Text()) + if info.parsed != nil && info.parsed.Doc != nil && p.Doc == "" && !isTest && !isXTest { + p.Doc = doc.Synopsis(info.parsed.Doc.Text()) } if mode&ImportComment != 0 { @@ -900,12 +924,12 @@ Found: if line != 0 { com, err := strconv.Unquote(qcom) if err != nil { - badFile(fmt.Errorf("%s:%d: cannot parse import comment", filename, line)) + badFile(name, fmt.Errorf("%s:%d: cannot parse import comment", filename, line)) } else if p.ImportComment == "" { p.ImportComment = com firstCommentFile = name } else if p.ImportComment != com { - badFile(fmt.Errorf("found import comments %q (%s) and %q (%s) in %s", p.ImportComment, firstCommentFile, com, name, p.Dir)) + badFile(name, fmt.Errorf("found import comments %q (%s) and %q (%s) in %s", p.ImportComment, firstCommentFile, com, name, p.Dir)) } } } @@ -915,13 +939,13 @@ Found: for _, imp := range info.imports { if imp.path == "C" { if isTest { - badFile(fmt.Errorf("use of cgo in test %s not supported", filename)) + badFile(name, fmt.Errorf("use of cgo in test %s not supported", filename)) continue } isCgo = true if imp.doc != nil { if err := ctxt.saveCgo(filename, p, imp.doc); err != nil { - badFile(err) + badFile(name, err) } } } @@ -1056,7 +1080,7 @@ func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode) // we must not being doing special things like AllowBinary or IgnoreVendor, // and all the file system callbacks must be nil (we're meant to use the local file system). if mode&AllowBinary != 0 || mode&IgnoreVendor != 0 || - ctxt.JoinPath != nil || ctxt.SplitPathList != nil || ctxt.IsAbsPath != nil || ctxt.IsDir != nil || ctxt.HasSubdir != nil || ctxt.ReadDir != nil || ctxt.OpenFile != nil || !equal(ctxt.ReleaseTags, defaultReleaseTags) { + ctxt.JoinPath != nil || ctxt.SplitPathList != nil || ctxt.IsAbsPath != nil || ctxt.IsDir != nil || ctxt.HasSubdir != nil || ctxt.ReadDir != nil || ctxt.OpenFile != nil || !equal(ctxt.ToolTags, defaultToolTags) || !equal(ctxt.ReleaseTags, defaultReleaseTags) { return errNoModules } @@ -1425,7 +1449,7 @@ func (ctxt *Context) matchFile(dir, name string, allTags map[string]bool, binary // Look for +build comments to accept or reject the file. ok, sawBinaryOnly, err := ctxt.shouldBuild(info.header, allTags) if err != nil { - return nil, err + return nil, fmt.Errorf("%s: %v", name, err) } if !ok && !ctxt.UseAllFiles { return nil, nil @@ -1461,11 +1485,12 @@ var ( bSlashSlash = []byte(slashSlash) bStarSlash = []byte(starSlash) bSlashStar = []byte(slashStar) + bPlusBuild = []byte("+build") goBuildComment = []byte("//go:build") errGoBuildWithoutBuild = errors.New("//go:build comment without // +build comment") - errMultipleGoBuild = errors.New("multiple //go:build comments") // unused in Go 1.(N-1) + errMultipleGoBuild = errors.New("multiple //go:build comments") ) func isGoBuildComment(line []byte) bool { @@ -1500,8 +1525,7 @@ var binaryOnlyComment = []byte("//go:binary-only-package") // shouldBuild reports whether the file should be built // and whether a //go:binary-only-package comment was found. func (ctxt *Context) shouldBuild(content []byte, allTags map[string]bool) (shouldBuild, binaryOnly bool, err error) { - - // Pass 1. Identify leading run of // comments and blank lines, + // Identify leading run of // comments and blank lines, // which must be followed by a blank line. // Also identify any //go:build comments. content, goBuild, sawBinaryOnly, err := parseFileHeader(content) @@ -1509,44 +1533,42 @@ func (ctxt *Context) shouldBuild(content []byte, allTags map[string]bool) (shoul return false, false, err } - // Pass 2. Process each +build line in the run. - p := content - shouldBuild = true - sawBuild := false - for len(p) > 0 { - line := p - if i := bytes.IndexByte(line, '\n'); i >= 0 { - line, p = line[:i], p[i+1:] - } else { - p = p[len(p):] - } - line = bytes.TrimSpace(line) - if !bytes.HasPrefix(line, bSlashSlash) { - continue + // If //go:build line is present, it controls. + // Otherwise fall back to +build processing. + switch { + case goBuild != nil: + x, err := constraint.Parse(string(goBuild)) + if err != nil { + return false, false, fmt.Errorf("parsing //go:build line: %v", err) } - line = bytes.TrimSpace(line[len(bSlashSlash):]) - if len(line) > 0 && line[0] == '+' { - // Looks like a comment +line. - f := strings.Fields(string(line)) - if f[0] == "+build" { - sawBuild = true - ok := false - for _, tok := range f[1:] { - if ctxt.match(tok, allTags) { - ok = true - } - } - if !ok { + shouldBuild = ctxt.eval(x, allTags) + + default: + shouldBuild = true + p := content + for len(p) > 0 { + line := p + if i := bytes.IndexByte(line, '\n'); i >= 0 { + line, p = line[:i], p[i+1:] + } else { + p = p[len(p):] + } + line = bytes.TrimSpace(line) + if !bytes.HasPrefix(line, bSlashSlash) || !bytes.Contains(line, bPlusBuild) { + continue + } + text := string(line) + if !constraint.IsPlusBuild(text) { + continue + } + if x, err := constraint.Parse(text); err == nil { + if !ctxt.eval(x, allTags) { shouldBuild = false } } } } - if goBuild != nil && !sawBuild { - return false, false, errGoBuildWithoutBuild - } - return shouldBuild, sawBinaryOnly, nil } @@ -1582,7 +1604,7 @@ Lines: } if !inSlashStar && isGoBuildComment(line) { - if false && goBuild != nil { // enabled in Go 1.N + if goBuild != nil { return nil, nil, false, errMultipleGoBuild } goBuild = line @@ -1651,7 +1673,7 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup) if len(cond) > 0 { ok := false for _, c := range cond { - if ctxt.match(c, nil) { + if ctxt.matchAuto(c, nil) { ok = true break } @@ -1833,50 +1855,44 @@ func splitQuoted(s string) (r []string, err error) { return args, err } -// match reports whether the name is one of: +// matchAuto interprets text as either a +build or //go:build expression (whichever works), +// reporting whether the expression matches the build context. +// +// matchAuto is only used for testing of tag evaluation +// and in #cgo lines, which accept either syntax. +func (ctxt *Context) matchAuto(text string, allTags map[string]bool) bool { + if strings.ContainsAny(text, "&|()") { + text = "//go:build " + text + } else { + text = "// +build " + text + } + x, err := constraint.Parse(text) + if err != nil { + return false + } + return ctxt.eval(x, allTags) +} + +func (ctxt *Context) eval(x constraint.Expr, allTags map[string]bool) bool { + return x.Eval(func(tag string) bool { return ctxt.matchTag(tag, allTags) }) +} + +// matchTag reports whether the name is one of: // +// cgo (if cgo is enabled) // $GOOS // $GOARCH -// cgo (if cgo is enabled) -// !cgo (if cgo is disabled) // ctxt.Compiler -// !ctxt.Compiler +// linux (if GOOS = android) +// solaris (if GOOS = illumos) // tag (if tag is listed in ctxt.BuildTags or ctxt.ReleaseTags) -// !tag (if tag is not listed in ctxt.BuildTags or ctxt.ReleaseTags) -// a comma-separated list of any of these // -func (ctxt *Context) match(name string, allTags map[string]bool) bool { - if name == "" { - if allTags != nil { - allTags[name] = true - } - return false - } - if i := strings.Index(name, ","); i >= 0 { - // comma-separated list - ok1 := ctxt.match(name[:i], allTags) - ok2 := ctxt.match(name[i+1:], allTags) - return ok1 && ok2 - } - if strings.HasPrefix(name, "!!") { // bad syntax, reject always - return false - } - if strings.HasPrefix(name, "!") { // negation - return len(name) > 1 && !ctxt.match(name[1:], allTags) - } - +// It records all consulted tags in allTags. +func (ctxt *Context) matchTag(name string, allTags map[string]bool) bool { if allTags != nil { allTags[name] = true } - // Tags must be letters, digits, underscores or dots. - // Unlike in Go identifiers, all digits are fine (e.g., "386"). - for _, c := range name { - if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' { - return false - } - } - // special tags if ctxt.CgoEnabled && name == "cgo" { return true @@ -1900,6 +1916,11 @@ func (ctxt *Context) match(name string, allTags map[string]bool) bool { return true } } + for _, tag := range ctxt.ToolTags { + if tag == name { + return true + } + } for _, tag := range ctxt.ReleaseTags { if tag == name { return true @@ -1948,10 +1969,10 @@ func (ctxt *Context) goodOSArchFile(name string, allTags map[string]bool) bool { } n := len(l) if n >= 2 && knownOS[l[n-2]] && knownArch[l[n-1]] { - return ctxt.match(l[n-1], allTags) && ctxt.match(l[n-2], allTags) + return ctxt.matchTag(l[n-1], allTags) && ctxt.matchTag(l[n-2], allTags) } if n >= 1 && (knownOS[l[n-1]] || knownArch[l[n-1]]) { - return ctxt.match(l[n-1], allTags) + return ctxt.matchTag(l[n-1], allTags) } return true } diff --git a/libgo/go/go/build/build_test.go b/libgo/go/go/build/build_test.go index 1c0dc46..a8f361a 100644 --- a/libgo/go/go/build/build_test.go +++ b/libgo/go/go/build/build_test.go @@ -30,7 +30,7 @@ func TestMatch(t *testing.T) { match := func(tag string, want map[string]bool) { t.Helper() m := make(map[string]bool) - if !ctxt.match(tag, m) { + if !ctxt.matchAuto(tag, m) { t.Errorf("%s context should match %s, does not", what, tag) } if !reflect.DeepEqual(m, want) { @@ -40,7 +40,7 @@ func TestMatch(t *testing.T) { nomatch := func(tag string, want map[string]bool) { t.Helper() m := make(map[string]bool) - if ctxt.match(tag, m) { + if ctxt.matchAuto(tag, m) { t.Errorf("%s context should NOT match %s, does", what, tag) } if !reflect.DeepEqual(m, want) { @@ -104,7 +104,8 @@ func TestEmptyFolderImport(t *testing.T) { } func TestMultiplePackageImport(t *testing.T) { - _, err := Import(".", "testdata/multi", 0) + pkg, err := Import(".", "testdata/multi", 0) + mpe, ok := err.(*MultiplePackageError) if !ok { t.Fatal(`Import("testdata/multi") did not return MultiplePackageError.`) @@ -115,7 +116,20 @@ func TestMultiplePackageImport(t *testing.T) { Files: []string{"file.go", "file_appengine.go"}, } if !reflect.DeepEqual(mpe, want) { - t.Errorf("got %#v; want %#v", mpe, want) + t.Errorf("err = %#v; want %#v", mpe, want) + } + + // TODO(#45999): Since the name is ambiguous, pkg.Name should be left empty. + if wantName := "main"; pkg.Name != wantName { + t.Errorf("pkg.Name = %q; want %q", pkg.Name, wantName) + } + + if wantGoFiles := []string{"file.go", "file_appengine.go"}; !reflect.DeepEqual(pkg.GoFiles, wantGoFiles) { + t.Errorf("pkg.GoFiles = %q; want %q", pkg.GoFiles, wantGoFiles) + } + + if wantInvalidFiles := []string{"file_appengine.go"}; !reflect.DeepEqual(pkg.InvalidGoFiles, wantInvalidFiles) { + t.Errorf("pkg.InvalidGoFiles = %q; want %q", pkg.InvalidGoFiles, wantInvalidFiles) } } @@ -155,6 +169,13 @@ var shouldBuildTests = []struct { shouldBuild: true, }, { + name: "Yes2", + content: "//go:build yes\n" + + "package main\n", + tags: map[string]bool{"yes": true}, + shouldBuild: true, + }, + { name: "Or", content: "// +build no yes\n\n" + "package main\n", @@ -162,6 +183,13 @@ var shouldBuildTests = []struct { shouldBuild: true, }, { + name: "Or2", + content: "//go:build no || yes\n" + + "package main\n", + tags: map[string]bool{"yes": true, "no": true}, + shouldBuild: true, + }, + { name: "And", content: "// +build no,yes\n\n" + "package main\n", @@ -169,6 +197,13 @@ var shouldBuildTests = []struct { shouldBuild: false, }, { + name: "And2", + content: "//go:build no && yes\n" + + "package main\n", + tags: map[string]bool{"yes": true, "no": true}, + shouldBuild: false, + }, + { name: "Cgo", content: "// +build cgo\n\n" + "// Copyright The Go Authors.\n\n" + @@ -179,11 +214,22 @@ var shouldBuildTests = []struct { shouldBuild: false, }, { + name: "Cgo2", + content: "//go:build cgo\n" + + "// Copyright The Go Authors.\n\n" + + "// This package implements parsing of tags like\n" + + "// +build tag1\n" + + "package build", + tags: map[string]bool{"cgo": true}, + shouldBuild: false, + }, + { name: "AfterPackage", content: "// Copyright The Go Authors.\n\n" + "package build\n\n" + "// shouldBuild checks tags given by lines of the form\n" + "// +build tag\n" + + "//go:build tag\n" + "func shouldBuild(content []byte)\n", tags: map[string]bool{}, shouldBuild: true, @@ -196,6 +242,13 @@ var shouldBuildTests = []struct { shouldBuild: true, }, { + name: "TooClose2", + content: "//go:build yes\n" + + "package main\n", + tags: map[string]bool{"yes": true}, + shouldBuild: true, + }, + { name: "TooCloseNo", content: "// +build no\n" + "package main\n", @@ -203,6 +256,13 @@ var shouldBuildTests = []struct { shouldBuild: true, }, { + name: "TooCloseNo2", + content: "//go:build no\n" + + "package main\n", + tags: map[string]bool{"no": true}, + shouldBuild: false, + }, + { name: "BinaryOnly", content: "//go:binary-only-package\n" + "// +build yes\n" + @@ -212,41 +272,30 @@ var shouldBuildTests = []struct { shouldBuild: true, }, { - name: "ValidGoBuild", - content: "// +build yes\n\n" + + name: "BinaryOnly2", + content: "//go:binary-only-package\n" + "//go:build no\n" + "package main\n", - tags: map[string]bool{"yes": true}, - shouldBuild: true, - }, - { - name: "MissingBuild", - content: "//go:build no\n" + - "package main\n", - tags: map[string]bool{}, + tags: map[string]bool{"no": true}, + binaryOnly: true, shouldBuild: false, - err: errGoBuildWithoutBuild, }, { - name: "MissingBuild2", - content: "/* */\n" + - "// +build yes\n\n" + + name: "ValidGoBuild", + content: "// +build yes\n\n" + "//go:build no\n" + "package main\n", - tags: map[string]bool{}, + tags: map[string]bool{"no": true}, shouldBuild: false, - err: errGoBuildWithoutBuild, }, { name: "MissingBuild2", - content: "/*\n" + + content: "/* */\n" + "// +build yes\n\n" + - "*/\n" + "//go:build no\n" + "package main\n", - tags: map[string]bool{}, + tags: map[string]bool{"no": true}, shouldBuild: false, - err: errGoBuildWithoutBuild, }, { name: "Comment1", @@ -264,9 +313,8 @@ var shouldBuildTests = []struct { "*/\n\n" + "//go:build no\n" + "package main\n", - tags: map[string]bool{}, + tags: map[string]bool{"no": true}, shouldBuild: false, - err: errGoBuildWithoutBuild, }, { name: "Comment3", @@ -275,9 +323,8 @@ var shouldBuildTests = []struct { "*/\n\n" + "//go:build no\n" + "package main\n", - tags: map[string]bool{}, + tags: map[string]bool{"no": true}, shouldBuild: false, - err: errGoBuildWithoutBuild, }, { name: "Comment4", @@ -291,9 +338,8 @@ var shouldBuildTests = []struct { content: "/**/\n" + "//go:build no\n" + "package main\n", - tags: map[string]bool{}, + tags: map[string]bool{"no": true}, shouldBuild: false, - err: errGoBuildWithoutBuild, }, } @@ -456,11 +502,7 @@ func TestImportDirNotExist(t *testing.T) { testenv.MustHaveGoBuild(t) // really must just have source ctxt := Default - emptyDir, err := os.MkdirTemp("", t.Name()) - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(emptyDir) + emptyDir := t.TempDir() ctxt.GOPATH = emptyDir ctxt.Dir = emptyDir @@ -513,8 +555,7 @@ func TestImportDirNotExist(t *testing.T) { func TestImportVendor(t *testing.T) { testenv.MustHaveGoBuild(t) // really must just have source - defer os.Setenv("GO111MODULE", os.Getenv("GO111MODULE")) - os.Setenv("GO111MODULE", "off") + t.Setenv("GO111MODULE", "off") ctxt := Default wd, err := os.Getwd() @@ -535,8 +576,7 @@ func TestImportVendor(t *testing.T) { func TestImportVendorFailure(t *testing.T) { testenv.MustHaveGoBuild(t) // really must just have source - defer os.Setenv("GO111MODULE", os.Getenv("GO111MODULE")) - os.Setenv("GO111MODULE", "off") + t.Setenv("GO111MODULE", "off") ctxt := Default wd, err := os.Getwd() @@ -558,8 +598,7 @@ func TestImportVendorFailure(t *testing.T) { func TestImportVendorParentFailure(t *testing.T) { testenv.MustHaveGoBuild(t) // really must just have source - defer os.Setenv("GO111MODULE", os.Getenv("GO111MODULE")) - os.Setenv("GO111MODULE", "off") + t.Setenv("GO111MODULE", "off") ctxt := Default wd, err := os.Getwd() @@ -589,16 +628,11 @@ func TestImportPackageOutsideModule(t *testing.T) { // Disable module fetching for this test so that 'go list' fails quickly // without trying to find the latest version of a module. - defer os.Setenv("GOPROXY", os.Getenv("GOPROXY")) - os.Setenv("GOPROXY", "off") + t.Setenv("GOPROXY", "off") // Create a GOPATH in a temporary directory. We don't use testdata // because it's in GOROOT, which interferes with the module heuristic. - gopath, err := os.MkdirTemp("", "gobuild-notmodule") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(gopath) + gopath := t.TempDir() if err := os.MkdirAll(filepath.Join(gopath, "src/example.com/p"), 0777); err != nil { t.Fatal(err) } @@ -606,10 +640,8 @@ func TestImportPackageOutsideModule(t *testing.T) { t.Fatal(err) } - defer os.Setenv("GO111MODULE", os.Getenv("GO111MODULE")) - os.Setenv("GO111MODULE", "on") - defer os.Setenv("GOPATH", os.Getenv("GOPATH")) - os.Setenv("GOPATH", gopath) + t.Setenv("GO111MODULE", "on") + t.Setenv("GOPATH", gopath) ctxt := Default ctxt.GOPATH = gopath ctxt.Dir = filepath.Join(gopath, "src/example.com/p") @@ -658,26 +690,19 @@ func TestIssue23594(t *testing.T) { // Verifies golang.org/issue/34752. func TestMissingImportErrorRepetition(t *testing.T) { testenv.MustHaveGoBuild(t) // need 'go list' internally - tmp, err := os.MkdirTemp("", "") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) + tmp := t.TempDir() if err := os.WriteFile(filepath.Join(tmp, "go.mod"), []byte("module m"), 0666); err != nil { t.Fatal(err) } - defer os.Setenv("GO111MODULE", os.Getenv("GO111MODULE")) - os.Setenv("GO111MODULE", "on") - defer os.Setenv("GOPROXY", os.Getenv("GOPROXY")) - os.Setenv("GOPROXY", "off") - defer os.Setenv("GONOPROXY", os.Getenv("GONOPROXY")) - os.Setenv("GONOPROXY", "none") + t.Setenv("GO111MODULE", "on") + t.Setenv("GOPROXY", "off") + t.Setenv("GONOPROXY", "none") ctxt := Default ctxt.Dir = tmp pkgPath := "example.com/hello" - _, err = ctxt.Import(pkgPath, tmp, FindOnly) + _, err := ctxt.Import(pkgPath, tmp, FindOnly) if err == nil { t.Fatal("unexpected success") } diff --git a/libgo/go/go/build/constraint/expr.go b/libgo/go/go/build/constraint/expr.go index 3b27870..957eb9b 100644 --- a/libgo/go/go/build/constraint/expr.go +++ b/libgo/go/go/build/constraint/expr.go @@ -355,8 +355,8 @@ func IsPlusBuild(line string) bool { return ok } -// splitGoBuild splits apart the leading //go:build prefix in line from the build expression itself. -// It returns "", false if the input is not a //go:build line or if the input contains multiple lines. +// splitPlusBuild splits apart the leading // +build prefix in line from the build expression itself. +// It returns "", false if the input is not a // +build line or if the input contains multiple lines. func splitPlusBuild(line string) (expr string, ok bool) { // A single trailing newline is OK; otherwise multiple lines are not. if len(line) > 0 && line[len(line)-1] == '\n' { @@ -426,6 +426,9 @@ func parsePlusBuildExpr(text string) Expr { x = or(x, y) } } + if x == nil { + x = tag("ignore") + } return x } diff --git a/libgo/go/go/build/constraint/expr_test.go b/libgo/go/go/build/constraint/expr_test.go index 4979f8b5..15d1890 100644 --- a/libgo/go/go/build/constraint/expr_test.go +++ b/libgo/go/go/build/constraint/expr_test.go @@ -216,6 +216,7 @@ var parsePlusBuildExprTests = []struct { {"!!x", tag("ignore")}, {"!x", not(tag("x"))}, {"!", tag("ignore")}, + {"", tag("ignore")}, } func TestParsePlusBuildExpr(t *testing.T) { @@ -232,19 +233,22 @@ func TestParsePlusBuildExpr(t *testing.T) { var constraintTests = []struct { in string x Expr - err error + err string }{ - {"//+build x y", or(tag("x"), tag("y")), nil}, - {"// +build x y \n", or(tag("x"), tag("y")), nil}, - {"// +build x y \n ", nil, errNotConstraint}, - {"// +build x y \nmore", nil, errNotConstraint}, - {" //+build x y", nil, errNotConstraint}, + {"//+build !", tag("ignore"), ""}, + {"//+build", tag("ignore"), ""}, + {"//+build x y", or(tag("x"), tag("y")), ""}, + {"// +build x y \n", or(tag("x"), tag("y")), ""}, + {"// +build x y \n ", nil, "not a build constraint"}, + {"// +build x y \nmore", nil, "not a build constraint"}, + {" //+build x y", nil, "not a build constraint"}, - {"//go:build x && y", and(tag("x"), tag("y")), nil}, - {"//go:build x && y\n", and(tag("x"), tag("y")), nil}, - {"//go:build x && y\n ", nil, errNotConstraint}, - {"//go:build x && y\nmore", nil, errNotConstraint}, - {" //go:build x && y", nil, errNotConstraint}, + {"//go:build x && y", and(tag("x"), tag("y")), ""}, + {"//go:build x && y\n", and(tag("x"), tag("y")), ""}, + {"//go:build x && y\n ", nil, "not a build constraint"}, + {"//go:build x && y\nmore", nil, "not a build constraint"}, + {" //go:build x && y", nil, "not a build constraint"}, + {"//go:build\n", nil, "unexpected end of expression"}, } func TestParse(t *testing.T) { @@ -252,14 +256,14 @@ func TestParse(t *testing.T) { t.Run(fmt.Sprint(i), func(t *testing.T) { x, err := Parse(tt.in) if err != nil { - if tt.err == nil { + if tt.err == "" { t.Errorf("Constraint(%q): unexpected error: %v", tt.in, err) - } else if tt.err != err { + } else if !strings.Contains(err.Error(), tt.err) { t.Errorf("Constraint(%q): error %v, want %v", tt.in, err, tt.err) } return } - if tt.err != nil { + if tt.err != "" { t.Errorf("Constraint(%q) = %v, want error %v", tt.in, x, tt.err) return } diff --git a/libgo/go/go/build/deps_test.go b/libgo/go/go/build/deps_test.go index f0bbe4e..e9b4e71 100644 --- a/libgo/go/go/build/deps_test.go +++ b/libgo/go/go/build/deps_test.go @@ -71,14 +71,19 @@ var depsRules = ` # No dependencies allowed for any of these packages. NONE < container/list, container/ring, - internal/cfg, internal/cpu, + internal/cfg, internal/cpu, internal/goexperiment, internal/goversion, internal/nettrace, unicode/utf8, unicode/utf16, unicode, unsafe; + # These packages depend only on unsafe. + unsafe + < internal/abi; + # RUNTIME is the core runtime group of packages, all of them very light-weight. - internal/cpu, unsafe + internal/abi, internal/cpu, internal/goexperiment, unsafe < internal/bytealg + < internal/itoa < internal/unsafeheader < runtime/internal/sys < runtime/internal/atomic @@ -273,9 +278,13 @@ var depsRules = ` < go/token < go/scanner < go/ast + < go/internal/typeparams < go/parser; - go/parser, text/tabwriter + FMT + < go/build/constraint; + + go/build/constraint, go/parser, text/tabwriter < go/printer < go/format; @@ -285,13 +294,13 @@ var depsRules = ` math/big, go/token < go/constant; - container/heap, go/constant, go/parser + container/heap, go/constant, go/parser, regexp < go/types; - FMT - < go/build/constraint; + FMT, internal/goexperiment + < internal/buildcfg; - go/doc, go/parser, internal/goroot, internal/goversion + go/build/constraint, go/doc, go/parser, internal/buildcfg, internal/goroot, internal/goversion < go/build; DEBUG, go/build, go/types, text/scanner @@ -383,6 +392,9 @@ var depsRules = ` < crypto < crypto/subtle < crypto/internal/subtle + < crypto/elliptic/internal/fiat + < crypto/ed25519/internal/edwards25519/field + < crypto/ed25519/internal/edwards25519 < crypto/cipher < crypto/aes, crypto/des, crypto/hmac, crypto/md5, crypto/rc4, crypto/sha1, crypto/sha256, crypto/sha512 @@ -394,7 +406,6 @@ var depsRules = ` CRYPTO, FMT, math/big < crypto/rand < crypto/internal/randutil - < crypto/ed25519/internal/edwards25519 < crypto/ed25519 < encoding/asn1 < golang.org/x/crypto/cryptobyte/asn1 @@ -429,7 +440,8 @@ var depsRules = ` # HTTP, King of Dependencies. FMT - < golang.org/x/net/http2/hpack, net/http/internal; + < golang.org/x/net/http2/hpack + < net/http/internal, net/http/internal/ascii, net/http/internal/testcert; FMT, NET, container/list, encoding/binary, log < golang.org/x/text/transform @@ -447,6 +459,8 @@ var depsRules = ` golang.org/x/net/http/httpproxy, golang.org/x/net/http2/hpack, net/http/internal, + net/http/internal/ascii, + net/http/internal/testcert, net/http/httptrace, mime/multipart, log @@ -457,7 +471,7 @@ var depsRules = ` encoding/json, net/http < expvar; - net/http + net/http, net/http/internal/ascii < net/http/cookiejar, net/http/httputil; net/http, flag @@ -494,7 +508,7 @@ var depsRules = ` FMT, flag, math/rand < testing/quick; - FMT, flag, runtime/debug, runtime/trace, internal/sysinfo + FMT, flag, runtime/debug, runtime/trace, internal/sysinfo, math/rand < testing; internal/testlog, runtime/pprof, regexp diff --git a/libgo/go/go/build/doc.go b/libgo/go/go/build/doc.go index 2c6f0a8..778b4f4 100644 --- a/libgo/go/go/build/doc.go +++ b/libgo/go/go/build/doc.go @@ -59,7 +59,7 @@ // // A build constraint, also known as a build tag, is a line comment that begins // -// // +build +// //go:build // // that lists the conditions under which a file should be included in the // package. Build constraints may also be part of a file's name diff --git a/libgo/go/go/build/gc.go b/libgo/go/go/build/gc.go index 3025cd5..e16e186 100644 --- a/libgo/go/go/build/gc.go +++ b/libgo/go/go/build/gc.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gc // +build gc package build diff --git a/libgo/go/go/build/gccgo.go b/libgo/go/go/build/gccgo.go index c6aac9a..c8ec704 100644 --- a/libgo/go/go/build/gccgo.go +++ b/libgo/go/go/build/gccgo.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gccgo // +build gccgo package build diff --git a/libgo/go/go/build/read.go b/libgo/go/go/build/read.go index aa7c6ee..b98c793 100644 --- a/libgo/go/go/build/read.go +++ b/libgo/go/go/build/read.go @@ -6,6 +6,7 @@ package build import ( "bufio" + "bytes" "errors" "fmt" "go/ast" @@ -28,9 +29,19 @@ type importReader struct { pos token.Position } +var bom = []byte{0xef, 0xbb, 0xbf} + func newImportReader(name string, r io.Reader) *importReader { + b := bufio.NewReader(r) + // Remove leading UTF-8 BOM. + // Per https://golang.org/ref/spec#Source_code_representation: + // a compiler may ignore a UTF-8-encoded byte order mark (U+FEFF) + // if it is the first Unicode code point in the source text. + if leadingBytes, err := b.Peek(3); err == nil && bytes.Equal(leadingBytes, bom) { + b.Discard(3) + } return &importReader{ - b: bufio.NewReader(r), + b: b, pos: token.Position{ Filename: name, Line: 1, diff --git a/libgo/go/go/build/read_test.go b/libgo/go/go/build/read_test.go index 32e6bae..1e5e1c2 100644 --- a/libgo/go/go/build/read_test.go +++ b/libgo/go/go/build/read_test.go @@ -66,6 +66,10 @@ var readGoInfoTests = []readTest{ `, "", }, + { + "\ufeff𝔻" + `package p; import "x";ℙvar x = 1`, + "", + }, } var readCommentsTests = []readTest{ @@ -82,6 +86,10 @@ var readCommentsTests = []readTest{ "", }, { + "\ufeff𝔻" + `ℙpackage p; import . "x"`, + "", + }, + { `// foo /* bar */ @@ -94,6 +102,19 @@ var readCommentsTests = []readTest{ ℙHello, world`, "", }, + { + "\ufeff𝔻" + `// foo + + /* bar */ + + /* quux */ // baz + + /*/ zot */ + + // asdf + ℙHello, world`, + "", + }, } func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, error)) { @@ -107,6 +128,11 @@ func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, erro in = tt.in[:j] + tt.in[j+len("ℙ"):] testOut = tt.in[:j] } + d := strings.Index(tt.in, "𝔻") + if d >= 0 { + in = in[:d] + in[d+len("𝔻"):] + testOut = testOut[d+len("𝔻"):] + } r := strings.NewReader(in) buf, err := read(r) if err != nil { @@ -265,6 +291,12 @@ var readEmbedTests = []struct { test:3:16:z`, }, { + "\ufeffpackage p\nimport \"embed\"\n//go:embed x y z\nvar files embed.FS", + `test:3:12:x + test:3:14:y + test:3:16:z`, + }, + { "package p\nimport \"embed\"\nvar s = \"/*\"\n//go:embed x\nvar files embed.FS", `test:4:12:x`, }, @@ -292,6 +324,10 @@ var readEmbedTests = []struct { "package p\n//go:embed x y z\nvar files embed.FS", // no import, no scan "", }, + { + "\ufeffpackage p\n//go:embed x y z\nvar files embed.FS", // no import, no scan + "", + }, } func TestReadEmbed(t *testing.T) { diff --git a/libgo/go/go/build/syslist.go b/libgo/go/go/build/syslist.go index 4f5e96c..cb7d876 100644 --- a/libgo/go/go/build/syslist.go +++ b/libgo/go/go/build/syslist.go @@ -8,4 +8,4 @@ package build // Do not remove from this list, as these are used for go/build filename matching. const goosList = "aix android darwin dragonfly freebsd hurd illumos ios js linux nacl netbsd openbsd plan9 solaris windows zos " -const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc riscv riscv64 s390 s390x sparc sparc64 wasm alpha m68k nios2 sh shbe " +const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le loong64 mips mipsle mips64 mips64le mips64p32 mips64p32le ppc riscv riscv64 s390 s390x sparc sparc64 wasm alpha m68k nios2 sh shbe " diff --git a/libgo/go/go/constant/value.go b/libgo/go/go/constant/value.go index 4641442..78cb3f8 100644 --- a/libgo/go/go/constant/value.go +++ b/libgo/go/go/constant/value.go @@ -17,6 +17,7 @@ import ( "go/token" "math" "math/big" + "math/bits" "strconv" "strings" "sync" @@ -71,6 +72,17 @@ const prec = 512 // too large (incl. infinity), that could be recorded in unknownVal. // See also #20583 and #42695 for use cases. +// Representation of values: +// +// Values of Int and Float Kind have two different representations each: int64Val +// and intVal, and ratVal and floatVal. When possible, the "smaller", respectively +// more precise (for Floats) representation is chosen. However, once a Float value +// is represented as a floatVal, any subsequent results remain floatVals (unless +// explicitly converted); i.e., no attempt is made to convert a floatVal back into +// a ratVal. The reasoning is that all representations but floatVal are mathematically +// exact, but once that precision is lost (by moving to floatVal), moving back to +// a different representation implies a precision that's not actually there. + type ( unknownVal struct{} boolVal bool @@ -262,14 +274,8 @@ func i64tor(x int64Val) ratVal { return ratVal{newRat().SetInt64(int64(x))} } func i64tof(x int64Val) floatVal { return floatVal{newFloat().SetInt64(int64(x))} } func itor(x intVal) ratVal { return ratVal{newRat().SetInt(x.val)} } func itof(x intVal) floatVal { return floatVal{newFloat().SetInt(x.val)} } - -func rtof(x ratVal) floatVal { - a := newFloat().SetInt(x.val.Num()) - b := newFloat().SetInt(x.val.Denom()) - return floatVal{a.Quo(a, b)} -} - -func vtoc(x Value) complexVal { return complexVal{x, int64Val(0)} } +func rtof(x ratVal) floatVal { return floatVal{newFloat().SetRat(x.val)} } +func vtoc(x Value) complexVal { return complexVal{x, int64Val(0)} } func makeInt(x *big.Int) Value { if x.IsInt64() { @@ -278,21 +284,15 @@ func makeInt(x *big.Int) Value { return intVal{x} } -// Permit fractions with component sizes up to maxExp -// before switching to using floating-point numbers. -const maxExp = 4 << 10 - func makeRat(x *big.Rat) Value { a := x.Num() b := x.Denom() - if a.BitLen() < maxExp && b.BitLen() < maxExp { + if smallInt(a) && smallInt(b) { // ok to remain fraction return ratVal{x} } // components too large => switch to float - fa := newFloat().SetInt(a) - fb := newFloat().SetInt(b) - return floatVal{fa.Quo(fa, fb)} + return floatVal{newFloat().SetRat(x)} } var floatVal0 = floatVal{newFloat()} @@ -305,6 +305,9 @@ func makeFloat(x *big.Float) Value { if x.IsInf() { return unknownVal{} } + // No attempt is made to "go back" to ratVal, even if possible, + // to avoid providing the illusion of a mathematically exact + // representation. return floatVal{x} } @@ -317,7 +320,7 @@ func makeComplex(re, im Value) Value { func makeFloatFromLiteral(lit string) Value { if f, ok := newFloat().SetString(lit); ok { - if smallRat(f) { + if smallFloat(f) { // ok to use rationals if f.Sign() == 0 { // Issue 20228: If the float underflowed to zero, parse just "0". @@ -336,14 +339,34 @@ func makeFloatFromLiteral(lit string) Value { return nil } -// smallRat reports whether x would lead to "reasonably"-sized fraction +// Permit fractions with component sizes up to maxExp +// before switching to using floating-point numbers. +const maxExp = 4 << 10 + +// smallInt reports whether x would lead to "reasonably"-sized fraction +// if converted to a *big.Rat. +func smallInt(x *big.Int) bool { + return x.BitLen() < maxExp +} + +// smallFloat64 reports whether x would lead to "reasonably"-sized fraction // if converted to a *big.Rat. -func smallRat(x *big.Float) bool { - if !x.IsInf() { - e := x.MantExp(nil) - return -maxExp < e && e < maxExp +func smallFloat64(x float64) bool { + if math.IsInf(x, 0) { + return false + } + _, e := math.Frexp(x) + return -maxExp < e && e < maxExp +} + +// smallFloat reports whether x would lead to "reasonably"-sized fraction +// if converted to a *big.Rat. +func smallFloat(x *big.Float) bool { + if x.IsInf() { + return false } - return false + e := x.MantExp(nil) + return -maxExp < e && e < maxExp } // ---------------------------------------------------------------------------- @@ -376,7 +399,10 @@ func MakeFloat64(x float64) Value { if math.IsInf(x, 0) || math.IsNaN(x) { return unknownVal{} } - return ratVal{newRat().SetFloat64(x + 0)} // convert -0 to 0 + if smallFloat64(x) { + return ratVal{newRat().SetFloat64(x + 0)} // convert -0 to 0 + } + return floatVal{newFloat().SetFloat64(x + 0)} } // MakeFromLiteral returns the corresponding integer, floating-point, @@ -607,7 +633,11 @@ func Make(x interface{}) Value { func BitLen(x Value) int { switch x := x.(type) { case int64Val: - return i64toi(x).val.BitLen() + u := uint64(x) + if x < 0 { + u = uint64(-x) + } + return 64 - bits.LeadingZeros64(u) case intVal: return x.val.BitLen() case unknownVal: @@ -728,7 +758,7 @@ func Num(x Value) Value { case ratVal: return makeInt(x.val.Num()) case floatVal: - if smallRat(x.val) { + if smallFloat(x.val) { r, _ := x.val.Rat(nil) return makeInt(r.Num()) } @@ -750,7 +780,7 @@ func Denom(x Value) Value { case ratVal: return makeInt(x.val.Denom()) case floatVal: - if smallRat(x.val) { + if smallFloat(x.val) { r, _ := x.val.Rat(nil) return makeInt(r.Denom()) } @@ -823,7 +853,7 @@ func ToInt(x Value) Value { // avoid creation of huge integers // (Existing tests require permitting exponents of at least 1024; // allow any value that would also be permissible as a fraction.) - if smallRat(x.val) { + if smallFloat(x.val) { i := newInt() if _, acc := x.val.Int(i); acc == big.Exact { return makeInt(i) @@ -866,14 +896,16 @@ func ToInt(x Value) Value { func ToFloat(x Value) Value { switch x := x.(type) { case int64Val: - return i64tof(x) + return i64tor(x) // x is always a small int case intVal: + if smallInt(x.val) { + return itor(x) + } return itof(x) case ratVal, floatVal: return x case complexVal: - if im := ToInt(x.im); im.Kind() == Int && Sign(im) == 0 { - // imaginary component is 0 + if Sign(x.im) == 0 { return ToFloat(x.re) } } @@ -884,13 +916,7 @@ func ToFloat(x Value) Value { // Otherwise it returns an Unknown. func ToComplex(x Value) Value { switch x := x.(type) { - case int64Val: - return vtoc(i64tof(x)) - case intVal: - return vtoc(itof(x)) - case ratVal: - return vtoc(x) - case floatVal: + case int64Val, intVal, ratVal, floatVal: return vtoc(x) case complexVal: return x @@ -1009,59 +1035,45 @@ func ord(x Value) int { // or invalid (say, nil) both results are that value. // func match(x, y Value) (_, _ Value) { - if ord(x) > ord(y) { - y, x = match(y, x) - return x, y + switch ox, oy := ord(x), ord(y); { + case ox < oy: + x, y = match0(x, y) + case ox > oy: + y, x = match0(y, x) } - // ord(x) <= ord(y) - - switch x := x.(type) { - case boolVal, *stringVal, complexVal: - return x, y + return x, y +} - case int64Val: - switch y := y.(type) { - case int64Val: - return x, y - case intVal: - return i64toi(x), y - case ratVal: - return i64tor(x), y - case floatVal: - return i64tof(x), y - case complexVal: - return vtoc(x), y - } +// match0 must only be called by match. +// Invariant: ord(x) < ord(y) +func match0(x, y Value) (_, _ Value) { + // Prefer to return the original x and y arguments when possible, + // to avoid unnecessary heap allocations. + switch y.(type) { case intVal: - switch y := y.(type) { - case intVal: - return x, y - case ratVal: - return itor(x), y - case floatVal: - return itof(x), y - case complexVal: - return vtoc(x), y + switch x1 := x.(type) { + case int64Val: + return i64toi(x1), y } - case ratVal: - switch y := y.(type) { - case ratVal: - return x, y - case floatVal: - return rtof(x), y - case complexVal: - return vtoc(x), y + switch x1 := x.(type) { + case int64Val: + return i64tor(x1), y + case intVal: + return itor(x1), y } - case floatVal: - switch y := y.(type) { - case floatVal: - return x, y - case complexVal: - return vtoc(x), y + switch x1 := x.(type) { + case int64Val: + return i64tof(x1), y + case intVal: + return itof(x1), y + case ratVal: + return rtof(x1), y } + case complexVal: + return vtoc(x), y } // force unknown and invalid values into "x position" in callers of match diff --git a/libgo/go/go/constant/value_test.go b/libgo/go/go/constant/value_test.go index 2866774..91ad0b0 100644 --- a/libgo/go/go/constant/value_test.go +++ b/libgo/go/go/constant/value_test.go @@ -706,3 +706,24 @@ func BenchmarkStringAdd(b *testing.B) { }) } } + +var bitLenTests = []struct { + val int64 + want int +}{ + {0, 0}, + {1, 1}, + {-16, 5}, + {1 << 61, 62}, + {1 << 62, 63}, + {-1 << 62, 63}, + {-1 << 63, 64}, +} + +func TestBitLen(t *testing.T) { + for _, test := range bitLenTests { + if got := BitLen(MakeInt64(test.val)); got != test.want { + t.Errorf("%v: got %v, want %v", test.val, got, test.want) + } + } +} diff --git a/libgo/go/go/doc/example.go b/libgo/go/go/doc/example.go index 125fd53..274000c 100644 --- a/libgo/go/go/doc/example.go +++ b/libgo/go/go/doc/example.go @@ -237,7 +237,10 @@ func playExample(file *ast.File, f *ast.FuncDecl) *ast.File { } } - ast.Inspect(d.Body, inspectFunc) + // Functions might not have a body. See #42706. + if d.Body != nil { + ast.Inspect(d.Body, inspectFunc) + } case *ast.GenDecl: for _, spec := range d.Specs { switch s := spec.(type) { diff --git a/libgo/go/go/doc/example_test.go b/libgo/go/go/doc/example_test.go index 7c96f03..cf1b702 100644 --- a/libgo/go/go/doc/example_test.go +++ b/libgo/go/go/doc/example_test.go @@ -352,6 +352,25 @@ func main() { } ` +const exampleWholeFileExternalFunction = `package foo_test + +func foo(int) + +func Example() { + foo(42) + // Output: +} +` + +const exampleWholeFileExternalFunctionOutput = `package main + +func foo(int) + +func main() { + foo(42) +} +` + var exampleWholeFileTestCases = []struct { Title, Source, Play, Output string }{ @@ -367,6 +386,12 @@ var exampleWholeFileTestCases = []struct { exampleWholeFileFunctionOutput, "Hello, world!\n", }, + { + "ExternalFunction", + exampleWholeFileExternalFunction, + exampleWholeFileExternalFunctionOutput, + "", + }, } func TestExamplesWholeFile(t *testing.T) { diff --git a/libgo/go/go/doc/headscan.go b/libgo/go/go/doc/headscan.go index fe26a0e..28cb84f 100644 --- a/libgo/go/go/doc/headscan.go +++ b/libgo/go/go/doc/headscan.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore /* diff --git a/libgo/go/go/format/format_test.go b/libgo/go/go/format/format_test.go index 27f4c74..6cc0278 100644 --- a/libgo/go/go/format/format_test.go +++ b/libgo/go/go/format/format_test.go @@ -151,6 +151,10 @@ var tests = []string{ // erroneous programs "ERROR1 + 2 +", "ERRORx := 0", + + // build comments + "// copyright\n\n//go:build x\n\npackage p\n", + "// copyright\n\n//go:build x\n// +build x\n\npackage p\n", } func String(s string) (string, error) { diff --git a/libgo/go/go/internal/gccgoimporter/gccgoinstallation_test.go b/libgo/go/go/internal/gccgoimporter/gccgoinstallation_test.go index 745ef90..5484ca5 100644 --- a/libgo/go/go/internal/gccgoimporter/gccgoinstallation_test.go +++ b/libgo/go/go/internal/gccgoimporter/gccgoinstallation_test.go @@ -188,7 +188,7 @@ func TestInstallationImporter(t *testing.T) { {pkgpath: "io", name: "ReadWriter", want: "type ReadWriter interface{Reader; Writer}"}, {pkgpath: "math", name: "Pi", want: "const Pi untyped float"}, {pkgpath: "math", name: "Sin", want: "func Sin(x float64) float64"}, - {pkgpath: "sort", name: "Ints", want: "func Ints(a []int)"}, + {pkgpath: "sort", name: "Search", want: "func Search(n int, f func(int) bool) int"}, {pkgpath: "unsafe", name: "Pointer", want: "type Pointer"}, } { runImporterTest(t, imp, nil, &test) diff --git a/libgo/go/go/internal/gccgoimporter/importer_test.go b/libgo/go/go/internal/gccgoimporter/importer_test.go index 35240c8..8a7ee1a 100644 --- a/libgo/go/go/internal/gccgoimporter/importer_test.go +++ b/libgo/go/go/internal/gccgoimporter/importer_test.go @@ -94,7 +94,7 @@ var importerTests = [...]importerTest{ {pkgpath: "nointerface", name: "I", want: "type I int"}, {pkgpath: "issue29198", name: "FooServer", gccgoVersion: 7, want: "type FooServer struct{FooServer *FooServer; user string; ctx context.Context}"}, {pkgpath: "issue30628", name: "Apple", want: "type Apple struct{hey sync.RWMutex; x int; RQ [517]struct{Count uintptr; NumBytes uintptr; Last uintptr}}"}, - {pkgpath: "issue31540", name: "S", gccgoVersion: 7, want: "type S struct{b int; map[Y]Z}"}, + {pkgpath: "issue31540", name: "S", gccgoVersion: 7, want: "type S struct{b int; map[Y]Z}"}, // should want "type S struct{b int; A2}" (issue #44410) {pkgpath: "issue34182", name: "T1", want: "type T1 struct{f *T2}"}, {pkgpath: "notinheap", name: "S", want: "type S struct{}"}, } @@ -149,21 +149,11 @@ func TestObjImporter(t *testing.T) { } t.Logf("gccgo version %d.%d", major, minor) - tmpdir, err := os.MkdirTemp("", "TestObjImporter") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) - + tmpdir := t.TempDir() initmap := make(map[*types.Package]InitData) imp := GetImporter([]string{tmpdir}, initmap) - artmpdir, err := os.MkdirTemp("", "TestObjImporter") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(artmpdir) - + artmpdir := t.TempDir() arinitmap := make(map[*types.Package]InitData) arimp := GetImporter([]string{artmpdir}, arinitmap) diff --git a/libgo/go/go/internal/gcimporter/gcimporter.go b/libgo/go/go/internal/gcimporter/gcimporter.go index b74daca..73cf633 100644 --- a/libgo/go/go/internal/gcimporter/gcimporter.go +++ b/libgo/go/go/internal/gcimporter/gcimporter.go @@ -145,17 +145,14 @@ func Import(fset *token.FileSet, packages map[string]*types.Package, path, srcDi err = fmt.Errorf("import %q: old textual export format no longer supported (recompile library)", path) case "$$B\n": - var data []byte - data, err = io.ReadAll(buf) - if err != nil { - break - } + var exportFormat byte + exportFormat, err = buf.ReadByte() // The indexed export format starts with an 'i'; the older // binary export format starts with a 'c', 'd', or 'v' // (from "version"). Select appropriate importer. - if len(data) > 0 && data[0] == 'i' { - _, pkg, err = iImportData(fset, packages, data[1:], id) + if err == nil && exportFormat == 'i' { + pkg, err = iImportData(fset, packages, buf, id) } else { err = fmt.Errorf("import %q: old binary export format no longer supported (recompile library)", path) } diff --git a/libgo/go/go/internal/gcimporter/iimport.go b/libgo/go/go/internal/gcimporter/iimport.go index c59dd16..76d47d0 100644 --- a/libgo/go/go/internal/gcimporter/iimport.go +++ b/libgo/go/go/internal/gcimporter/iimport.go @@ -8,6 +8,7 @@ package gcimporter import ( + "bufio" "bytes" "encoding/binary" "fmt" @@ -15,11 +16,12 @@ import ( "go/token" "go/types" "io" + "math/big" "sort" ) type intReader struct { - *bytes.Reader + *bufio.Reader path string } @@ -60,7 +62,7 @@ const ( // and returns the number of bytes consumed and a reference to the package. // If the export data version is not recognized or the format is otherwise // compromised, an error is returned. -func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) { +func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataReader *bufio.Reader, path string) (pkg *types.Package, err error) { const currentVersion = 1 version := int64(-1) defer func() { @@ -73,7 +75,7 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data [] } }() - r := &intReader{bytes.NewReader(data), path} + r := &intReader{dataReader, path} version = int64(r.uint64()) switch version { @@ -85,10 +87,12 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data [] sLen := int64(r.uint64()) dLen := int64(r.uint64()) - whence, _ := r.Seek(0, io.SeekCurrent) - stringData := data[whence : whence+sLen] - declData := data[whence+sLen : whence+sLen+dLen] - r.Seek(sLen+dLen, io.SeekCurrent) + data := make([]byte, sLen+dLen) + if _, err := io.ReadFull(r, data); err != nil { + errorf("cannot read %d bytes of stringData and declData: %s", len(data), err) + } + stringData := data[:sLen] + declData := data[sLen:] p := iimporter{ ipath: path, @@ -164,9 +168,7 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data [] // package was imported completely and without errors localpkg.MarkComplete() - - consumed, _ := r.Seek(0, io.SeekCurrent) - return int(consumed), localpkg, nil + return localpkg, nil } type iimporter struct { @@ -320,7 +322,9 @@ func (r *importReader) value() (typ types.Type, val constant.Value) { val = constant.MakeString(r.string()) case types.IsInteger: - val = r.mpint(b) + var x big.Int + r.mpint(&x, b) + val = constant.Make(&x) case types.IsFloat: val = r.mpfloat(b) @@ -365,8 +369,8 @@ func intSize(b *types.Basic) (signed bool, maxBytes uint) { return } -func (r *importReader) mpint(b *types.Basic) constant.Value { - signed, maxBytes := intSize(b) +func (r *importReader) mpint(x *big.Int, typ *types.Basic) { + signed, maxBytes := intSize(typ) maxSmall := 256 - maxBytes if signed { @@ -385,7 +389,8 @@ func (r *importReader) mpint(b *types.Basic) constant.Value { v = ^v } } - return constant.MakeInt64(v) + x.SetInt64(v) + return } v := -n @@ -395,39 +400,23 @@ func (r *importReader) mpint(b *types.Basic) constant.Value { if v < 1 || uint(v) > maxBytes { errorf("weird decoding: %v, %v => %v", n, signed, v) } - - buf := make([]byte, v) - io.ReadFull(&r.declReader, buf) - - // convert to little endian - // TODO(gri) go/constant should have a more direct conversion function - // (e.g., once it supports a big.Float based implementation) - for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 { - buf[i], buf[j] = buf[j], buf[i] - } - - x := constant.MakeFromBytes(buf) + b := make([]byte, v) + io.ReadFull(&r.declReader, b) + x.SetBytes(b) if signed && n&1 != 0 { - x = constant.UnaryOp(token.SUB, x, 0) + x.Neg(x) } - return x } -func (r *importReader) mpfloat(b *types.Basic) constant.Value { - x := r.mpint(b) - if constant.Sign(x) == 0 { - return x +func (r *importReader) mpfloat(typ *types.Basic) constant.Value { + var mant big.Int + r.mpint(&mant, typ) + var f big.Float + f.SetInt(&mant) + if f.Sign() != 0 { + f.SetMantExp(&f, int(r.int64())) } - - exp := r.int64() - switch { - case exp > 0: - x = constant.Shift(x, token.SHL, uint(exp)) - case exp < 0: - d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp)) - x = constant.BinaryOp(x, token.QUO, d) - } - return x + return constant.Make(&f) } func (r *importReader) ident() string { diff --git a/libgo/go/go/internal/srcimporter/srcimporter.go b/libgo/go/go/internal/srcimporter/srcimporter.go index 863b672b..c0172ba 100644 --- a/libgo/go/go/internal/srcimporter/srcimporter.go +++ b/libgo/go/go/internal/srcimporter/srcimporter.go @@ -30,7 +30,7 @@ type Importer struct { packages map[string]*types.Package } -// NewImporter returns a new Importer for the given context, file set, and map +// New returns a new Importer for the given context, file set, and map // of packages. The context is used to resolve import paths to package paths, // and identifying the files belonging to the package. If the context provides // non-nil file system functions, they are used instead of the regular package diff --git a/libgo/go/go/internal/typeparams/common.go b/libgo/go/go/internal/typeparams/common.go new file mode 100644 index 0000000..47b8f7c --- /dev/null +++ b/libgo/go/go/internal/typeparams/common.go @@ -0,0 +1,13 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package typeparams provides functions to work with type parameter data +// stored in the AST, while these AST changes are guarded by a build +// constraint. +package typeparams + +// DisallowParsing is the numeric value of a parsing mode that disallows type +// parameters. This only matters if the typeparams experiment is active, and +// may be used for running tests that disallow generics. +const DisallowParsing = 1 << 30 diff --git a/libgo/go/go/internal/typeparams/notypeparams.go b/libgo/go/go/internal/typeparams/notypeparams.go new file mode 100644 index 0000000..2ceafaa --- /dev/null +++ b/libgo/go/go/internal/typeparams/notypeparams.go @@ -0,0 +1,40 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !typeparams +// +build !typeparams + +package typeparams + +import ( + "go/ast" +) + +const Enabled = false + +func PackExpr(list []ast.Expr) ast.Expr { + switch len(list) { + case 1: + return list[0] + default: + // The parser should not attempt to pack multiple expressions into an + // IndexExpr if type params are disabled. + panic("multiple index expressions are unsupported without type params") + } +} + +func UnpackExpr(expr ast.Expr) []ast.Expr { + return []ast.Expr{expr} +} + +func IsListExpr(n ast.Node) bool { + return false +} + +func Get(ast.Node) *ast.FieldList { + return nil +} + +func Set(node ast.Node, params *ast.FieldList) { +} diff --git a/libgo/go/go/internal/typeparams/typeparams.go b/libgo/go/go/internal/typeparams/typeparams.go new file mode 100644 index 0000000..871e95d --- /dev/null +++ b/libgo/go/go/internal/typeparams/typeparams.go @@ -0,0 +1,69 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build typeparams +// +build typeparams + +package typeparams + +import ( + "fmt" + "go/ast" +) + +const Enabled = true + +func PackExpr(list []ast.Expr) ast.Expr { + switch len(list) { + case 0: + // Return an empty ListExpr here, rather than nil, as IndexExpr.Index must + // never be nil. + // TODO(rFindley) would a BadExpr be more appropriate here? + return &ast.ListExpr{} + case 1: + return list[0] + default: + return &ast.ListExpr{ElemList: list} + } +} + +// TODO(gri) Should find a more efficient solution that doesn't +// require introduction of a new slice for simple +// expressions. +func UnpackExpr(x ast.Expr) []ast.Expr { + if x, _ := x.(*ast.ListExpr); x != nil { + return x.ElemList + } + if x != nil { + return []ast.Expr{x} + } + return nil +} + +func IsListExpr(n ast.Node) bool { + _, ok := n.(*ast.ListExpr) + return ok +} + +func Get(n ast.Node) *ast.FieldList { + switch n := n.(type) { + case *ast.TypeSpec: + return n.TParams + case *ast.FuncType: + return n.TParams + default: + panic(fmt.Sprintf("node type %T has no type parameters", n)) + } +} + +func Set(n ast.Node, params *ast.FieldList) { + switch n := n.(type) { + case *ast.TypeSpec: + n.TParams = params + case *ast.FuncType: + n.TParams = params + default: + panic(fmt.Sprintf("node type %T has no type parameters", n)) + } +} diff --git a/libgo/go/go/parser/error_test.go b/libgo/go/go/parser/error_test.go index 358a844..f4f0a52 100644 --- a/libgo/go/go/parser/error_test.go +++ b/libgo/go/go/parser/error_test.go @@ -23,6 +23,7 @@ package parser import ( + "go/internal/typeparams" "go/scanner" "go/token" "os" @@ -89,7 +90,7 @@ func expectedErrors(fset *token.FileSet, filename string, src []byte) map[token. if s[1] == "HERE" { pos = here } - errors[pos] = string(s[2]) + errors[pos] = s[2] } case token.SEMICOLON: // don't use the position of auto-inserted (invisible) semicolons @@ -114,6 +115,7 @@ func expectedErrors(fset *token.FileSet, filename string, src []byte) map[token. // of found errors and reports discrepancies. // func compareErrors(t *testing.T, fset *token.FileSet, expected map[token.Pos]string, found scanner.ErrorList) { + t.Helper() for _, error := range found { // error.Pos is a token.Position, but we want // a token.Pos so we can do a map lookup @@ -149,7 +151,8 @@ func compareErrors(t *testing.T, fset *token.FileSet, expected map[token.Pos]str } } -func checkErrors(t *testing.T, filename string, input interface{}) { +func checkErrors(t *testing.T, filename string, input interface{}, mode Mode, expectErrors bool) { + t.Helper() src, err := readSource(filename, input) if err != nil { t.Error(err) @@ -157,7 +160,7 @@ func checkErrors(t *testing.T, filename string, input interface{}) { } fset := token.NewFileSet() - _, err = ParseFile(fset, filename, src, DeclarationErrors|AllErrors) + _, err = ParseFile(fset, filename, src, mode) found, ok := err.(scanner.ErrorList) if err != nil && !ok { t.Error(err) @@ -165,9 +168,12 @@ func checkErrors(t *testing.T, filename string, input interface{}) { } found.RemoveMultiples() - // we are expecting the following errors - // (collect these after parsing a file so that it is found in the file set) - expected := expectedErrors(fset, filename, src) + expected := map[token.Pos]string{} + if expectErrors { + // we are expecting the following errors + // (collect these after parsing a file so that it is found in the file set) + expected = expectedErrors(fset, filename, src) + } // verify errors returned by the parser compareErrors(t, fset, expected, found) @@ -180,8 +186,16 @@ func TestErrors(t *testing.T) { } for _, d := range list { name := d.Name() - if !d.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".src") { - checkErrors(t, filepath.Join(testdata, name), nil) + if !d.IsDir() && !strings.HasPrefix(name, ".") && (strings.HasSuffix(name, ".src") || strings.HasSuffix(name, ".go2")) { + mode := DeclarationErrors | AllErrors + if strings.HasSuffix(name, ".go2") { + if !typeparams.Enabled { + continue + } + } else { + mode |= typeparams.DisallowParsing + } + checkErrors(t, filepath.Join(testdata, name), nil, mode, true) } } } diff --git a/libgo/go/go/parser/interface.go b/libgo/go/go/parser/interface.go index 56ff5fe..85486d2 100644 --- a/libgo/go/go/parser/interface.go +++ b/libgo/go/go/parser/interface.go @@ -49,13 +49,14 @@ func readSource(filename string, src interface{}) ([]byte, error) { type Mode uint const ( - PackageClauseOnly Mode = 1 << iota // stop parsing after package clause - ImportsOnly // stop parsing after import declarations - ParseComments // parse comments and add them to AST - Trace // print a trace of parsed productions - DeclarationErrors // report declaration errors - SpuriousErrors // same as AllErrors, for backward-compatibility - AllErrors = SpuriousErrors // report all errors (not just the first 10 on different lines) + PackageClauseOnly Mode = 1 << iota // stop parsing after package clause + ImportsOnly // stop parsing after import declarations + ParseComments // parse comments and add them to AST + Trace // print a trace of parsed productions + DeclarationErrors // report declaration errors + SpuriousErrors // same as AllErrors, for backward-compatibility + SkipObjectResolution // don't resolve identifiers to objects - see ParseFile + AllErrors = SpuriousErrors // report all errors (not just the first 10 on different lines) ) // ParseFile parses the source code of a single Go source file and returns @@ -68,8 +69,12 @@ const ( // If src == nil, ParseFile parses the file specified by filename. // // The mode parameter controls the amount of source text parsed and other -// optional parser functionality. Position information is recorded in the -// file set fset, which must not be nil. +// optional parser functionality. If the SkipObjectResolution mode bit is set, +// the object resolution phase of parsing will be skipped, causing File.Scope, +// File.Unresolved, and all Ident.Obj fields to be nil. +// +// Position information is recorded in the file set fset, which must not be +// nil. // // If the source couldn't be read, the returned AST is nil and the error // indicates the specific failure. If the source was read but syntax @@ -208,15 +213,7 @@ func ParseExprFrom(fset *token.FileSet, filename string, src interface{}, mode M // parse expr p.init(fset, filename, text, mode) - // Set up pkg-level scopes to avoid nil-pointer errors. - // This is not needed for a correct expression x as the - // parser will be ok with a nil topScope, but be cautious - // in case of an erroneous x. - p.openScope() - p.pkgScope = p.topScope expr = p.parseRhsOrType() - p.closeScope() - assert(p.topScope == nil, "unbalanced scopes") // If a semicolon was inserted, consume it; // report an error if there's more tokens. diff --git a/libgo/go/go/parser/parser.go b/libgo/go/go/parser/parser.go index 31a7398..f10c865 100644 --- a/libgo/go/go/parser/parser.go +++ b/libgo/go/go/parser/parser.go @@ -19,6 +19,7 @@ package parser import ( "fmt" "go/ast" + "go/internal/typeparams" "go/scanner" "go/token" "strconv" @@ -34,7 +35,7 @@ type parser struct { // Tracing/debugging mode Mode // parsing mode - trace bool // == (mode & Trace != 0) + trace bool // == (mode&Trace != 0) indent int // indentation used for tracing output // Comments @@ -58,16 +59,7 @@ type parser struct { exprLev int // < 0: in control clause, >= 0: in expression inRhs bool // if set, the parser is parsing a rhs expression - // Ordinary identifier scopes - pkgScope *ast.Scope // pkgScope.Outer == nil - topScope *ast.Scope // top-most scope; may be pkgScope - unresolved []*ast.Ident // unresolved identifiers - imports []*ast.ImportSpec // list of imports - - // Label scopes - // (maintained by open/close LabelScope) - labelScope *ast.Scope // label scope for current function - targetStack [][]*ast.Ident // stack of unresolved labels + imports []*ast.ImportSpec // list of imports } func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mode) { @@ -81,129 +73,11 @@ func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mod p.mode = mode p.trace = mode&Trace != 0 // for convenience (p.trace is used frequently) - p.next() } -// ---------------------------------------------------------------------------- -// Scoping support - -func (p *parser) openScope() { - p.topScope = ast.NewScope(p.topScope) -} - -func (p *parser) closeScope() { - p.topScope = p.topScope.Outer -} - -func (p *parser) openLabelScope() { - p.labelScope = ast.NewScope(p.labelScope) - p.targetStack = append(p.targetStack, nil) -} - -func (p *parser) closeLabelScope() { - // resolve labels - n := len(p.targetStack) - 1 - scope := p.labelScope - for _, ident := range p.targetStack[n] { - ident.Obj = scope.Lookup(ident.Name) - if ident.Obj == nil && p.mode&DeclarationErrors != 0 { - p.error(ident.Pos(), fmt.Sprintf("label %s undefined", ident.Name)) - } - } - // pop label scope - p.targetStack = p.targetStack[0:n] - p.labelScope = p.labelScope.Outer -} - -func (p *parser) declare(decl, data interface{}, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) { - for _, ident := range idents { - assert(ident.Obj == nil, "identifier already declared or resolved") - obj := ast.NewObj(kind, ident.Name) - // remember the corresponding declaration for redeclaration - // errors and global variable resolution/typechecking phase - obj.Decl = decl - obj.Data = data - ident.Obj = obj - if ident.Name != "_" { - if alt := scope.Insert(obj); alt != nil && p.mode&DeclarationErrors != 0 { - prevDecl := "" - if pos := alt.Pos(); pos.IsValid() { - prevDecl = fmt.Sprintf("\n\tprevious declaration at %s", p.file.Position(pos)) - } - p.error(ident.Pos(), fmt.Sprintf("%s redeclared in this block%s", ident.Name, prevDecl)) - } - } - } -} - -func (p *parser) shortVarDecl(decl *ast.AssignStmt, list []ast.Expr) { - // Go spec: A short variable declaration may redeclare variables - // provided they were originally declared in the same block with - // the same type, and at least one of the non-blank variables is new. - n := 0 // number of new variables - for _, x := range list { - if ident, isIdent := x.(*ast.Ident); isIdent { - assert(ident.Obj == nil, "identifier already declared or resolved") - obj := ast.NewObj(ast.Var, ident.Name) - // remember corresponding assignment for other tools - obj.Decl = decl - ident.Obj = obj - if ident.Name != "_" { - if alt := p.topScope.Insert(obj); alt != nil { - ident.Obj = alt // redeclaration - } else { - n++ // new declaration - } - } - } else { - p.errorExpected(x.Pos(), "identifier on left side of :=") - } - } - if n == 0 && p.mode&DeclarationErrors != 0 { - p.error(list[0].Pos(), "no new variables on left side of :=") - } -} - -// The unresolved object is a sentinel to mark identifiers that have been added -// to the list of unresolved identifiers. The sentinel is only used for verifying -// internal consistency. -var unresolved = new(ast.Object) - -// If x is an identifier, tryResolve attempts to resolve x by looking up -// the object it denotes. If no object is found and collectUnresolved is -// set, x is marked as unresolved and collected in the list of unresolved -// identifiers. -// -func (p *parser) tryResolve(x ast.Expr, collectUnresolved bool) { - // nothing to do if x is not an identifier or the blank identifier - ident, _ := x.(*ast.Ident) - if ident == nil { - return - } - assert(ident.Obj == nil, "identifier already declared or resolved") - if ident.Name == "_" { - return - } - // try to resolve the identifier - for s := p.topScope; s != nil; s = s.Outer { - if obj := s.Lookup(ident.Name); obj != nil { - ident.Obj = obj - return - } - } - // all local scopes are known, so any unresolved identifier - // must be found either in the file scope, package scope - // (perhaps in another file), or universe scope --- collect - // them so that they can be resolved later - if collectUnresolved { - ident.Obj = unresolved - p.unresolved = append(p.unresolved, ident) - } -} - -func (p *parser) resolve(x ast.Expr) { - p.tryResolve(x, true) +func (p *parser) parseTypeParams() bool { + return typeparams.Enabled && p.mode&typeparams.DisallowParsing == 0 } // ---------------------------------------------------------------------------- @@ -241,7 +115,7 @@ func (p *parser) next0() { // Because of one-token look-ahead, print the previous token // when tracing as it provides a more readable output. The // very first token (!p.pos.IsValid()) is not initialized - // (it is token.ILLEGAL), so don't print it . + // (it is token.ILLEGAL), so don't print it. if p.trace && p.pos.IsValid() { s := p.tok.String() switch { @@ -352,6 +226,10 @@ func (p *parser) next() { type bailout struct{} func (p *parser) error(pos token.Pos, msg string) { + if p.trace { + defer un(trace(p, "error: "+msg)) + } + epos := p.file.Position(pos) // If AllErrors is not set, discard errors reported on the same line @@ -573,52 +451,24 @@ func (p *parser) parseIdentList() (list []*ast.Ident) { // Common productions // If lhs is set, result list elements which are identifiers are not resolved. -func (p *parser) parseExprList(lhs bool) (list []ast.Expr) { +func (p *parser) parseExprList() (list []ast.Expr) { if p.trace { defer un(trace(p, "ExpressionList")) } - list = append(list, p.checkExpr(p.parseExpr(lhs))) + list = append(list, p.checkExpr(p.parseExpr())) for p.tok == token.COMMA { p.next() - list = append(list, p.checkExpr(p.parseExpr(lhs))) + list = append(list, p.checkExpr(p.parseExpr())) } return } -func (p *parser) parseLhsList() []ast.Expr { +func (p *parser) parseList(inRhs bool) []ast.Expr { old := p.inRhs - p.inRhs = false - list := p.parseExprList(true) - switch p.tok { - case token.DEFINE: - // lhs of a short variable declaration - // but doesn't enter scope until later: - // caller must call p.shortVarDecl(p.makeIdentList(list)) - // at appropriate time. - case token.COLON: - // lhs of a label declaration or a communication clause of a select - // statement (parseLhsList is not called when parsing the case clause - // of a switch statement): - // - labels are declared by the caller of parseLhsList - // - for communication clauses, if there is a stand-alone identifier - // followed by a colon, we have a syntax error; there is no need - // to resolve the identifier in that case - default: - // identifiers must be declared elsewhere - for _, x := range list { - p.resolve(x) - } - } - p.inRhs = old - return list -} - -func (p *parser) parseRhsList() []ast.Expr { - old := p.inRhs - p.inRhs = true - list := p.parseExprList(false) + p.inRhs = inRhs + list := p.parseExprList() p.inRhs = old return list } @@ -631,7 +481,7 @@ func (p *parser) parseType() ast.Expr { defer un(trace(p, "Type")) } - typ := p.tryType() + typ := p.tryIdentOrType() if typ == nil { pos := p.pos @@ -643,19 +493,32 @@ func (p *parser) parseType() ast.Expr { return typ } +func (p *parser) parseQualifiedIdent(ident *ast.Ident) ast.Expr { + if p.trace { + defer un(trace(p, "QualifiedIdent")) + } + + typ := p.parseTypeName(ident) + if p.tok == token.LBRACK && p.parseTypeParams() { + typ = p.parseTypeInstance(typ) + } + + return typ +} + // If the result is an identifier, it is not resolved. -func (p *parser) parseTypeName() ast.Expr { +func (p *parser) parseTypeName(ident *ast.Ident) ast.Expr { if p.trace { defer un(trace(p, "TypeName")) } - ident := p.parseIdent() - // don't resolve ident yet - it may be a parameter or field name + if ident == nil { + ident = p.parseIdent() + } if p.tok == token.PERIOD { // ident is a package name p.next() - p.resolve(ident) sel := p.parseIdent() return &ast.SelectorExpr{X: ident, Sel: sel} } @@ -663,12 +526,11 @@ func (p *parser) parseTypeName() ast.Expr { return ident } -func (p *parser) parseArrayType() ast.Expr { +func (p *parser) parseArrayLen() ast.Expr { if p.trace { - defer un(trace(p, "ArrayType")) + defer un(trace(p, "ArrayLen")) } - lbrack := p.expect(token.LBRACK) p.exprLev++ var len ast.Expr // always permit ellipsis for more fault-tolerant parsing @@ -679,66 +541,111 @@ func (p *parser) parseArrayType() ast.Expr { len = p.parseRhs() } p.exprLev-- - p.expect(token.RBRACK) - elt := p.parseType() - return &ast.ArrayType{Lbrack: lbrack, Len: len, Elt: elt} + return len } -func (p *parser) makeIdentList(list []ast.Expr) []*ast.Ident { - idents := make([]*ast.Ident, len(list)) - for i, x := range list { - ident, isIdent := x.(*ast.Ident) - if !isIdent { - if _, isBad := x.(*ast.BadExpr); !isBad { - // only report error if it's a new one - p.errorExpected(x.Pos(), "identifier") +func (p *parser) parseArrayFieldOrTypeInstance(x *ast.Ident) (*ast.Ident, ast.Expr) { + if p.trace { + defer un(trace(p, "ArrayFieldOrTypeInstance")) + } + + // TODO(gri) Should we allow a trailing comma in a type argument + // list such as T[P,]? (We do in parseTypeInstance). + lbrack := p.expect(token.LBRACK) + var args []ast.Expr + var firstComma token.Pos + // TODO(rfindley): consider changing parseRhsOrType so that this function variable + // is not needed. + argparser := p.parseRhsOrType + if !p.parseTypeParams() { + argparser = p.parseRhs + } + if p.tok != token.RBRACK { + p.exprLev++ + args = append(args, argparser()) + for p.tok == token.COMMA { + if !firstComma.IsValid() { + firstComma = p.pos } - ident = &ast.Ident{NamePos: x.Pos(), Name: "_"} + p.next() + args = append(args, argparser()) } - idents[i] = ident + p.exprLev-- } - return idents + rbrack := p.expect(token.RBRACK) + + if len(args) == 0 { + // x []E + elt := p.parseType() + return x, &ast.ArrayType{Lbrack: lbrack, Elt: elt} + } + + // x [P]E or x[P] + if len(args) == 1 { + elt := p.tryIdentOrType() + if elt != nil { + // x [P]E + return x, &ast.ArrayType{Lbrack: lbrack, Len: args[0], Elt: elt} + } + if !p.parseTypeParams() { + p.error(rbrack, "missing element type in array type expression") + return nil, &ast.BadExpr{From: args[0].Pos(), To: args[0].End()} + } + } + + if !p.parseTypeParams() { + p.error(firstComma, "expected ']', found ','") + return x, &ast.BadExpr{From: args[0].Pos(), To: args[len(args)-1].End()} + } + + // x[P], x[P1, P2], ... + return nil, &ast.IndexExpr{X: x, Lbrack: lbrack, Index: typeparams.PackExpr(args), Rbrack: rbrack} } -func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field { +func (p *parser) parseFieldDecl() *ast.Field { if p.trace { defer un(trace(p, "FieldDecl")) } doc := p.leadComment - // 1st FieldDecl - // A type name used as an anonymous field looks like a field identifier. - var list []ast.Expr - for { - list = append(list, p.parseVarType(false)) - if p.tok != token.COMMA { - break + var names []*ast.Ident + var typ ast.Expr + if p.tok == token.IDENT { + name := p.parseIdent() + if p.tok == token.PERIOD || p.tok == token.STRING || p.tok == token.SEMICOLON || p.tok == token.RBRACE { + // embedded type + typ = name + if p.tok == token.PERIOD { + typ = p.parseQualifiedIdent(name) + } + } else { + // name1, name2, ... T + names = []*ast.Ident{name} + for p.tok == token.COMMA { + p.next() + names = append(names, p.parseIdent()) + } + // Careful dance: We don't know if we have an embedded instantiated + // type T[P1, P2, ...] or a field T of array type []E or [P]E. + if len(names) == 1 && p.tok == token.LBRACK { + name, typ = p.parseArrayFieldOrTypeInstance(name) + if name == nil { + names = nil + } + } else { + // T P + typ = p.parseType() + } } - p.next() - } - - typ := p.tryVarType(false) - - // analyze case - var idents []*ast.Ident - if typ != nil { - // IdentifierList Type - idents = p.makeIdentList(list) } else { - // ["*"] TypeName (AnonymousField) - typ = list[0] // we always have at least one element - if n := len(list); n > 1 { - p.errorExpected(p.pos, "type") - typ = &ast.BadExpr{From: p.pos, To: p.pos} - } else if !isTypeName(deref(typ)) { - p.errorExpected(typ.Pos(), "anonymous field") - typ = &ast.BadExpr{From: typ.Pos(), To: p.safePos(typ.End())} - } + // embedded, possibly generic type + // (using the enclosing parentheses to distinguish it from a named field declaration) + // TODO(rFindley) confirm that this doesn't allow parenthesized embedded type + typ = p.parseType() } - // Tag var tag *ast.BasicLit if p.tok == token.STRING { tag = &ast.BasicLit{ValuePos: p.pos, Kind: p.tok, Value: p.lit} @@ -747,10 +654,7 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field { p.expectSemi() // call before accessing p.linecomment - field := &ast.Field{Doc: doc, Names: idents, Type: typ, Tag: tag, Comment: p.lineComment} - p.declare(field, nil, scope, ast.Var, idents...) - p.resolve(typ) - + field := &ast.Field{Doc: doc, Names: names, Type: typ, Tag: tag, Comment: p.lineComment} return field } @@ -761,13 +665,12 @@ func (p *parser) parseStructType() *ast.StructType { pos := p.expect(token.STRUCT) lbrace := p.expect(token.LBRACE) - scope := ast.NewScope(nil) // struct scope var list []*ast.Field for p.tok == token.IDENT || p.tok == token.MUL || p.tok == token.LPAREN { // a field declaration cannot start with a '(' but we accept // it here for more robust parsing and better error messages // (parseFieldDecl will check and complain if necessary) - list = append(list, p.parseFieldDecl(scope)) + list = append(list, p.parseFieldDecl()) } rbrace := p.expect(token.RBRACE) @@ -792,119 +695,232 @@ func (p *parser) parsePointerType() *ast.StarExpr { return &ast.StarExpr{Star: star, X: base} } -// If the result is an identifier, it is not resolved. -func (p *parser) tryVarType(isParam bool) ast.Expr { - if isParam && p.tok == token.ELLIPSIS { - pos := p.pos - p.next() - typ := p.tryIdentOrType() // don't use parseType so we can provide better error message - if typ != nil { - p.resolve(typ) - } else { - p.error(pos, "'...' parameter is missing type") - typ = &ast.BadExpr{From: pos, To: p.pos} - } - return &ast.Ellipsis{Ellipsis: pos, Elt: typ} +func (p *parser) parseDotsType() *ast.Ellipsis { + if p.trace { + defer un(trace(p, "DotsType")) } - return p.tryIdentOrType() + + pos := p.expect(token.ELLIPSIS) + elt := p.parseType() + + return &ast.Ellipsis{Ellipsis: pos, Elt: elt} } -// If the result is an identifier, it is not resolved. -func (p *parser) parseVarType(isParam bool) ast.Expr { - typ := p.tryVarType(isParam) - if typ == nil { - pos := p.pos - p.errorExpected(pos, "type") - p.next() // make progress - typ = &ast.BadExpr{From: pos, To: p.pos} +type field struct { + name *ast.Ident + typ ast.Expr +} + +func (p *parser) parseParamDecl(name *ast.Ident) (f field) { + // TODO(rFindley) compare with parser.paramDeclOrNil in the syntax package + if p.trace { + defer un(trace(p, "ParamDeclOrNil")) } - return typ + + ptok := p.tok + if name != nil { + p.tok = token.IDENT // force token.IDENT case in switch below + } + + switch p.tok { + case token.IDENT: + if name != nil { + f.name = name + p.tok = ptok + } else { + f.name = p.parseIdent() + } + switch p.tok { + case token.IDENT, token.MUL, token.ARROW, token.FUNC, token.CHAN, token.MAP, token.STRUCT, token.INTERFACE, token.LPAREN: + // name type + f.typ = p.parseType() + + case token.LBRACK: + // name[type1, type2, ...] or name []type or name [len]type + f.name, f.typ = p.parseArrayFieldOrTypeInstance(f.name) + + case token.ELLIPSIS: + // name ...type + f.typ = p.parseDotsType() + + case token.PERIOD: + // qualified.typename + f.typ = p.parseQualifiedIdent(f.name) + f.name = nil + } + + case token.MUL, token.ARROW, token.FUNC, token.LBRACK, token.CHAN, token.MAP, token.STRUCT, token.INTERFACE, token.LPAREN: + // type + f.typ = p.parseType() + + case token.ELLIPSIS: + // ...type + // (always accepted) + f.typ = p.parseDotsType() + + default: + p.errorExpected(p.pos, ")") + p.advance(exprEnd) + } + + return } -func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params []*ast.Field) { +func (p *parser) parseParameterList(name0 *ast.Ident, closing token.Token, parseParamDecl func(*ast.Ident) field, tparams bool) (params []*ast.Field) { if p.trace { defer un(trace(p, "ParameterList")) } - // 1st ParameterDecl - // A list of identifiers looks like a list of type names. - var list []ast.Expr - for { - list = append(list, p.parseVarType(ellipsisOk)) - if p.tok != token.COMMA { - break + pos := p.pos + if name0 != nil { + pos = name0.Pos() + } + + var list []field + var named int // number of parameters that have an explicit name and type + + for name0 != nil || p.tok != closing && p.tok != token.EOF { + par := parseParamDecl(name0) + name0 = nil // 1st name was consumed if present + if par.name != nil || par.typ != nil { + list = append(list, par) + if par.name != nil && par.typ != nil { + named++ + } } - p.next() - if p.tok == token.RPAREN { + if !p.atComma("parameter list", closing) { break } + p.next() } - // analyze case - if typ := p.tryVarType(ellipsisOk); typ != nil { - // IdentifierList Type - idents := p.makeIdentList(list) - field := &ast.Field{Names: idents, Type: typ} - params = append(params, field) - // Go spec: The scope of an identifier denoting a function - // parameter or result variable is the function body. - p.declare(field, nil, scope, ast.Var, idents...) - p.resolve(typ) - if !p.atComma("parameter list", token.RPAREN) { - return + if len(list) == 0 { + return // not uncommon + } + + // TODO(gri) parameter distribution and conversion to []*ast.Field + // can be combined and made more efficient + + // distribute parameter types + if named == 0 { + // all unnamed => found names are type names + for i := 0; i < len(list); i++ { + par := &list[i] + if typ := par.name; typ != nil { + par.typ = typ + par.name = nil + } } - p.next() - for p.tok != token.RPAREN && p.tok != token.EOF { - idents := p.parseIdentList() - typ := p.parseVarType(ellipsisOk) - field := &ast.Field{Names: idents, Type: typ} - params = append(params, field) - // Go spec: The scope of an identifier denoting a function - // parameter or result variable is the function body. - p.declare(field, nil, scope, ast.Var, idents...) - p.resolve(typ) - if !p.atComma("parameter list", token.RPAREN) { - break + if tparams { + p.error(pos, "all type parameters must be named") + } + } else if named != len(list) { + // some named => all must be named + ok := true + var typ ast.Expr + for i := len(list) - 1; i >= 0; i-- { + if par := &list[i]; par.typ != nil { + typ = par.typ + if par.name == nil { + ok = false + n := ast.NewIdent("_") + n.NamePos = typ.Pos() // correct position + par.name = n + } + } else if typ != nil { + par.typ = typ + } else { + // par.typ == nil && typ == nil => we only have a par.name + ok = false + par.typ = &ast.BadExpr{From: par.name.Pos(), To: p.pos} } - p.next() + } + if !ok { + if tparams { + p.error(pos, "all type parameters must be named") + } else { + p.error(pos, "mixed named and unnamed parameters") + } + } + } + + // convert list []*ast.Field + if named == 0 { + // parameter list consists of types only + for _, par := range list { + assert(par.typ != nil, "nil type in unnamed parameter list") + params = append(params, &ast.Field{Type: par.typ}) } return } - // Type { "," Type } (anonymous parameters) - params = make([]*ast.Field, len(list)) - for i, typ := range list { - p.resolve(typ) - params[i] = &ast.Field{Type: typ} + // parameter list consists of named parameters with types + var names []*ast.Ident + var typ ast.Expr + addParams := func() { + assert(typ != nil, "nil type in named parameter list") + field := &ast.Field{Names: names, Type: typ} + params = append(params, field) + names = nil + } + for _, par := range list { + if par.typ != typ { + if len(names) > 0 { + addParams() + } + typ = par.typ + } + names = append(names, par.name) + } + if len(names) > 0 { + addParams() } return } -func (p *parser) parseParameters(scope *ast.Scope, ellipsisOk bool) *ast.FieldList { +func (p *parser) parseParameters(acceptTParams bool) (tparams, params *ast.FieldList) { if p.trace { defer un(trace(p, "Parameters")) } - var params []*ast.Field - lparen := p.expect(token.LPAREN) + if p.parseTypeParams() && acceptTParams && p.tok == token.LBRACK { + opening := p.pos + p.next() + // [T any](params) syntax + list := p.parseParameterList(nil, token.RBRACK, p.parseParamDecl, true) + rbrack := p.expect(token.RBRACK) + tparams = &ast.FieldList{Opening: opening, List: list, Closing: rbrack} + // Type parameter lists must not be empty. + if tparams.NumFields() == 0 { + p.error(tparams.Closing, "empty type parameter list") + tparams = nil // avoid follow-on errors + } + } + + opening := p.expect(token.LPAREN) + + var fields []*ast.Field if p.tok != token.RPAREN { - params = p.parseParameterList(scope, ellipsisOk) + fields = p.parseParameterList(nil, token.RPAREN, p.parseParamDecl, false) } + rparen := p.expect(token.RPAREN) + params = &ast.FieldList{Opening: opening, List: fields, Closing: rparen} - return &ast.FieldList{Opening: lparen, List: params, Closing: rparen} + return } -func (p *parser) parseResult(scope *ast.Scope) *ast.FieldList { +func (p *parser) parseResult() *ast.FieldList { if p.trace { defer un(trace(p, "Result")) } if p.tok == token.LPAREN { - return p.parseParameters(scope, false) + _, results := p.parseParameters(false) + return results } - typ := p.tryType() + typ := p.tryIdentOrType() if typ != nil { list := make([]*ast.Field, 1) list[0] = &ast.Field{Type: typ} @@ -914,30 +930,22 @@ func (p *parser) parseResult(scope *ast.Scope) *ast.FieldList { return nil } -func (p *parser) parseSignature(scope *ast.Scope) (params, results *ast.FieldList) { - if p.trace { - defer un(trace(p, "Signature")) - } - - params = p.parseParameters(scope, true) - results = p.parseResult(scope) - - return -} - -func (p *parser) parseFuncType() (*ast.FuncType, *ast.Scope) { +func (p *parser) parseFuncType() *ast.FuncType { if p.trace { defer un(trace(p, "FuncType")) } pos := p.expect(token.FUNC) - scope := ast.NewScope(p.topScope) // function scope - params, results := p.parseSignature(scope) + tparams, params := p.parseParameters(true) + if tparams != nil { + p.error(tparams.Pos(), "function type cannot have type parameters") + } + results := p.parseResult() - return &ast.FuncType{Func: pos, Params: params, Results: results}, scope + return &ast.FuncType{Func: pos, Params: params, Results: results} } -func (p *parser) parseMethodSpec(scope *ast.Scope) *ast.Field { +func (p *parser) parseMethodSpec() *ast.Field { if p.trace { defer un(trace(p, "MethodSpec")) } @@ -945,22 +953,67 @@ func (p *parser) parseMethodSpec(scope *ast.Scope) *ast.Field { doc := p.leadComment var idents []*ast.Ident var typ ast.Expr - x := p.parseTypeName() - if ident, isIdent := x.(*ast.Ident); isIdent && p.tok == token.LPAREN { - // method - idents = []*ast.Ident{ident} - scope := ast.NewScope(nil) // method scope - params, results := p.parseSignature(scope) - typ = &ast.FuncType{Func: token.NoPos, Params: params, Results: results} + x := p.parseTypeName(nil) + if ident, _ := x.(*ast.Ident); ident != nil { + switch { + case p.tok == token.LBRACK && p.parseTypeParams(): + // generic method or embedded instantiated type + lbrack := p.pos + p.next() + p.exprLev++ + x := p.parseExpr() + p.exprLev-- + if name0, _ := x.(*ast.Ident); name0 != nil && p.tok != token.COMMA && p.tok != token.RBRACK { + // generic method m[T any] + list := p.parseParameterList(name0, token.RBRACK, p.parseParamDecl, true) + rbrack := p.expect(token.RBRACK) + tparams := &ast.FieldList{Opening: lbrack, List: list, Closing: rbrack} + // TODO(rfindley) refactor to share code with parseFuncType. + _, params := p.parseParameters(false) + results := p.parseResult() + idents = []*ast.Ident{ident} + typ = &ast.FuncType{Func: token.NoPos, Params: params, Results: results} + typeparams.Set(typ, tparams) + } else { + // embedded instantiated type + // TODO(rfindley) should resolve all identifiers in x. + list := []ast.Expr{x} + if p.atComma("type argument list", token.RBRACK) { + p.exprLev++ + for p.tok != token.RBRACK && p.tok != token.EOF { + list = append(list, p.parseType()) + if !p.atComma("type argument list", token.RBRACK) { + break + } + p.next() + } + p.exprLev-- + } + rbrack := p.expectClosing(token.RBRACK, "type argument list") + typ = &ast.IndexExpr{X: ident, Lbrack: lbrack, Index: typeparams.PackExpr(list), Rbrack: rbrack} + } + case p.tok == token.LPAREN: + // ordinary method + // TODO(rfindley) refactor to share code with parseFuncType. + _, params := p.parseParameters(false) + results := p.parseResult() + idents = []*ast.Ident{ident} + typ = &ast.FuncType{Func: token.NoPos, Params: params, Results: results} + default: + // embedded type + typ = x + } } else { - // embedded interface + // embedded, possibly instantiated type typ = x - p.resolve(typ) + if p.tok == token.LBRACK && p.parseTypeParams() { + // embedded instantiated interface + typ = p.parseTypeInstance(typ) + } } p.expectSemi() // call before accessing p.linecomment spec := &ast.Field{Doc: doc, Names: idents, Type: typ, Comment: p.lineComment} - p.declare(spec, nil, scope, ast.Fun, idents...) return spec } @@ -972,11 +1025,24 @@ func (p *parser) parseInterfaceType() *ast.InterfaceType { pos := p.expect(token.INTERFACE) lbrace := p.expect(token.LBRACE) - scope := ast.NewScope(nil) // interface scope var list []*ast.Field - for p.tok == token.IDENT { - list = append(list, p.parseMethodSpec(scope)) + for p.tok == token.IDENT || p.parseTypeParams() && p.tok == token.TYPE { + if p.tok == token.IDENT { + list = append(list, p.parseMethodSpec()) + } else { + // all types in a type list share the same field name "type" + // (since type is a keyword, a Go program cannot have that field name) + name := []*ast.Ident{{NamePos: p.pos, Name: "type"}} + p.next() + // add each type as a field named "type" + for _, typ := range p.parseTypeList() { + list = append(list, &ast.Field{Names: name, Type: typ}) + } + p.expectSemi() + } } + // TODO(rfindley): the error produced here could be improved, since we could + // accept a identifier, 'type', or a '}' at this point. rbrace := p.expect(token.RBRACE) return &ast.InterfaceType{ @@ -1028,19 +1094,50 @@ func (p *parser) parseChanType() *ast.ChanType { return &ast.ChanType{Begin: pos, Arrow: arrow, Dir: dir, Value: value} } -// If the result is an identifier, it is not resolved. +func (p *parser) parseTypeInstance(typ ast.Expr) ast.Expr { + assert(p.parseTypeParams(), "parseTypeInstance while not parsing type params") + if p.trace { + defer un(trace(p, "TypeInstance")) + } + + opening := p.expect(token.LBRACK) + + p.exprLev++ + var list []ast.Expr + for p.tok != token.RBRACK && p.tok != token.EOF { + list = append(list, p.parseType()) + if !p.atComma("type argument list", token.RBRACK) { + break + } + p.next() + } + p.exprLev-- + + closing := p.expectClosing(token.RBRACK, "type argument list") + + return &ast.IndexExpr{X: typ, Lbrack: opening, Index: typeparams.PackExpr(list), Rbrack: closing} +} + func (p *parser) tryIdentOrType() ast.Expr { switch p.tok { case token.IDENT: - return p.parseTypeName() + typ := p.parseTypeName(nil) + if p.tok == token.LBRACK && p.parseTypeParams() { + typ = p.parseTypeInstance(typ) + } + return typ case token.LBRACK: - return p.parseArrayType() + lbrack := p.expect(token.LBRACK) + alen := p.parseArrayLen() + p.expect(token.RBRACK) + elt := p.parseType() + return &ast.ArrayType{Lbrack: lbrack, Len: alen, Elt: elt} case token.STRUCT: return p.parseStructType() case token.MUL: return p.parsePointerType() case token.FUNC: - typ, _ := p.parseFuncType() + typ := p.parseFuncType() return typ case token.INTERFACE: return p.parseInterfaceType() @@ -1060,14 +1157,6 @@ func (p *parser) tryIdentOrType() ast.Expr { return nil } -func (p *parser) tryType() ast.Expr { - typ := p.tryIdentOrType() - if typ != nil { - p.resolve(typ) - } - return typ -} - // ---------------------------------------------------------------------------- // Blocks @@ -1083,17 +1172,13 @@ func (p *parser) parseStmtList() (list []ast.Stmt) { return } -func (p *parser) parseBody(scope *ast.Scope) *ast.BlockStmt { +func (p *parser) parseBody() *ast.BlockStmt { if p.trace { defer un(trace(p, "Body")) } lbrace := p.expect(token.LBRACE) - p.topScope = scope // open function scope - p.openLabelScope() list := p.parseStmtList() - p.closeLabelScope() - p.closeScope() rbrace := p.expect2(token.RBRACE) return &ast.BlockStmt{Lbrace: lbrace, List: list, Rbrace: rbrace} @@ -1105,9 +1190,7 @@ func (p *parser) parseBlockStmt() *ast.BlockStmt { } lbrace := p.expect(token.LBRACE) - p.openScope() list := p.parseStmtList() - p.closeScope() rbrace := p.expect2(token.RBRACE) return &ast.BlockStmt{Lbrace: lbrace, List: list, Rbrace: rbrace} @@ -1121,14 +1204,14 @@ func (p *parser) parseFuncTypeOrLit() ast.Expr { defer un(trace(p, "FuncTypeOrLit")) } - typ, scope := p.parseFuncType() + typ := p.parseFuncType() if p.tok != token.LBRACE { // function type only return typ } p.exprLev++ - body := p.parseBody(scope) + body := p.parseBody() p.exprLev-- return &ast.FuncLit{Type: typ, Body: body} @@ -1136,9 +1219,8 @@ func (p *parser) parseFuncTypeOrLit() ast.Expr { // parseOperand may return an expression or a raw type (incl. array // types of the form [...]T. Callers must verify the result. -// If lhs is set and the result is an identifier, it is not resolved. // -func (p *parser) parseOperand(lhs bool) ast.Expr { +func (p *parser) parseOperand() ast.Expr { if p.trace { defer un(trace(p, "Operand")) } @@ -1146,9 +1228,6 @@ func (p *parser) parseOperand(lhs bool) ast.Expr { switch p.tok { case token.IDENT: x := p.parseIdent() - if !lhs { - p.resolve(x) - } return x case token.INT, token.FLOAT, token.IMAG, token.CHAR, token.STRING: @@ -1169,7 +1248,7 @@ func (p *parser) parseOperand(lhs bool) ast.Expr { return p.parseFuncTypeOrLit() } - if typ := p.tryIdentOrType(); typ != nil { + if typ := p.tryIdentOrType(); typ != nil { // do not consume trailing type parameters // could be type for composite literal or conversion _, isIdent := typ.(*ast.Ident) assert(!isIdent, "type cannot be identifier") @@ -1211,28 +1290,61 @@ func (p *parser) parseTypeAssertion(x ast.Expr) ast.Expr { return &ast.TypeAssertExpr{X: x, Type: typ, Lparen: lparen, Rparen: rparen} } -func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr { +func (p *parser) parseIndexOrSliceOrInstance(x ast.Expr) ast.Expr { if p.trace { - defer un(trace(p, "IndexOrSlice")) + defer un(trace(p, "parseIndexOrSliceOrInstance")) } - const N = 3 // change the 3 to 2 to disable 3-index slices lbrack := p.expect(token.LBRACK) + if p.tok == token.RBRACK { + // empty index, slice or index expressions are not permitted; + // accept them for parsing tolerance, but complain + p.errorExpected(p.pos, "operand") + rbrack := p.pos + p.next() + return &ast.IndexExpr{ + X: x, + Lbrack: lbrack, + Index: &ast.BadExpr{From: rbrack, To: rbrack}, + Rbrack: rbrack, + } + } p.exprLev++ + + const N = 3 // change the 3 to 2 to disable 3-index slices + var args []ast.Expr var index [N]ast.Expr var colons [N - 1]token.Pos + var firstComma token.Pos if p.tok != token.COLON { - index[0] = p.parseRhs() + // We can't know if we have an index expression or a type instantiation; + // so even if we see a (named) type we are not going to be in type context. + index[0] = p.parseRhsOrType() } ncolons := 0 - for p.tok == token.COLON && ncolons < len(colons) { - colons[ncolons] = p.pos - ncolons++ - p.next() - if p.tok != token.COLON && p.tok != token.RBRACK && p.tok != token.EOF { - index[ncolons] = p.parseRhs() + switch p.tok { + case token.COLON: + // slice expression + for p.tok == token.COLON && ncolons < len(colons) { + colons[ncolons] = p.pos + ncolons++ + p.next() + if p.tok != token.COLON && p.tok != token.RBRACK && p.tok != token.EOF { + index[ncolons] = p.parseRhs() + } + } + case token.COMMA: + firstComma = p.pos + // instance expression + args = append(args, index[0]) + for p.tok == token.COMMA { + p.next() + if p.tok != token.RBRACK && p.tok != token.EOF { + args = append(args, p.parseType()) + } } } + p.exprLev-- rbrack := p.expect(token.RBRACK) @@ -1255,7 +1367,18 @@ func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr { return &ast.SliceExpr{X: x, Lbrack: lbrack, Low: index[0], High: index[1], Max: index[2], Slice3: slice3, Rbrack: rbrack} } - return &ast.IndexExpr{X: x, Lbrack: lbrack, Index: index[0], Rbrack: rbrack} + if len(args) == 0 { + // index expression + return &ast.IndexExpr{X: x, Lbrack: lbrack, Index: index[0], Rbrack: rbrack} + } + + if !p.parseTypeParams() { + p.error(firstComma, "expected ']' or ':', found ','") + return &ast.BadExpr{From: args[0].Pos(), To: args[len(args)-1].End()} + } + + // instance expression + return &ast.IndexExpr{X: x, Lbrack: lbrack, Index: typeparams.PackExpr(args), Rbrack: rbrack} } func (p *parser) parseCallOrConversion(fun ast.Expr) *ast.CallExpr { @@ -1284,7 +1407,7 @@ func (p *parser) parseCallOrConversion(fun ast.Expr) *ast.CallExpr { return &ast.CallExpr{Fun: fun, Lparen: lparen, Args: list, Ellipsis: ellipsis, Rparen: rparen} } -func (p *parser) parseValue(keyOk bool) ast.Expr { +func (p *parser) parseValue() ast.Expr { if p.trace { defer un(trace(p, "Element")) } @@ -1293,35 +1416,7 @@ func (p *parser) parseValue(keyOk bool) ast.Expr { return p.parseLiteralValue(nil) } - // Because the parser doesn't know the composite literal type, it cannot - // know if a key that's an identifier is a struct field name or a name - // denoting a value. The former is not resolved by the parser or the - // resolver. - // - // Instead, _try_ to resolve such a key if possible. If it resolves, - // it a) has correctly resolved, or b) incorrectly resolved because - // the key is a struct field with a name matching another identifier. - // In the former case we are done, and in the latter case we don't - // care because the type checker will do a separate field lookup. - // - // If the key does not resolve, it a) must be defined at the top - // level in another file of the same package, the universe scope, or be - // undeclared; or b) it is a struct field. In the former case, the type - // checker can do a top-level lookup, and in the latter case it will do - // a separate field lookup. - x := p.checkExpr(p.parseExpr(keyOk)) - if keyOk { - if p.tok == token.COLON { - // Try to resolve the key but don't collect it - // as unresolved identifier if it fails so that - // we don't get (possibly false) errors about - // undeclared names. - p.tryResolve(x, false) - } else { - // not a key - p.resolve(x) - } - } + x := p.checkExpr(p.parseExpr()) return x } @@ -1331,11 +1426,11 @@ func (p *parser) parseElement() ast.Expr { defer un(trace(p, "Element")) } - x := p.parseValue(true) + x := p.parseValue() if p.tok == token.COLON { colon := p.pos p.next() - x = &ast.KeyValueExpr{Key: x, Colon: colon, Value: p.parseValue(false)} + x = &ast.KeyValueExpr{Key: x, Colon: colon, Value: p.parseValue()} } return x @@ -1404,45 +1499,6 @@ func (p *parser) checkExpr(x ast.Expr) ast.Expr { return x } -// isTypeName reports whether x is a (qualified) TypeName. -func isTypeName(x ast.Expr) bool { - switch t := x.(type) { - case *ast.BadExpr: - case *ast.Ident: - case *ast.SelectorExpr: - _, isIdent := t.X.(*ast.Ident) - return isIdent - default: - return false // all other nodes are not type names - } - return true -} - -// isLiteralType reports whether x is a legal composite literal type. -func isLiteralType(x ast.Expr) bool { - switch t := x.(type) { - case *ast.BadExpr: - case *ast.Ident: - case *ast.SelectorExpr: - _, isIdent := t.X.(*ast.Ident) - return isIdent - case *ast.ArrayType: - case *ast.StructType: - case *ast.MapType: - default: - return false // all other nodes are not legal composite literal types - } - return true -} - -// If x is of the form *T, deref returns T, otherwise it returns x. -func deref(x ast.Expr) ast.Expr { - if p, isPtr := x.(*ast.StarExpr); isPtr { - x = p.X - } - return x -} - // If x is of the form (T), unparen returns unparen(T), otherwise it returns x. func unparen(x ast.Expr) ast.Expr { if p, isParen := x.(*ast.ParenExpr); isParen { @@ -1469,21 +1525,16 @@ func (p *parser) checkExprOrType(x ast.Expr) ast.Expr { return x } -// If lhs is set and the result is an identifier, it is not resolved. -func (p *parser) parsePrimaryExpr(lhs bool) ast.Expr { +func (p *parser) parsePrimaryExpr() (x ast.Expr) { if p.trace { defer un(trace(p, "PrimaryExpr")) } - x := p.parseOperand(lhs) -L: + x = p.parseOperand() for { switch p.tok { case token.PERIOD: p.next() - if lhs { - p.resolve(x) - } switch p.tok { case token.IDENT: x = p.parseSelector(p.checkExprOrType(x)) @@ -1492,40 +1543,54 @@ L: default: pos := p.pos p.errorExpected(pos, "selector or type assertion") - p.next() // make progress + // TODO(rFindley) The check for token.RBRACE below is a targeted fix + // to error recovery sufficient to make the x/tools tests to + // pass with the new parsing logic introduced for type + // parameters. Remove this once error recovery has been + // more generally reconsidered. + if p.tok != token.RBRACE { + p.next() // make progress + } sel := &ast.Ident{NamePos: pos, Name: "_"} x = &ast.SelectorExpr{X: x, Sel: sel} } case token.LBRACK: - if lhs { - p.resolve(x) - } - x = p.parseIndexOrSlice(p.checkExpr(x)) + x = p.parseIndexOrSliceOrInstance(p.checkExpr(x)) case token.LPAREN: - if lhs { - p.resolve(x) - } x = p.parseCallOrConversion(p.checkExprOrType(x)) case token.LBRACE: - if isLiteralType(x) && (p.exprLev >= 0 || !isTypeName(x)) { - if lhs { - p.resolve(x) + // operand may have returned a parenthesized complit + // type; accept it but complain if we have a complit + t := unparen(x) + // determine if '{' belongs to a composite literal or a block statement + switch t.(type) { + case *ast.BadExpr, *ast.Ident, *ast.SelectorExpr: + if p.exprLev < 0 { + return } - x = p.parseLiteralValue(x) - } else { - break L + // x is possibly a composite literal type + case *ast.IndexExpr: + if p.exprLev < 0 { + return + } + // x is possibly a composite literal type + case *ast.ArrayType, *ast.StructType, *ast.MapType: + // x is a composite literal type + default: + return + } + if t != x { + p.error(t.Pos(), "cannot parenthesize type in composite literal") + // already progressed, no need to advance } + x = p.parseLiteralValue(x) default: - break L + return } - lhs = false // no need to try to resolve again } - - return x } -// If lhs is set and the result is an identifier, it is not resolved. -func (p *parser) parseUnaryExpr(lhs bool) ast.Expr { +func (p *parser) parseUnaryExpr() ast.Expr { if p.trace { defer un(trace(p, "UnaryExpr")) } @@ -1534,7 +1599,7 @@ func (p *parser) parseUnaryExpr(lhs bool) ast.Expr { case token.ADD, token.SUB, token.NOT, token.XOR, token.AND: pos, op := p.pos, p.tok p.next() - x := p.parseUnaryExpr(false) + x := p.parseUnaryExpr() return &ast.UnaryExpr{OpPos: pos, Op: op, X: p.checkExpr(x)} case token.ARROW: @@ -1556,7 +1621,7 @@ func (p *parser) parseUnaryExpr(lhs bool) ast.Expr { // <- (chan type) => (<-chan type) // <- (chan<- type) => (<-chan (<-type)) - x := p.parseUnaryExpr(false) + x := p.parseUnaryExpr() // determine which case we have if typ, ok := x.(*ast.ChanType); ok { @@ -1587,11 +1652,11 @@ func (p *parser) parseUnaryExpr(lhs bool) ast.Expr { // pointer type or unary "*" expression pos := p.pos p.next() - x := p.parseUnaryExpr(false) + x := p.parseUnaryExpr() return &ast.StarExpr{Star: pos, X: p.checkExprOrType(x)} } - return p.parsePrimaryExpr(lhs) + return p.parsePrimaryExpr() } func (p *parser) tokPrec() (token.Token, int) { @@ -1602,44 +1667,38 @@ func (p *parser) tokPrec() (token.Token, int) { return tok, tok.Precedence() } -// If lhs is set and the result is an identifier, it is not resolved. -func (p *parser) parseBinaryExpr(lhs bool, prec1 int) ast.Expr { +func (p *parser) parseBinaryExpr(prec1 int) ast.Expr { if p.trace { defer un(trace(p, "BinaryExpr")) } - x := p.parseUnaryExpr(lhs) + x := p.parseUnaryExpr() for { op, oprec := p.tokPrec() if oprec < prec1 { return x } pos := p.expect(op) - if lhs { - p.resolve(x) - lhs = false - } - y := p.parseBinaryExpr(false, oprec+1) + y := p.parseBinaryExpr(oprec + 1) x = &ast.BinaryExpr{X: p.checkExpr(x), OpPos: pos, Op: op, Y: p.checkExpr(y)} } } -// If lhs is set and the result is an identifier, it is not resolved. // The result may be a type or even a raw type ([...]int). Callers must // check the result (using checkExpr or checkExprOrType), depending on // context. -func (p *parser) parseExpr(lhs bool) ast.Expr { +func (p *parser) parseExpr() ast.Expr { if p.trace { defer un(trace(p, "Expression")) } - return p.parseBinaryExpr(lhs, token.LowestPrec+1) + return p.parseBinaryExpr(token.LowestPrec + 1) } func (p *parser) parseRhs() ast.Expr { old := p.inRhs p.inRhs = true - x := p.checkExpr(p.parseExpr(false)) + x := p.checkExpr(p.parseExpr()) p.inRhs = old return x } @@ -1647,7 +1706,7 @@ func (p *parser) parseRhs() ast.Expr { func (p *parser) parseRhsOrType() ast.Expr { old := p.inRhs p.inRhs = true - x := p.checkExprOrType(p.parseExpr(false)) + x := p.checkExprOrType(p.parseExpr()) p.inRhs = old return x } @@ -1671,7 +1730,7 @@ func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool) { defer un(trace(p, "SimpleStmt")) } - x := p.parseLhsList() + x := p.parseList(false) switch p.tok { case @@ -1690,11 +1749,11 @@ func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool) { y = []ast.Expr{&ast.UnaryExpr{OpPos: pos, Op: token.RANGE, X: p.parseRhs()}} isRange = true } else { - y = p.parseRhsList() + y = p.parseList(true) } as := &ast.AssignStmt{Lhs: x, TokPos: pos, Tok: tok, Rhs: y} if tok == token.DEFINE { - p.shortVarDecl(as, x) + p.checkAssignStmt(as) } return as, isRange } @@ -1714,7 +1773,6 @@ func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool) { // in which it is declared and excludes the body of any nested // function. stmt := &ast.LabeledStmt{Label: label, Colon: colon, Stmt: p.parseStmt()} - p.declare(stmt, nil, p.labelScope, ast.Lbl, label) return stmt, false } // The label declaration typically starts at x[0].Pos(), but the label @@ -1744,6 +1802,14 @@ func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool) { return &ast.ExprStmt{X: x[0]}, false } +func (p *parser) checkAssignStmt(as *ast.AssignStmt) { + for _, x := range as.Lhs { + if _, isIdent := x.(*ast.Ident); !isIdent { + p.errorExpected(x.Pos(), "identifier on left side of :=") + } + } +} + func (p *parser) parseCallExpr(callType string) *ast.CallExpr { x := p.parseRhsOrType() // could be a conversion: (some type)(x) if call, isCall := x.(*ast.CallExpr); isCall { @@ -1795,7 +1861,7 @@ func (p *parser) parseReturnStmt() *ast.ReturnStmt { p.expect(token.RETURN) var x []ast.Expr if p.tok != token.SEMICOLON && p.tok != token.RBRACE { - x = p.parseRhsList() + x = p.parseList(true) } p.expectSemi() @@ -1811,9 +1877,6 @@ func (p *parser) parseBranchStmt(tok token.Token) *ast.BranchStmt { var label *ast.Ident if tok != token.FALLTHROUGH && p.tok == token.IDENT { label = p.parseIdent() - // add to list of unresolved targets - n := len(p.targetStack) - 1 - p.targetStack[n] = append(p.targetStack[n], label) } p.expectSemi() @@ -1846,14 +1909,14 @@ func (p *parser) parseIfHeader() (init ast.Stmt, cond ast.Expr) { } // p.tok != token.LBRACE - outer := p.exprLev + prevLev := p.exprLev p.exprLev = -1 if p.tok != token.SEMICOLON { // accept potential variable declaration but complain if p.tok == token.VAR { p.next() - p.error(p.pos, fmt.Sprintf("var declaration not allowed in 'IF' initializer")) + p.error(p.pos, "var declaration not allowed in 'IF' initializer") } init, _ = p.parseSimpleStmt(basic) } @@ -1894,7 +1957,7 @@ func (p *parser) parseIfHeader() (init ast.Stmt, cond ast.Expr) { cond = &ast.BadExpr{From: p.pos, To: p.pos} } - p.exprLev = outer + p.exprLev = prevLev return } @@ -1904,8 +1967,6 @@ func (p *parser) parseIfStmt() *ast.IfStmt { } pos := p.expect(token.IF) - p.openScope() - defer p.closeScope() init, cond := p.parseIfHeader() body := p.parseBlockStmt() @@ -1956,16 +2017,14 @@ func (p *parser) parseCaseClause(typeSwitch bool) *ast.CaseClause { if typeSwitch { list = p.parseTypeList() } else { - list = p.parseRhsList() + list = p.parseList(true) } } else { p.expect(token.DEFAULT) } colon := p.expect(token.COLON) - p.openScope() body := p.parseStmtList() - p.closeScope() return &ast.CaseClause{Case: pos, List: list, Colon: colon, Body: body} } @@ -2002,8 +2061,6 @@ func (p *parser) parseSwitchStmt() ast.Stmt { } pos := p.expect(token.SWITCH) - p.openScope() - defer p.closeScope() var s1, s2 ast.Stmt if p.tok != token.LBRACE { @@ -2029,8 +2086,6 @@ func (p *parser) parseSwitchStmt() ast.Stmt { // // If we don't have a type switch, s2 must be an expression. // Having the extra nested but empty scope won't affect it. - p.openScope() - defer p.closeScope() s2, _ = p.parseSimpleStmt(basic) } } @@ -2059,12 +2114,11 @@ func (p *parser) parseCommClause() *ast.CommClause { defer un(trace(p, "CommClause")) } - p.openScope() pos := p.pos var comm ast.Stmt if p.tok == token.CASE { p.next() - lhs := p.parseLhsList() + lhs := p.parseList(false) if p.tok == token.ARROW { // SendStmt if len(lhs) > 1 { @@ -2089,7 +2143,7 @@ func (p *parser) parseCommClause() *ast.CommClause { rhs := p.parseRhs() as := &ast.AssignStmt{Lhs: lhs, TokPos: pos, Tok: tok, Rhs: []ast.Expr{rhs}} if tok == token.DEFINE { - p.shortVarDecl(as, lhs) + p.checkAssignStmt(as) } comm = as } else { @@ -2107,7 +2161,6 @@ func (p *parser) parseCommClause() *ast.CommClause { colon := p.expect(token.COLON) body := p.parseStmtList() - p.closeScope() return &ast.CommClause{Case: pos, Comm: comm, Colon: colon, Body: body} } @@ -2136,8 +2189,6 @@ func (p *parser) parseForStmt() ast.Stmt { } pos := p.expect(token.FOR) - p.openScope() - defer p.closeScope() var s1, s2, s3 ast.Stmt var isRange bool @@ -2275,7 +2326,7 @@ func (p *parser) parseStmt() (s ast.Stmt) { // ---------------------------------------------------------------------------- // Declarations -type parseSpecFunction func(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec +type parseSpecFunction func(doc *ast.CommentGroup, pos token.Pos, keyword token.Token, iota int) ast.Spec func isValidImport(lit string) bool { const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD" @@ -2288,7 +2339,7 @@ func isValidImport(lit string) bool { return s != "" } -func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec { +func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Token, _ int) ast.Spec { if p.trace { defer un(trace(p, "ImportSpec")) } @@ -2327,19 +2378,19 @@ func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Token, _ int) as return spec } -func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec { +func (p *parser) parseValueSpec(doc *ast.CommentGroup, _ token.Pos, keyword token.Token, iota int) ast.Spec { if p.trace { defer un(trace(p, keyword.String()+"Spec")) } pos := p.pos idents := p.parseIdentList() - typ := p.tryType() + typ := p.tryIdentOrType() var values []ast.Expr // always permit optional initialization for more tolerant parsing if p.tok == token.ASSIGN { p.next() - values = p.parseRhsList() + values = p.parseList(true) } p.expectSemi() // call before accessing p.linecomment @@ -2354,10 +2405,6 @@ func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota } } - // Go spec: The scope of a constant or variable identifier declared inside - // a function begins at the end of the ConstSpec or VarSpec and ends at - // the end of the innermost containing block. - // (Global identifiers are resolved in a separate phase after parsing.) spec := &ast.ValueSpec{ Doc: doc, Names: idents, @@ -2365,33 +2412,66 @@ func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota Values: values, Comment: p.lineComment, } - kind := ast.Con - if keyword == token.VAR { - kind = ast.Var - } - p.declare(spec, iota, p.topScope, kind, idents...) - return spec } -func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec { +func (p *parser) parseGenericType(spec *ast.TypeSpec, openPos token.Pos, name0 *ast.Ident, closeTok token.Token) { + list := p.parseParameterList(name0, closeTok, p.parseParamDecl, true) + closePos := p.expect(closeTok) + typeparams.Set(spec, &ast.FieldList{Opening: openPos, List: list, Closing: closePos}) + // Type alias cannot have type parameters. Accept them for robustness but complain. + if p.tok == token.ASSIGN { + p.error(p.pos, "generic type cannot be alias") + p.next() + } + spec.Type = p.parseType() +} + +func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Token, _ int) ast.Spec { if p.trace { defer un(trace(p, "TypeSpec")) } ident := p.parseIdent() - - // Go spec: The scope of a type identifier declared inside a function begins - // at the identifier in the TypeSpec and ends at the end of the innermost - // containing block. - // (Global identifiers are resolved in a separate phase after parsing.) spec := &ast.TypeSpec{Doc: doc, Name: ident} - p.declare(spec, nil, p.topScope, ast.Typ, ident) - if p.tok == token.ASSIGN { - spec.Assign = p.pos + + switch p.tok { + case token.LBRACK: + lbrack := p.pos p.next() + if p.tok == token.IDENT { + // array type or generic type [T any] + p.exprLev++ + x := p.parseExpr() + p.exprLev-- + if name0, _ := x.(*ast.Ident); p.parseTypeParams() && name0 != nil && p.tok != token.RBRACK { + // generic type [T any]; + p.parseGenericType(spec, lbrack, name0, token.RBRACK) + } else { + // array type + // TODO(rfindley) should resolve all identifiers in x. + p.expect(token.RBRACK) + elt := p.parseType() + spec.Type = &ast.ArrayType{Lbrack: lbrack, Len: x, Elt: elt} + } + } else { + // array type + alen := p.parseArrayLen() + p.expect(token.RBRACK) + elt := p.parseType() + spec.Type = &ast.ArrayType{Lbrack: lbrack, Len: alen, Elt: elt} + } + + default: + // no type parameters + if p.tok == token.ASSIGN { + // type alias + spec.Assign = p.pos + p.next() + } + spec.Type = p.parseType() } - spec.Type = p.parseType() + p.expectSemi() // call before accessing p.linecomment spec.Comment = p.lineComment @@ -2411,12 +2491,12 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.Gen lparen = p.pos p.next() for iota := 0; p.tok != token.RPAREN && p.tok != token.EOF; iota++ { - list = append(list, f(p.leadComment, keyword, iota)) + list = append(list, f(p.leadComment, pos, keyword, iota)) } rparen = p.expect(token.RPAREN) p.expectSemi() } else { - list = append(list, f(nil, keyword, 0)) + list = append(list, f(nil, pos, keyword, 0)) } return &ast.GenDecl{ @@ -2436,27 +2516,27 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl { doc := p.leadComment pos := p.expect(token.FUNC) - scope := ast.NewScope(p.topScope) // function scope var recv *ast.FieldList if p.tok == token.LPAREN { - recv = p.parseParameters(scope, false) + _, recv = p.parseParameters(false) } ident := p.parseIdent() - params, results := p.parseSignature(scope) + tparams, params := p.parseParameters(true) + results := p.parseResult() var body *ast.BlockStmt if p.tok == token.LBRACE { - body = p.parseBody(scope) + body = p.parseBody() p.expectSemi() } else if p.tok == token.SEMICOLON { p.next() if p.tok == token.LBRACE { // opening { of function declaration on next line p.error(p.pos, "unexpected semicolon or newline before {") - body = p.parseBody(scope) + body = p.parseBody() p.expectSemi() } } else { @@ -2474,18 +2554,7 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl { }, Body: body, } - if recv == nil { - // Go spec: The scope of an identifier denoting a constant, type, - // variable, or function (but not method) declared at top level - // (outside any function) is the package block. - // - // init() functions cannot be referred to and there may - // be more than one - don't put them in the pkgScope - if ident.Name != "init" { - p.declare(decl, nil, p.pkgScope, ast.Fun, ident) - } - } - + typeparams.Set(decl.Type, tparams) return decl } @@ -2546,8 +2615,6 @@ func (p *parser) parseFile() *ast.File { return nil } - p.openScope() - p.pkgScope = p.topScope var decls []ast.Decl if p.mode&PackageClauseOnly == 0 { // import decls @@ -2562,30 +2629,22 @@ func (p *parser) parseFile() *ast.File { } } } - p.closeScope() - assert(p.topScope == nil, "unbalanced scopes") - assert(p.labelScope == nil, "unbalanced label scopes") - // resolve global identifiers within the same file - i := 0 - for _, ident := range p.unresolved { - // i <= index for current ident - assert(ident.Obj == unresolved, "object already resolved") - ident.Obj = p.pkgScope.Lookup(ident.Name) // also removes unresolved sentinel - if ident.Obj == nil { - p.unresolved[i] = ident - i++ - } + f := &ast.File{ + Doc: doc, + Package: pos, + Name: ident, + Decls: decls, + Imports: p.imports, + Comments: p.comments, } - - return &ast.File{ - Doc: doc, - Package: pos, - Name: ident, - Decls: decls, - Scope: p.pkgScope, - Imports: p.imports, - Unresolved: p.unresolved[0:i], - Comments: p.comments, + var declErr func(token.Pos, string) + if p.mode&DeclarationErrors != 0 { + declErr = p.error } + if p.mode&SkipObjectResolution == 0 { + resolveFile(f, p.file, declErr) + } + + return f } diff --git a/libgo/go/go/parser/performance_test.go b/libgo/go/go/parser/performance_test.go index f81bcee..6f8a977 100644 --- a/libgo/go/go/parser/performance_test.go +++ b/libgo/go/go/parser/performance_test.go @@ -10,6 +10,8 @@ import ( "testing" ) +// TODO(rFindley): use a testdata file or file from another package here, to +// avoid a moving target. var src = readFile("parser.go") func readFile(filename string) []byte { @@ -28,3 +30,27 @@ func BenchmarkParse(b *testing.B) { } } } + +func BenchmarkParseOnly(b *testing.B) { + b.SetBytes(int64(len(src))) + for i := 0; i < b.N; i++ { + if _, err := ParseFile(token.NewFileSet(), "", src, ParseComments|SkipObjectResolution); err != nil { + b.Fatalf("benchmark failed due to parse error: %s", err) + } + } +} + +func BenchmarkResolve(b *testing.B) { + b.SetBytes(int64(len(src))) + for i := 0; i < b.N; i++ { + b.StopTimer() + fset := token.NewFileSet() + file, err := ParseFile(fset, "", src, SkipObjectResolution) + if err != nil { + b.Fatalf("benchmark failed due to parse error: %s", err) + } + b.StartTimer() + handle := fset.File(file.Package) + resolveFile(file, handle, nil) + } +} diff --git a/libgo/go/go/parser/resolver.go b/libgo/go/go/parser/resolver.go new file mode 100644 index 0000000..cf92c7e --- /dev/null +++ b/libgo/go/go/parser/resolver.go @@ -0,0 +1,556 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package parser + +import ( + "fmt" + "go/ast" + "go/internal/typeparams" + "go/token" +) + +const debugResolve = false + +// resolveFile walks the given file to resolve identifiers within the file +// scope, updating ast.Ident.Obj fields with declaration information. +// +// If declErr is non-nil, it is used to report declaration errors during +// resolution. tok is used to format position in error messages. +func resolveFile(file *ast.File, handle *token.File, declErr func(token.Pos, string)) { + pkgScope := ast.NewScope(nil) + r := &resolver{ + handle: handle, + declErr: declErr, + topScope: pkgScope, + pkgScope: pkgScope, + } + + for _, decl := range file.Decls { + ast.Walk(r, decl) + } + + r.closeScope() + assert(r.topScope == nil, "unbalanced scopes") + assert(r.labelScope == nil, "unbalanced label scopes") + + // resolve global identifiers within the same file + i := 0 + for _, ident := range r.unresolved { + // i <= index for current ident + assert(ident.Obj == unresolved, "object already resolved") + ident.Obj = r.pkgScope.Lookup(ident.Name) // also removes unresolved sentinel + if ident.Obj == nil { + r.unresolved[i] = ident + i++ + } else if debugResolve { + pos := ident.Obj.Decl.(interface{ Pos() token.Pos }).Pos() + r.dump("resolved %s@%v to package object %v", ident.Name, ident.Pos(), pos) + } + } + file.Scope = r.pkgScope + file.Unresolved = r.unresolved[0:i] +} + +type resolver struct { + handle *token.File + declErr func(token.Pos, string) + + // Ordinary identifier scopes + pkgScope *ast.Scope // pkgScope.Outer == nil + topScope *ast.Scope // top-most scope; may be pkgScope + unresolved []*ast.Ident // unresolved identifiers + + // Label scopes + // (maintained by open/close LabelScope) + labelScope *ast.Scope // label scope for current function + targetStack [][]*ast.Ident // stack of unresolved labels +} + +func (r *resolver) dump(format string, args ...interface{}) { + fmt.Println(">>> " + r.sprintf(format, args...)) +} + +func (r *resolver) sprintf(format string, args ...interface{}) string { + for i, arg := range args { + switch arg := arg.(type) { + case token.Pos: + args[i] = r.handle.Position(arg) + } + } + return fmt.Sprintf(format, args...) +} + +func (r *resolver) openScope(pos token.Pos) { + if debugResolve { + r.dump("opening scope @%v", pos) + } + r.topScope = ast.NewScope(r.topScope) +} + +func (r *resolver) closeScope() { + if debugResolve { + r.dump("closing scope") + } + r.topScope = r.topScope.Outer +} + +func (r *resolver) openLabelScope() { + r.labelScope = ast.NewScope(r.labelScope) + r.targetStack = append(r.targetStack, nil) +} + +func (r *resolver) closeLabelScope() { + // resolve labels + n := len(r.targetStack) - 1 + scope := r.labelScope + for _, ident := range r.targetStack[n] { + ident.Obj = scope.Lookup(ident.Name) + if ident.Obj == nil && r.declErr != nil { + r.declErr(ident.Pos(), fmt.Sprintf("label %s undefined", ident.Name)) + } + } + // pop label scope + r.targetStack = r.targetStack[0:n] + r.labelScope = r.labelScope.Outer +} + +func (r *resolver) declare(decl, data interface{}, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) { + for _, ident := range idents { + // "type" is used for type lists in interfaces, and is otherwise an invalid + // identifier. The 'type' identifier is also artificially duplicated in the + // type list, so could cause panics below if we were to proceed. + if ident.Name == "type" { + continue + } + assert(ident.Obj == nil, "identifier already declared or resolved") + obj := ast.NewObj(kind, ident.Name) + // remember the corresponding declaration for redeclaration + // errors and global variable resolution/typechecking phase + obj.Decl = decl + obj.Data = data + ident.Obj = obj + if ident.Name != "_" { + if debugResolve { + r.dump("declaring %s@%v", ident.Name, ident.Pos()) + } + if alt := scope.Insert(obj); alt != nil && r.declErr != nil { + prevDecl := "" + if pos := alt.Pos(); pos.IsValid() { + prevDecl = fmt.Sprintf("\n\tprevious declaration at %s", r.handle.Position(pos)) + } + r.declErr(ident.Pos(), fmt.Sprintf("%s redeclared in this block%s", ident.Name, prevDecl)) + } + } + } +} + +func (r *resolver) shortVarDecl(decl *ast.AssignStmt) { + // Go spec: A short variable declaration may redeclare variables + // provided they were originally declared in the same block with + // the same type, and at least one of the non-blank variables is new. + n := 0 // number of new variables + for _, x := range decl.Lhs { + if ident, isIdent := x.(*ast.Ident); isIdent { + assert(ident.Obj == nil, "identifier already declared or resolved") + obj := ast.NewObj(ast.Var, ident.Name) + // remember corresponding assignment for other tools + obj.Decl = decl + ident.Obj = obj + if ident.Name != "_" { + if debugResolve { + r.dump("declaring %s@%v", ident.Name, ident.Pos()) + } + if alt := r.topScope.Insert(obj); alt != nil { + ident.Obj = alt // redeclaration + } else { + n++ // new declaration + } + } + } + } + if n == 0 && r.declErr != nil { + r.declErr(decl.Lhs[0].Pos(), "no new variables on left side of :=") + } +} + +// The unresolved object is a sentinel to mark identifiers that have been added +// to the list of unresolved identifiers. The sentinel is only used for verifying +// internal consistency. +var unresolved = new(ast.Object) + +// If x is an identifier, resolve attempts to resolve x by looking up +// the object it denotes. If no object is found and collectUnresolved is +// set, x is marked as unresolved and collected in the list of unresolved +// identifiers. +// +func (r *resolver) resolve(ident *ast.Ident, collectUnresolved bool) { + if ident.Obj != nil { + panic(fmt.Sprintf("%s: identifier %s already declared or resolved", r.handle.Position(ident.Pos()), ident.Name)) + } + // '_' and 'type' should never refer to existing declarations: '_' because it + // has special handling in the spec, and 'type' because it is a keyword, and + // only valid in an interface type list. + if ident.Name == "_" || ident.Name == "type" { + return + } + for s := r.topScope; s != nil; s = s.Outer { + if obj := s.Lookup(ident.Name); obj != nil { + assert(obj.Name != "", "obj with no name") + ident.Obj = obj + return + } + } + // all local scopes are known, so any unresolved identifier + // must be found either in the file scope, package scope + // (perhaps in another file), or universe scope --- collect + // them so that they can be resolved later + if collectUnresolved { + ident.Obj = unresolved + r.unresolved = append(r.unresolved, ident) + } +} + +func (r *resolver) walkExprs(list []ast.Expr) { + for _, node := range list { + ast.Walk(r, node) + } +} + +func (r *resolver) walkLHS(list []ast.Expr) { + for _, expr := range list { + expr := unparen(expr) + if _, ok := expr.(*ast.Ident); !ok && expr != nil { + ast.Walk(r, expr) + } + } +} + +func (r *resolver) walkStmts(list []ast.Stmt) { + for _, stmt := range list { + ast.Walk(r, stmt) + } +} + +func (r *resolver) Visit(node ast.Node) ast.Visitor { + if debugResolve && node != nil { + r.dump("node %T@%v", node, node.Pos()) + } + + switch n := node.(type) { + + // Expressions. + case *ast.Ident: + r.resolve(n, true) + + case *ast.FuncLit: + r.openScope(n.Pos()) + defer r.closeScope() + r.walkFuncType(n.Type) + r.walkBody(n.Body) + + case *ast.SelectorExpr: + ast.Walk(r, n.X) + // Note: don't try to resolve n.Sel, as we don't support qualified + // resolution. + + case *ast.StructType: + r.openScope(n.Pos()) + defer r.closeScope() + r.walkFieldList(n.Fields, ast.Var) + + case *ast.FuncType: + r.openScope(n.Pos()) + defer r.closeScope() + r.walkFuncType(n) + + case *ast.CompositeLit: + if n.Type != nil { + ast.Walk(r, n.Type) + } + for _, e := range n.Elts { + if kv, _ := e.(*ast.KeyValueExpr); kv != nil { + // See issue #45160: try to resolve composite lit keys, but don't + // collect them as unresolved if resolution failed. This replicates + // existing behavior when resolving during parsing. + if ident, _ := kv.Key.(*ast.Ident); ident != nil { + r.resolve(ident, false) + } else { + ast.Walk(r, kv.Key) + } + ast.Walk(r, kv.Value) + } else { + ast.Walk(r, e) + } + } + + case *ast.InterfaceType: + r.openScope(n.Pos()) + defer r.closeScope() + r.walkFieldList(n.Methods, ast.Fun) + + // Statements + case *ast.LabeledStmt: + r.declare(n, nil, r.labelScope, ast.Lbl, n.Label) + ast.Walk(r, n.Stmt) + + case *ast.AssignStmt: + r.walkExprs(n.Rhs) + if n.Tok == token.DEFINE { + r.shortVarDecl(n) + } else { + r.walkExprs(n.Lhs) + } + + case *ast.BranchStmt: + // add to list of unresolved targets + if n.Tok != token.FALLTHROUGH && n.Label != nil { + depth := len(r.targetStack) - 1 + r.targetStack[depth] = append(r.targetStack[depth], n.Label) + } + + case *ast.BlockStmt: + r.openScope(n.Pos()) + defer r.closeScope() + r.walkStmts(n.List) + + case *ast.IfStmt: + r.openScope(n.Pos()) + defer r.closeScope() + if n.Init != nil { + ast.Walk(r, n.Init) + } + ast.Walk(r, n.Cond) + ast.Walk(r, n.Body) + if n.Else != nil { + ast.Walk(r, n.Else) + } + + case *ast.CaseClause: + r.walkExprs(n.List) + r.openScope(n.Pos()) + defer r.closeScope() + r.walkStmts(n.Body) + + case *ast.SwitchStmt: + r.openScope(n.Pos()) + defer r.closeScope() + if n.Init != nil { + ast.Walk(r, n.Init) + } + if n.Tag != nil { + // The scope below reproduces some unnecessary behavior of the parser, + // opening an extra scope in case this is a type switch. It's not needed + // for expression switches. + // TODO: remove this once we've matched the parser resolution exactly. + if n.Init != nil { + r.openScope(n.Tag.Pos()) + defer r.closeScope() + } + ast.Walk(r, n.Tag) + } + if n.Body != nil { + r.walkStmts(n.Body.List) + } + + case *ast.TypeSwitchStmt: + if n.Init != nil { + r.openScope(n.Pos()) + defer r.closeScope() + ast.Walk(r, n.Init) + } + r.openScope(n.Assign.Pos()) + defer r.closeScope() + ast.Walk(r, n.Assign) + // s.Body consists only of case clauses, so does not get its own + // scope. + if n.Body != nil { + r.walkStmts(n.Body.List) + } + + case *ast.CommClause: + r.openScope(n.Pos()) + defer r.closeScope() + if n.Comm != nil { + ast.Walk(r, n.Comm) + } + r.walkStmts(n.Body) + + case *ast.SelectStmt: + // as for switch statements, select statement bodies don't get their own + // scope. + if n.Body != nil { + r.walkStmts(n.Body.List) + } + + case *ast.ForStmt: + r.openScope(n.Pos()) + defer r.closeScope() + if n.Init != nil { + ast.Walk(r, n.Init) + } + if n.Cond != nil { + ast.Walk(r, n.Cond) + } + if n.Post != nil { + ast.Walk(r, n.Post) + } + ast.Walk(r, n.Body) + + case *ast.RangeStmt: + r.openScope(n.Pos()) + defer r.closeScope() + ast.Walk(r, n.X) + var lhs []ast.Expr + if n.Key != nil { + lhs = append(lhs, n.Key) + } + if n.Value != nil { + lhs = append(lhs, n.Value) + } + if len(lhs) > 0 { + if n.Tok == token.DEFINE { + // Note: we can't exactly match the behavior of object resolution + // during the parsing pass here, as it uses the position of the RANGE + // token for the RHS OpPos. That information is not contained within + // the AST. + as := &ast.AssignStmt{ + Lhs: lhs, + Tok: token.DEFINE, + TokPos: n.TokPos, + Rhs: []ast.Expr{&ast.UnaryExpr{Op: token.RANGE, X: n.X}}, + } + // TODO(rFindley): this walkLHS reproduced the parser resolution, but + // is it necessary? By comparison, for a normal AssignStmt we don't + // walk the LHS in case there is an invalid identifier list. + r.walkLHS(lhs) + r.shortVarDecl(as) + } else { + r.walkExprs(lhs) + } + } + ast.Walk(r, n.Body) + + // Declarations + case *ast.GenDecl: + switch n.Tok { + case token.CONST, token.VAR: + for i, spec := range n.Specs { + spec := spec.(*ast.ValueSpec) + kind := ast.Con + if n.Tok == token.VAR { + kind = ast.Var + } + r.walkExprs(spec.Values) + if spec.Type != nil { + ast.Walk(r, spec.Type) + } + r.declare(spec, i, r.topScope, kind, spec.Names...) + } + case token.TYPE: + for _, spec := range n.Specs { + spec := spec.(*ast.TypeSpec) + // Go spec: The scope of a type identifier declared inside a function begins + // at the identifier in the TypeSpec and ends at the end of the innermost + // containing block. + r.declare(spec, nil, r.topScope, ast.Typ, spec.Name) + if tparams := typeparams.Get(spec); tparams != nil { + r.openScope(spec.Pos()) + defer r.closeScope() + r.walkTParams(tparams) + } + ast.Walk(r, spec.Type) + } + } + + case *ast.FuncDecl: + // Open the function scope. + r.openScope(n.Pos()) + defer r.closeScope() + + // Resolve the receiver first, without declaring. + r.resolveList(n.Recv) + + // Type parameters are walked normally: they can reference each other, and + // can be referenced by normal parameters. + if tparams := typeparams.Get(n.Type); tparams != nil { + r.walkTParams(tparams) + // TODO(rFindley): need to address receiver type parameters. + } + + // Resolve and declare parameters in a specific order to get duplicate + // declaration errors in the correct location. + r.resolveList(n.Type.Params) + r.resolveList(n.Type.Results) + r.declareList(n.Recv, ast.Var) + r.declareList(n.Type.Params, ast.Var) + r.declareList(n.Type.Results, ast.Var) + + r.walkBody(n.Body) + if n.Recv == nil && n.Name.Name != "init" { + r.declare(n, nil, r.pkgScope, ast.Fun, n.Name) + } + + default: + return r + } + + return nil +} + +func (r *resolver) walkFuncType(typ *ast.FuncType) { + // typ.TParams must be walked separately for FuncDecls. + r.resolveList(typ.Params) + r.resolveList(typ.Results) + r.declareList(typ.Params, ast.Var) + r.declareList(typ.Results, ast.Var) +} + +func (r *resolver) resolveList(list *ast.FieldList) { + if list == nil { + return + } + for _, f := range list.List { + if f.Type != nil { + ast.Walk(r, f.Type) + } + } +} + +func (r *resolver) declareList(list *ast.FieldList, kind ast.ObjKind) { + if list == nil { + return + } + for _, f := range list.List { + r.declare(f, nil, r.topScope, kind, f.Names...) + } +} + +func (r *resolver) walkFieldList(list *ast.FieldList, kind ast.ObjKind) { + if list == nil { + return + } + r.resolveList(list) + r.declareList(list, kind) +} + +// walkTParams is like walkFieldList, but declares type parameters eagerly so +// that they may be resolved in the constraint expressions held in the field +// Type. +func (r *resolver) walkTParams(list *ast.FieldList) { + if list == nil { + return + } + r.declareList(list, ast.Typ) + r.resolveList(list) +} + +func (r *resolver) walkBody(body *ast.BlockStmt) { + if body == nil { + return + } + r.openLabelScope() + defer r.closeLabelScope() + r.walkStmts(body.List) +} diff --git a/libgo/go/go/parser/resolver_test.go b/libgo/go/go/parser/resolver_test.go new file mode 100644 index 0000000..625c009 --- /dev/null +++ b/libgo/go/go/parser/resolver_test.go @@ -0,0 +1,180 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package parser + +import ( + "fmt" + "go/ast" + "go/internal/typeparams" + "go/scanner" + "go/token" + "os" + "path/filepath" + "strings" + "testing" +) + +// TestResolution checks that identifiers are resolved to the declarations +// annotated in the source, by comparing the positions of the resulting +// Ident.Obj.Decl to positions marked in the source via special comments. +// +// In the test source, any comment prefixed with '=' or '@' (or both) marks the +// previous token position as the declaration ('=') or a use ('@') of an +// identifier. The text following '=' and '@' in the comment string is the +// label to use for the location. Declaration labels must be unique within the +// file, and use labels must refer to an existing declaration label. It's OK +// for a comment to denote both the declaration and use of a label (e.g. +// '=@foo'). Leading and trailing whitespace is ignored. Any comment not +// beginning with '=' or '@' is ignored. +func TestResolution(t *testing.T) { + dir := filepath.Join("testdata", "resolution") + fis, err := os.ReadDir(dir) + if err != nil { + t.Fatal(err) + } + + for _, fi := range fis { + t.Run(fi.Name(), func(t *testing.T) { + fset := token.NewFileSet() + path := filepath.Join(dir, fi.Name()) + src := readFile(path) // panics on failure + var mode Mode + if strings.HasSuffix(path, ".go2") { + if !typeparams.Enabled { + t.Skip("type params are not enabled") + } + } else { + mode |= typeparams.DisallowParsing + } + file, err := ParseFile(fset, path, src, mode) + if err != nil { + t.Fatal(err) + } + + // Compare the positions of objects resolved during parsing (fromParser) + // to those annotated in source comments (fromComments). + + handle := fset.File(file.Package) + fromParser := declsFromParser(file) + fromComments := declsFromComments(handle, src) + + pos := func(pos token.Pos) token.Position { + p := handle.Position(pos) + // The file name is implied by the subtest, so remove it to avoid + // clutter in error messages. + p.Filename = "" + return p + } + for k, want := range fromComments { + if got := fromParser[k]; got != want { + t.Errorf("%s resolved to %s, want %s", pos(k), pos(got), pos(want)) + } + delete(fromParser, k) + } + // What remains in fromParser are unexpected resolutions. + for k, got := range fromParser { + t.Errorf("%s resolved to %s, want no object", pos(k), pos(got)) + } + }) + } +} + +// declsFromParser walks the file and collects the map associating an +// identifier position with its declaration position. +func declsFromParser(file *ast.File) map[token.Pos]token.Pos { + objmap := map[token.Pos]token.Pos{} + ast.Inspect(file, func(node ast.Node) bool { + // Ignore blank identifiers to reduce noise. + if ident, _ := node.(*ast.Ident); ident != nil && ident.Obj != nil && ident.Name != "_" { + objmap[ident.Pos()] = ident.Obj.Pos() + } + return true + }) + return objmap +} + +// declsFromComments looks at comments annotating uses and declarations, and +// maps each identifier use to its corresponding declaration. See the +// description of these annotations in the documentation for TestResolution. +func declsFromComments(handle *token.File, src []byte) map[token.Pos]token.Pos { + decls, uses := positionMarkers(handle, src) + + objmap := make(map[token.Pos]token.Pos) + // Join decls and uses on name, to build the map of use->decl. + for name, posns := range uses { + declpos, ok := decls[name] + if !ok { + panic(fmt.Sprintf("missing declaration for %s", name)) + } + for _, pos := range posns { + objmap[pos] = declpos + } + } + return objmap +} + +// positionMarkers extracts named positions from the source denoted by comments +// prefixed with '=' (declarations) and '@' (uses): for example '@foo' or +// '=@bar'. It returns a map of name->position for declarations, and +// name->position(s) for uses. +func positionMarkers(handle *token.File, src []byte) (decls map[string]token.Pos, uses map[string][]token.Pos) { + var s scanner.Scanner + s.Init(handle, src, nil, scanner.ScanComments) + decls = make(map[string]token.Pos) + uses = make(map[string][]token.Pos) + var prev token.Pos // position of last non-comment, non-semicolon token + +scanFile: + for { + pos, tok, lit := s.Scan() + switch tok { + case token.EOF: + break scanFile + case token.COMMENT: + name, decl, use := annotatedObj(lit) + if len(name) > 0 { + if decl { + if _, ok := decls[name]; ok { + panic(fmt.Sprintf("duplicate declaration markers for %s", name)) + } + decls[name] = prev + } + if use { + uses[name] = append(uses[name], prev) + } + } + case token.SEMICOLON: + // ignore automatically inserted semicolon + if lit == "\n" { + continue scanFile + } + fallthrough + default: + prev = pos + } + } + return decls, uses +} + +func annotatedObj(lit string) (name string, decl, use bool) { + if lit[1] == '*' { + lit = lit[:len(lit)-2] // strip trailing */ + } + lit = strings.TrimSpace(lit[2:]) + +scanLit: + for idx, r := range lit { + switch r { + case '=': + decl = true + case '@': + use = true + default: + name = lit[idx:] + break scanLit + } + } + return +} diff --git a/libgo/go/go/parser/short_test.go b/libgo/go/go/parser/short_test.go index 49bb681..67fef15 100644 --- a/libgo/go/go/parser/short_test.go +++ b/libgo/go/go/parser/short_test.go @@ -6,7 +6,10 @@ package parser -import "testing" +import ( + "go/internal/typeparams" + "testing" +) var valids = []string{ "package p\n", @@ -48,12 +51,104 @@ var valids = []string{ `package p; var _ = map[*P]int{&P{}:0, {}:1}`, `package p; type T = int`, `package p; type (T = p.T; _ = struct{}; x = *T)`, + `package p; type T (*int)`, + `package p; type _ struct{ ((int)) }`, + `package p; type _ struct{ (*(int)) }`, + `package p; type _ struct{ ([]byte) }`, // disallowed by type-checker + `package p; var _ = func()T(nil)`, + `package p; func _(T (P))`, + `package p; func _(T []E)`, + `package p; func _(T [P]E)`, + `package p; type _ [A+B]struct{}`, + `package p; func (R) _()`, + `package p; type _ struct{ f [n]E }`, + `package p; type _ struct{ f [a+b+c+d]E }`, + `package p; type I1 interface{}; type I2 interface{ I1 }`, +} + +// validWithTParamsOnly holds source code examples that are valid if +// parseTypeParams is set, but invalid if not. When checking with the +// parseTypeParams set, errors are ignored. +var validWithTParamsOnly = []string{ + `package p; type _ []T[ /* ERROR "expected ';', found '\['" */ int]`, + `package p; type T[P any /* ERROR "expected ']', found any" */ ] struct { P }`, + `package p; type T[P comparable /* ERROR "expected ']', found comparable" */ ] struct { P }`, + `package p; type T[P comparable /* ERROR "expected ']', found comparable" */ [P]] struct { P }`, + `package p; type T[P1, /* ERROR "expected ']', found ','" */ P2 any] struct { P1; f []P2 }`, + `package p; func _[ /* ERROR "expected '\(', found '\['" */ T any]()()`, + `package p; func _(T (P))`, + `package p; func f[ /* ERROR "expected '\(', found '\['" */ A, B any](); func _() { _ = f[int, int] }`, + `package p; func _(x /* ERROR "mixed named and unnamed parameters" */ T[P1, P2, P3])`, + `package p; func _(x /* ERROR "mixed named and unnamed parameters" */ p.T[Q])`, + `package p; func _(p.T[ /* ERROR "missing ',' in parameter list" */ Q])`, + `package p; type _[A interface /* ERROR "expected ']', found 'interface'" */ {},] struct{}`, + `package p; type _[A interface /* ERROR "expected ']', found 'interface'" */ {}] struct{}`, + `package p; type _[A, /* ERROR "expected ']', found ','" */ B any,] struct{}`, + `package p; type _[A, /* ERROR "expected ']', found ','" */ B any] struct{}`, + `package p; type _[A any /* ERROR "expected ']', found any" */,] struct{}`, + `package p; type _[A any /* ERROR "expected ']', found any" */ ]struct{}`, + `package p; type _[A any /* ERROR "expected ']', found any" */ ] struct{ A }`, + `package p; func _[ /* ERROR "expected '\(', found '\['" */ T any]()`, + `package p; func _[ /* ERROR "expected '\(', found '\['" */ T any](x T)`, + `package p; func _[ /* ERROR "expected '\(', found '\['" */ T1, T2 any](x T)`, + `package p; func _[ /* ERROR "expected '\(', found '\['" */ A, B any](a A) B`, + `package p; func _[ /* ERROR "expected '\(', found '\['" */ A, B C](a A) B`, + `package p; func _[ /* ERROR "expected '\(', found '\['" */ A, B C[A, B]](a A) B`, + `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B any](a A) B`, + `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B C](a A) B`, + `package p; func (T) _[ /* ERROR "expected '\(', found '\['" */ A, B C[A, B]](a A) B`, + `package p; type _[A, /* ERROR "expected ']', found ','" */ B any] interface { _(a A) B }`, + `package p; type _[A, /* ERROR "expected ']', found ','" */ B C[A, B]] interface { _(a A) B }`, + `package p; func _[ /* ERROR "expected '\(', found '\['" */ T1, T2 interface{}](x T1) T2`, + `package p; func _[ /* ERROR "expected '\(', found '\['" */ T1 interface{ m() }, T2, T3 interface{}](x T1, y T3) T2`, + `package p; var _ = [ /* ERROR "expected expression" */ ]T[int]{}`, + `package p; var _ = [ /* ERROR "expected expression" */ 10]T[int]{}`, + `package p; var _ = func /* ERROR "expected expression" */ ()T[int]{}`, + `package p; var _ = map /* ERROR "expected expression" */ [T[int]]T[int]{}`, + `package p; var _ = chan /* ERROR "expected expression" */ T[int](x)`, + `package p; func _(_ T[ /* ERROR "missing ',' in parameter list" */ P], T P) T[P]`, + `package p; var _ T[ /* ERROR "expected ';', found '\['" */ chan int]`, + + // TODO(rfindley) this error message could be improved. + `package p; func (_ /* ERROR "mixed named and unnamed parameters" */ R[P]) _[T any](x T)`, + `package p; func (_ /* ERROR "mixed named and unnamed parameters" */ R[ P, Q]) _[T1, T2 any](x T)`, + + `package p; func (R[P] /* ERROR "missing element type" */ ) _[T any]()`, + `package p; func _(T[P] /* ERROR "missing element type" */ )`, + `package p; func _(T[P1, /* ERROR "expected ']', found ','" */ P2, P3 ])`, + `package p; func _(T[P] /* ERROR "missing element type" */ ) T[P]`, + `package p; type _ struct{ T[P] /* ERROR "missing element type" */ }`, + `package p; type _ struct{ T[struct /* ERROR "expected expression" */ {a, b, c int}] }`, + `package p; type _ interface{type /* ERROR "expected '}', found 'type'" */ int}`, + `package p; type _ interface{type /* ERROR "expected '}', found 'type'" */ int, float32; type bool; m(); type string;}`, + `package p; type I1[T any /* ERROR "expected ']', found any" */ ] interface{}; type I2 interface{ I1[int] }`, + `package p; type I1[T any /* ERROR "expected ']', found any" */ ] interface{}; type I2[T any] interface{ I1[T] }`, + `package p; type _ interface { f[ /* ERROR "expected ';', found '\['" */ T any]() }`, } func TestValid(t *testing.T) { - for _, src := range valids { - checkErrors(t, src, src) - } + t.Run("no tparams", func(t *testing.T) { + for _, src := range valids { + checkErrors(t, src, src, DeclarationErrors|AllErrors, false) + } + }) + t.Run("tparams", func(t *testing.T) { + if !typeparams.Enabled { + t.Skip("type params are not enabled") + } + for _, src := range valids { + checkErrors(t, src, src, DeclarationErrors|AllErrors, false) + } + for _, src := range validWithTParamsOnly { + checkErrors(t, src, src, DeclarationErrors|AllErrors, false) + } + }) +} + +// TestSingle is useful to track down a problem with a single short test program. +func TestSingle(t *testing.T) { + const src = `package p; var _ = T{}` + checkErrors(t, src, src, DeclarationErrors|AllErrors, true) } var invalids = []string{ @@ -79,7 +174,6 @@ var invalids = []string{ `package p; var a = chan /* ERROR "expected expression" */ int;`, `package p; var a = []int{[ /* ERROR "expected expression" */ ]int};`, `package p; var a = ( /* ERROR "expected expression" */ []int);`, - `package p; var a = a[[ /* ERROR "expected expression" */ ]int:[]int];`, `package p; var a = <- /* ERROR "expected expression" */ chan int;`, `package p; func f() { select { case _ <- chan /* ERROR "expected expression" */ int: } };`, `package p; func f() { _ = (<-<- /* ERROR "expected 'chan'" */ chan int)(nil) };`, @@ -102,7 +196,14 @@ var invalids = []string{ `package p; func f() { go f /* ERROR HERE "function must be invoked" */ }`, `package p; func f() { defer func() {} /* ERROR HERE "function must be invoked" */ }`, `package p; func f() { go func() { func() { f(x func /* ERROR "missing ','" */ (){}) } } }`, - `package p; func f(x func(), u v func /* ERROR "missing ','" */ ()){}`, + `package p; func _() (type /* ERROR "found 'type'" */ T)(T)`, + `package p; func (type /* ERROR "found 'type'" */ T)(T) _()`, + `package p; type _[A+B, /* ERROR "expected ']'" */ ] int`, + + // TODO: this error should be positioned on the ':' + `package p; var a = a[[]int:[ /* ERROR "expected expression" */ ]int];`, + // TODO: the compiler error is better here: "cannot parenthesize embedded type" + `package p; type I1 interface{}; type I2 interface{ (/* ERROR "expected '}', found '\('" */ I1) }`, // issue 8656 `package p; func f() (a b string /* ERROR "missing ','" */ , ok bool)`, @@ -118,19 +219,61 @@ var invalids = []string{ `package p; var _ = struct { x int, /* ERROR "expected ';', found ','" */ y float }{};`, // issue 11611 - `package p; type _ struct { int, } /* ERROR "expected type, found '}'" */ ;`, + `package p; type _ struct { int, } /* ERROR "expected 'IDENT', found '}'" */ ;`, `package p; type _ struct { int, float } /* ERROR "expected type, found '}'" */ ;`, - `package p; type _ struct { ( /* ERROR "expected anonymous field" */ int) };`, - `package p; func _()(x, y, z ... /* ERROR "expected '\)', found '...'" */ int){}`, - `package p; func _()(... /* ERROR "expected type, found '...'" */ int){}`, // issue 13475 `package p; func f() { if true {} else ; /* ERROR "expected if statement or block" */ }`, `package p; func f() { if true {} else defer /* ERROR "expected if statement or block" */ f() }`, } +// invalidNoTParamErrs holds invalid source code examples annotated with the +// error messages produced when ParseTypeParams is not set. +var invalidNoTParamErrs = []string{ + `package p; type _[_ any /* ERROR "expected ']', found any" */ ] int; var _ = T[]{}`, + `package p; type T[P any /* ERROR "expected ']', found any" */ ] = T0`, + `package p; var _ func[ /* ERROR "expected '\(', found '\['" */ T any](T)`, + `package p; func _[ /* ERROR "expected '\(', found '\['" */ ]()`, + `package p; type _[A, /* ERROR "expected ']', found ','" */] struct{ A }`, + `package p; func _[ /* ERROR "expected '\(', found '\['" */ type P, *Q interface{}]()`, +} + +// invalidTParamErrs holds invalid source code examples annotated with the +// error messages produced when ParseTypeParams is set. +var invalidTParamErrs = []string{ + `package p; type _[_ any] int; var _ = T[] /* ERROR "expected operand" */ {}`, + `package p; type T[P any] = /* ERROR "cannot be alias" */ T0`, + `package p; var _ func[ /* ERROR "cannot have type parameters" */ T any](T)`, + `package p; func _[]/* ERROR "empty type parameter list" */()`, + + // TODO(rfindley) a better location would be after the ']' + `package p; type _[A/* ERROR "all type parameters must be named" */,] struct{ A }`, + + // TODO(rfindley) this error is confusing. + `package p; func _[type /* ERROR "all type parameters must be named" */P, *Q interface{}]()`, +} + func TestInvalid(t *testing.T) { - for _, src := range invalids { - checkErrors(t, src, src) - } + t.Run("no tparams", func(t *testing.T) { + for _, src := range invalids { + checkErrors(t, src, src, DeclarationErrors|AllErrors|typeparams.DisallowParsing, true) + } + for _, src := range validWithTParamsOnly { + checkErrors(t, src, src, DeclarationErrors|AllErrors|typeparams.DisallowParsing, true) + } + for _, src := range invalidNoTParamErrs { + checkErrors(t, src, src, DeclarationErrors|AllErrors|typeparams.DisallowParsing, true) + } + }) + t.Run("tparams", func(t *testing.T) { + if !typeparams.Enabled { + t.Skip("type params are not enabled") + } + for _, src := range invalids { + checkErrors(t, src, src, DeclarationErrors|AllErrors, true) + } + for _, src := range invalidTParamErrs { + checkErrors(t, src, src, DeclarationErrors|AllErrors, true) + } + }) } diff --git a/libgo/go/go/parser/testdata/chans.go2 b/libgo/go/go/parser/testdata/chans.go2 new file mode 100644 index 0000000..fad2bce --- /dev/null +++ b/libgo/go/go/parser/testdata/chans.go2 @@ -0,0 +1,62 @@ +package chans + +import "runtime" + +// Ranger returns a Sender and a Receiver. The Receiver provides a +// Next method to retrieve values. The Sender provides a Send method +// to send values and a Close method to stop sending values. The Next +// method indicates when the Sender has been closed, and the Send +// method indicates when the Receiver has been freed. +// +// This is a convenient way to exit a goroutine sending values when +// the receiver stops reading them. +func Ranger[T any]() (*Sender[T], *Receiver[T]) { + c := make(chan T) + d := make(chan bool) + s := &Sender[T]{values: c, done: d} + r := &Receiver[T]{values: c, done: d} + runtime.SetFinalizer(r, r.finalize) + return s, r +} + +// A sender is used to send values to a Receiver. +type Sender[T any] struct { + values chan<- T + done <-chan bool +} + +// Send sends a value to the receiver. It returns whether any more +// values may be sent; if it returns false the value was not sent. +func (s *Sender[T]) Send(v T) bool { + select { + case s.values <- v: + return true + case <-s.done: + return false + } +} + +// Close tells the receiver that no more values will arrive. +// After Close is called, the Sender may no longer be used. +func (s *Sender[T]) Close() { + close(s.values) +} + +// A Receiver receives values from a Sender. +type Receiver[T any] struct { + values <-chan T + done chan<- bool +} + +// Next returns the next value from the channel. The bool result +// indicates whether the value is valid, or whether the Sender has +// been closed and no more values will be received. +func (r *Receiver[T]) Next() (T, bool) { + v, ok := <-r.values + return v, ok +} + +// finalize is a finalizer for the receiver. +func (r *Receiver[T]) finalize() { + close(r.done) +} diff --git a/libgo/go/go/parser/testdata/issue11377.src b/libgo/go/go/parser/testdata/issue11377.src new file mode 100644 index 0000000..1c43800 --- /dev/null +++ b/libgo/go/go/parser/testdata/issue11377.src @@ -0,0 +1,27 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test case for issue 11377: Better synchronization of +// parser after certain syntax errors. + +package p + +func bad1() { + if f()) /* ERROR "expected ';', found '\)'" */ { + return + } +} + +// There shouldn't be any errors down below. + +func F1() {} +func F2() {} +func F3() {} +func F4() {} +func F5() {} +func F6() {} +func F7() {} +func F8() {} +func F9() {} +func F10() {} diff --git a/libgo/go/go/parser/testdata/issue23434.src b/libgo/go/go/parser/testdata/issue23434.src new file mode 100644 index 0000000..24a0832 --- /dev/null +++ b/libgo/go/go/parser/testdata/issue23434.src @@ -0,0 +1,25 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test case for issue 23434: Better synchronization of +// parser after missing type. There should be exactly +// one error each time, with now follow errors. + +package p + +func g() { + m := make(map[string]! /* ERROR "expected type, found '!'" */ ) + for { + x := 1 + print(x) + } +} + +func f() { + m := make(map[string]) /* ERROR "expected type, found '\)'" */ + for { + x := 1 + print(x) + } +} diff --git a/libgo/go/go/parser/testdata/issue34946.src b/libgo/go/go/parser/testdata/issue34946.src new file mode 100644 index 0000000..6bb15e1 --- /dev/null +++ b/libgo/go/go/parser/testdata/issue34946.src @@ -0,0 +1,22 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test case for issue 34946: Better synchronization of +// parser for function declarations that start their +// body's opening { on a new line. + +package p + +// accept Allman/BSD-style declaration but complain +// (implicit semicolon between signature and body) +func _() int +{ /* ERROR "unexpected semicolon or newline before {" */ + { return 0 } +} + +func _() {} + +func _(); { /* ERROR "unexpected semicolon or newline before {" */ } + +func _() {} diff --git a/libgo/go/go/parser/testdata/issue44504.src b/libgo/go/go/parser/testdata/issue44504.src new file mode 100644 index 0000000..7791f4a --- /dev/null +++ b/libgo/go/go/parser/testdata/issue44504.src @@ -0,0 +1,13 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test case for issue 44504: panic due to duplicate resolution of slice/index +// operands. We should not try to resolve a LHS expression with invalid syntax. + +package p + +func _() { + var items []bool + items[] /* ERROR "operand" */ = false +} diff --git a/libgo/go/go/parser/testdata/linalg.go2 b/libgo/go/go/parser/testdata/linalg.go2 new file mode 100644 index 0000000..fba0d02 --- /dev/null +++ b/libgo/go/go/parser/testdata/linalg.go2 @@ -0,0 +1,83 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package linalg + +import "math" + +// Numeric is type bound that matches any numeric type. +// It would likely be in a constraints package in the standard library. +type Numeric interface { + type int, int8, int16, int32, int64, + uint, uint8, uint16, uint32, uint64, uintptr, + float32, float64, + complex64, complex128 +} + +func DotProduct[T Numeric](s1, s2 []T) T { + if len(s1) != len(s2) { + panic("DotProduct: slices of unequal length") + } + var r T + for i := range s1 { + r += s1[i] * s2[i] + } + return r +} + +// NumericAbs matches numeric types with an Abs method. +type NumericAbs[T any] interface { + Numeric + + Abs() T +} + +// AbsDifference computes the absolute value of the difference of +// a and b, where the absolute value is determined by the Abs method. +func AbsDifference[T NumericAbs](a, b T) T { + d := a - b + return d.Abs() +} + +// OrderedNumeric is a type bound that matches numeric types that support the < operator. +type OrderedNumeric interface { + type int, int8, int16, int32, int64, + uint, uint8, uint16, uint32, uint64, uintptr, + float32, float64 +} + +// Complex is a type bound that matches the two complex types, which do not have a < operator. +type Complex interface { + type complex64, complex128 +} + +// OrderedAbs is a helper type that defines an Abs method for +// ordered numeric types. +type OrderedAbs[T OrderedNumeric] T + +func (a OrderedAbs[T]) Abs() OrderedAbs[T] { + if a < 0 { + return -a + } + return a +} + +// ComplexAbs is a helper type that defines an Abs method for +// complex types. +type ComplexAbs[T Complex] T + +func (a ComplexAbs[T]) Abs() ComplexAbs[T] { + r := float64(real(a)) + i := float64(imag(a)) + d := math.Sqrt(r * r + i * i) + return ComplexAbs[T](complex(d, 0)) +} + +func OrderedAbsDifference[T OrderedNumeric](a, b T) T { + return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b))) +} + +func ComplexAbsDifference[T Complex](a, b T) T { + return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b))) +} diff --git a/libgo/go/go/parser/testdata/map.go2 b/libgo/go/go/parser/testdata/map.go2 new file mode 100644 index 0000000..74c79ae --- /dev/null +++ b/libgo/go/go/parser/testdata/map.go2 @@ -0,0 +1,109 @@ +// Package orderedmap provides an ordered map, implemented as a binary tree. +package orderedmap + +import "chans" + +// Map is an ordered map. +type Map[K, V any] struct { + root *node[K, V] + compare func(K, K) int +} + +// node is the type of a node in the binary tree. +type node[K, V any] struct { + key K + val V + left, right *node[K, V] +} + +// New returns a new map. +func New[K, V any](compare func(K, K) int) *Map[K, V] { + return &Map[K, V]{compare: compare} +} + +// find looks up key in the map, and returns either a pointer +// to the node holding key, or a pointer to the location where +// such a node would go. +func (m *Map[K, V]) find(key K) **node[K, V] { + pn := &m.root + for *pn != nil { + switch cmp := m.compare(key, (*pn).key); { + case cmp < 0: + pn = &(*pn).left + case cmp > 0: + pn = &(*pn).right + default: + return pn + } + } + return pn +} + +// Insert inserts a new key/value into the map. +// If the key is already present, the value is replaced. +// Returns true if this is a new key, false if already present. +func (m *Map[K, V]) Insert(key K, val V) bool { + pn := m.find(key) + if *pn != nil { + (*pn).val = val + return false + } + *pn = &node[K, V]{key: key, val: val} + return true +} + +// Find returns the value associated with a key, or zero if not present. +// The found result reports whether the key was found. +func (m *Map[K, V]) Find(key K) (V, bool) { + pn := m.find(key) + if *pn == nil { + var zero V // see the discussion of zero values, above + return zero, false + } + return (*pn).val, true +} + +// keyValue is a pair of key and value used when iterating. +type keyValue[K, V any] struct { + key K + val V +} + +// InOrder returns an iterator that does an in-order traversal of the map. +func (m *Map[K, V]) InOrder() *Iterator[K, V] { + sender, receiver := chans.Ranger[keyValue[K, V]]() + var f func(*node[K, V]) bool + f = func(n *node[K, V]) bool { + if n == nil { + return true + } + // Stop sending values if sender.Send returns false, + // meaning that nothing is listening at the receiver end. + return f(n.left) && + // TODO + // sender.Send(keyValue[K, V]{n.key, n.val}) && + f(n.right) + } + go func() { + f(m.root) + sender.Close() + }() + return &Iterator{receiver} +} + +// Iterator is used to iterate over the map. +type Iterator[K, V any] struct { + r *chans.Receiver[keyValue[K, V]] +} + +// Next returns the next key and value pair, and a boolean indicating +// whether they are valid or whether we have reached the end. +func (it *Iterator[K, V]) Next() (K, V, bool) { + keyval, ok := it.r.Next() + if !ok { + var zerok K + var zerov V + return zerok, zerov, false + } + return keyval.key, keyval.val, true +} diff --git a/libgo/go/go/parser/testdata/metrics.go2 b/libgo/go/go/parser/testdata/metrics.go2 new file mode 100644 index 0000000..ef1c66b --- /dev/null +++ b/libgo/go/go/parser/testdata/metrics.go2 @@ -0,0 +1,58 @@ +package metrics + +import "sync" + +type Metric1[T comparable] struct { + mu sync.Mutex + m map[T]int +} + +func (m *Metric1[T]) Add(v T) { + m.mu.Lock() + defer m.mu.Unlock() + if m.m == nil { + m.m = make(map[T]int) + } + m[v]++ +} + +type key2[T1, T2 comparable] struct { + f1 T1 + f2 T2 +} + +type Metric2[T1, T2 cmp2] struct { + mu sync.Mutex + m map[key2[T1, T2]]int +} + +func (m *Metric2[T1, T2]) Add(v1 T1, v2 T2) { + m.mu.Lock() + defer m.mu.Unlock() + if m.m == nil { + m.m = make(map[key2[T1, T2]]int) + } + m[key[T1, T2]{v1, v2}]++ +} + +type key3[T1, T2, T3 comparable] struct { + f1 T1 + f2 T2 + f3 T3 +} + +type Metric3[T1, T2, T3 comparable] struct { + mu sync.Mutex + m map[key3[T1, T2, T3]]int +} + +func (m *Metric3[T1, T2, T3]) Add(v1 T1, v2 T2, v3 T3) { + m.mu.Lock() + defer m.mu.Unlock() + if m.m == nil { + m.m = make(map[key3]int) + } + m[key[T1, T2, T3]{v1, v2, v3}]++ +} + +// Repeat for the maximum number of permitted arguments. diff --git a/libgo/go/go/parser/testdata/resolution/issue45136.src b/libgo/go/go/parser/testdata/resolution/issue45136.src new file mode 100644 index 0000000..e1d63d8 --- /dev/null +++ b/libgo/go/go/parser/testdata/resolution/issue45136.src @@ -0,0 +1,27 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue45136 + +type obj /* =@obj */ struct { + name /*=@name */ string +} + +func _() { + var foo /* =@foo */ = "foo" + obj /* @obj */ ["foo"] + obj /* @obj */ .run() + obj /* @obj */ { + name: foo /* @foo */, + } + obj /* @obj */ { + name: "bar", + }.run() + + var _ = File{key: obj /* @obj */ {}} + var _ = File{obj /* @obj */ {}} + + []obj /* @obj */ {foo /* @foo */} + x /* =@x1 */ := obj /* @obj */{} +} diff --git a/libgo/go/go/parser/testdata/resolution/issue45160.src b/libgo/go/go/parser/testdata/resolution/issue45160.src new file mode 100644 index 0000000..6be933b --- /dev/null +++ b/libgo/go/go/parser/testdata/resolution/issue45160.src @@ -0,0 +1,25 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue45160 + +func mklink1 /* =@mklink1func */() {} + +func _() { + var tests /* =@tests */ = []dirLinkTest /* @dirLinkTest */ { + { + mklink1 /* @mklink1func */: func() {}, + mklink2: func(link /* =@link */, target /* =@target */ string) error { + return nil + }, + }, + } +} + +type dirLinkTest /* =@dirLinkTest */ struct { + mklink1 /* =@mklink1field */ func(string, string) error + mklink2 /* =@mklink2field */ func(string, string) error +} + +func mklink2 /* =@mklink2func */() {} diff --git a/libgo/go/go/parser/testdata/resolution/resolution.src b/libgo/go/go/parser/testdata/resolution/resolution.src new file mode 100644 index 0000000..a880dd1 --- /dev/null +++ b/libgo/go/go/parser/testdata/resolution/resolution.src @@ -0,0 +1,63 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package resolution + +func f /* =@fdecl */(n /* =@narg */ ast.Node) bool { + if n /* =@ninit */, ok /* =@ok */ := n /* @narg */ .(*ast.SelectorExpr); ok /* @ok */ { + sel = n /* @ninit */ + } +} + +type c /* =@cdecl */ map[token.Pos]resolvedObj + +func (v /* =@vdecl */ c /* @cdecl */) Visit(node /* =@nodearg */ ast.Node) (w /* =@w */ ast.Visitor) {} + +const ( + basic /* =@basic */ = iota + labelOk // =@labelOk +) + +type T /* =@T */ int + +func _(count /* =@count */ T /* @T */) { + x /* =@x1 */ := c /* @cdecl */{} + switch x /* =@x2 */ := x /* @x1 */; x /* =@x3 */ := x /* @x2 */.(type) { + case c /* @cdecl */: + default: + } +loop /* =@loop */: + for { + if true { + break loop /* @loop */ + } + } + select { + case err /* =@err1 */ := <-_: + return err /* @err1 */ + case err /* =@err2 */ := <-_: + return err /* @err2 */ + } + + _ = func(p1 /* =@p1 */ int, p2 /* =@p2 */ p1) { + closed /* =@closed */ := p1 // @p1 + shadowed /* =@shadowed1 */ := p2 // @p2 + _ = func(shadowed /* =@shadowed2 */ p2 /* @p2 */) { + closed /* @closed */ = 1 + shadowed /* @shadowed2 */ = 2 + } + } +} + +func (r /* =@r */ c /* @cdecl */) m(_ r) c /* @cdecl */ { return r /* @r */ } + +var cycle /* =@cycle */ = cycle /* @cycle */ + 1 + +type chain /* =@chain */ struct { + next /* =@next */ *chain /* @chain */ +} + +func recursive /* =@recursive */() { + recursive /* @recursive */ () +} diff --git a/libgo/go/go/parser/testdata/resolution/typeparams.go2 b/libgo/go/go/parser/testdata/resolution/typeparams.go2 new file mode 100644 index 0000000..0ffecd6 --- /dev/null +++ b/libgo/go/go/parser/testdata/resolution/typeparams.go2 @@ -0,0 +1,43 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package resolution + +type List /* =@List */ [E /* =@E */ any] []E // @E + +type Pair /* =@Pair */ [L /* =@L */, R /* =@R */ any] struct { + Left /* =@Left */ L // @L + Right /* =@Right */ R // @R + L /* =@Lfield */ int +} + +var _ = Pair /* @Pair */ [int, string]{} + +type Addable /* =@Addable */ interface { + type int64, float64 +} + +func Add /* =@AddDecl */[T /* =@T */ Addable /* @Addable */](l /* =@l */, r /* =@r */ T /* @T */) T /* @T */ { + var t /* =@t */ T /* @T */ + return l /* @l */ + r /* @r */ + t /* @t */ +} + +type Receiver /* =@Receiver */[P /* =@P */ any] struct {} + +// TODO(rFindley): make a decision on how/whether to resolve identifiers that +// refer to receiver type parameters, as is the case for the 'P' result +// parameter below. +func (r /* =@recv */ Receiver /* @Receiver */ [P]) m() P {} + +func f /* =@f */[T1 /* =@T1 */ interface{type []T2 /* @T2 */}, T2 /* =@T2 */ any]( + x /* =@x */ T1 /* @T1 */, T1 /* =@T1_duplicate */ y, // Note that this is a bug: + // the duplicate T1 should + // not be allowed. + ){ + // Note that duplicate short var declarations resolve to their alt declaration. + x /* @x */ := 0 + y /* =@y */ := 0 + T1 /* @T1 */ := 0 + var t1var /* =@t1var */ T1 /* @T1 */ +} diff --git a/libgo/go/go/parser/testdata/set.go2 b/libgo/go/go/parser/testdata/set.go2 new file mode 100644 index 0000000..0da6377 --- /dev/null +++ b/libgo/go/go/parser/testdata/set.go2 @@ -0,0 +1,31 @@ +// Package set implements sets of any type. +package set + +type Set[Elem comparable] map[Elem]struct{} + +func Make[Elem comparable]() Set[Elem] { + return make(Set(Elem)) +} + +func (s Set[Elem]) Add(v Elem) { + s[v] = struct{}{} +} + +func (s Set[Elem]) Delete(v Elem) { + delete(s, v) +} + +func (s Set[Elem]) Contains(v Elem) bool { + _, ok := s[v] + return ok +} + +func (s Set[Elem]) Len() int { + return len(s) +} + +func (s Set[Elem]) Iterate(f func(Elem)) { + for v := range s { + f(v) + } +} diff --git a/libgo/go/go/parser/testdata/slices.go2 b/libgo/go/go/parser/testdata/slices.go2 new file mode 100644 index 0000000..e060212 --- /dev/null +++ b/libgo/go/go/parser/testdata/slices.go2 @@ -0,0 +1,31 @@ +// Package slices implements various slice algorithms. +package slices + +// Map turns a []T1 to a []T2 using a mapping function. +func Map[T1, T2 any](s []T1, f func(T1) T2) []T2 { + r := make([]T2, len(s)) + for i, v := range s { + r[i] = f(v) + } + return r +} + +// Reduce reduces a []T1 to a single value using a reduction function. +func Reduce[T1, T2 any](s []T1, initializer T2, f func(T2, T1) T2) T2 { + r := initializer + for _, v := range s { + r = f(r, v) + } + return r +} + +// Filter filters values from a slice using a filter function. +func Filter[T any](s []T, f func(T) bool) []T { + var r []T + for _, v := range s { + if f(v) { + r = append(r, v) + } + } + return r +} diff --git a/libgo/go/go/parser/testdata/sort.go2 b/libgo/go/go/parser/testdata/sort.go2 new file mode 100644 index 0000000..88be79f --- /dev/null +++ b/libgo/go/go/parser/testdata/sort.go2 @@ -0,0 +1,27 @@ +package sort + +type orderedSlice[Elem comparable] []Elem + +func (s orderedSlice[Elem]) Len() int { return len(s) } +func (s orderedSlice[Elem]) Less(i, j int) bool { return s[i] < s[j] } +func (s orderedSlice[Elem]) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// OrderedSlice sorts the slice s in ascending order. +// The elements of s must be ordered using the < operator. +func OrderedSlice[Elem comparable](s []Elem) { + sort.Sort(orderedSlice[Elem](s)) +} + +type sliceFn[Elem any] struct { + s []Elem + f func(Elem, Elem) bool +} + +func (s sliceFn[Elem]) Len() int { return len(s.s) } +func (s sliceFn[Elem]) Less(i, j int) bool { return s.f(s.s[i], s.s[j]) } +func (s sliceFn[Elem]) Swap(i, j int) { s.s[i], s.s[j] = s.s[j], s.s[i] } + +// SliceFn sorts the slice s according to the function f. +func SliceFn[Elem any](s []Elem, f func(Elem, Elem) bool) { + Sort(sliceFn[Elem]{s, f}) +} diff --git a/libgo/go/go/parser/testdata/typeparams.src b/libgo/go/go/parser/testdata/typeparams.src new file mode 100644 index 0000000..1fea23f --- /dev/null +++ b/libgo/go/go/parser/testdata/typeparams.src @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test cases for error messages produced while parsing code that uses type +// parameters, without ParseTypeParams being enabled. + +package p + +type List[E any /* ERROR "expected ']', found any" */ ] []E + +type Pair[L, /* ERROR "expected ']', found ','" */ R any] struct { + Left L + Right R +} + +var _ = Pair[int, /* ERROR "expected ']' or ':', found ','" */ string]{} diff --git a/libgo/go/go/printer/gobuild.go b/libgo/go/go/printer/gobuild.go new file mode 100644 index 0000000..f00492d --- /dev/null +++ b/libgo/go/go/printer/gobuild.go @@ -0,0 +1,170 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package printer + +import ( + "go/build/constraint" + "sort" + "text/tabwriter" +) + +func (p *printer) fixGoBuildLines() { + if len(p.goBuild)+len(p.plusBuild) == 0 { + return + } + + // Find latest possible placement of //go:build and // +build comments. + // That's just after the last blank line before we find a non-comment. + // (We'll add another blank line after our comment block.) + // When we start dropping // +build comments, we can skip over /* */ comments too. + // Note that we are processing tabwriter input, so every comment + // begins and ends with a tabwriter.Escape byte. + // And some newlines have turned into \f bytes. + insert := 0 + for pos := 0; ; { + // Skip leading space at beginning of line. + blank := true + for pos < len(p.output) && (p.output[pos] == ' ' || p.output[pos] == '\t') { + pos++ + } + // Skip over // comment if any. + if pos+3 < len(p.output) && p.output[pos] == tabwriter.Escape && p.output[pos+1] == '/' && p.output[pos+2] == '/' { + blank = false + for pos < len(p.output) && !isNL(p.output[pos]) { + pos++ + } + } + // Skip over \n at end of line. + if pos >= len(p.output) || !isNL(p.output[pos]) { + break + } + pos++ + + if blank { + insert = pos + } + } + + // If there is a //go:build comment before the place we identified, + // use that point instead. (Earlier in the file is always fine.) + if len(p.goBuild) > 0 && p.goBuild[0] < insert { + insert = p.goBuild[0] + } else if len(p.plusBuild) > 0 && p.plusBuild[0] < insert { + insert = p.plusBuild[0] + } + + var x constraint.Expr + switch len(p.goBuild) { + case 0: + // Synthesize //go:build expression from // +build lines. + for _, pos := range p.plusBuild { + y, err := constraint.Parse(p.commentTextAt(pos)) + if err != nil { + x = nil + break + } + if x == nil { + x = y + } else { + x = &constraint.AndExpr{X: x, Y: y} + } + } + case 1: + // Parse //go:build expression. + x, _ = constraint.Parse(p.commentTextAt(p.goBuild[0])) + } + + var block []byte + if x == nil { + // Don't have a valid //go:build expression to treat as truth. + // Bring all the lines together but leave them alone. + // Note that these are already tabwriter-escaped. + for _, pos := range p.goBuild { + block = append(block, p.lineAt(pos)...) + } + for _, pos := range p.plusBuild { + block = append(block, p.lineAt(pos)...) + } + } else { + block = append(block, tabwriter.Escape) + block = append(block, "//go:build "...) + block = append(block, x.String()...) + block = append(block, tabwriter.Escape, '\n') + if len(p.plusBuild) > 0 { + lines, err := constraint.PlusBuildLines(x) + if err != nil { + lines = []string{"// +build error: " + err.Error()} + } + for _, line := range lines { + block = append(block, tabwriter.Escape) + block = append(block, line...) + block = append(block, tabwriter.Escape, '\n') + } + } + } + block = append(block, '\n') + + // Build sorted list of lines to delete from remainder of output. + toDelete := append(p.goBuild, p.plusBuild...) + sort.Ints(toDelete) + + // Collect output after insertion point, with lines deleted, into after. + var after []byte + start := insert + for _, end := range toDelete { + if end < start { + continue + } + after = appendLines(after, p.output[start:end]) + start = end + len(p.lineAt(end)) + } + after = appendLines(after, p.output[start:]) + if n := len(after); n >= 2 && isNL(after[n-1]) && isNL(after[n-2]) { + after = after[:n-1] + } + + p.output = p.output[:insert] + p.output = append(p.output, block...) + p.output = append(p.output, after...) +} + +// appendLines is like append(x, y...) +// but it avoids creating doubled blank lines, +// which would not be gofmt-standard output. +// It assumes that only whole blocks of lines are being appended, +// not line fragments. +func appendLines(x, y []byte) []byte { + if len(y) > 0 && isNL(y[0]) && // y starts in blank line + (len(x) == 0 || len(x) >= 2 && isNL(x[len(x)-1]) && isNL(x[len(x)-2])) { // x is empty or ends in blank line + y = y[1:] // delete y's leading blank line + } + return append(x, y...) +} + +func (p *printer) lineAt(start int) []byte { + pos := start + for pos < len(p.output) && !isNL(p.output[pos]) { + pos++ + } + if pos < len(p.output) { + pos++ + } + return p.output[start:pos] +} + +func (p *printer) commentTextAt(start int) string { + if start < len(p.output) && p.output[start] == tabwriter.Escape { + start++ + } + pos := start + for pos < len(p.output) && p.output[pos] != tabwriter.Escape && !isNL(p.output[pos]) { + pos++ + } + return string(p.output[start:pos]) +} + +func isNL(b byte) bool { + return b == '\n' || b == '\f' +} diff --git a/libgo/go/go/printer/nodes.go b/libgo/go/go/printer/nodes.go index 95b9e918..913281e 100644 --- a/libgo/go/go/printer/nodes.go +++ b/libgo/go/go/printer/nodes.go @@ -11,6 +11,7 @@ package printer import ( "bytes" "go/ast" + "go/internal/typeparams" "go/token" "math" "strconv" @@ -319,8 +320,12 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp } } -func (p *printer) parameters(fields *ast.FieldList) { - p.print(fields.Opening, token.LPAREN) +func (p *printer) parameters(fields *ast.FieldList, isTypeParam bool) { + openTok, closeTok := token.LPAREN, token.RPAREN + if isTypeParam { + openTok, closeTok = token.LBRACK, token.RBRACK + } + p.print(fields.Opening, openTok) if len(fields.List) > 0 { prevLine := p.lineFor(fields.Opening) ws := indent @@ -328,13 +333,8 @@ func (p *printer) parameters(fields *ast.FieldList) { // determine par begin and end line (may be different // if there are multiple parameter names for this par // or the type is on a separate line) - var parLineBeg int - if len(par.Names) > 0 { - parLineBeg = p.lineFor(par.Names[0].Pos()) - } else { - parLineBeg = p.lineFor(par.Type.Pos()) - } - var parLineEnd = p.lineFor(par.Type.End()) + parLineBeg := p.lineFor(par.Pos()) + parLineEnd := p.lineFor(par.End()) // separating "," if needed needsLinebreak := 0 < prevLine && prevLine < parLineBeg if i > 0 { @@ -379,25 +379,29 @@ func (p *printer) parameters(fields *ast.FieldList) { p.print(unindent) } } - p.print(fields.Closing, token.RPAREN) + p.print(fields.Closing, closeTok) } -func (p *printer) signature(params, result *ast.FieldList) { - if params != nil { - p.parameters(params) +func (p *printer) signature(sig *ast.FuncType) { + if tparams := typeparams.Get(sig); tparams != nil { + p.parameters(tparams, true) + } + if sig.Params != nil { + p.parameters(sig.Params, false) } else { p.print(token.LPAREN, token.RPAREN) } - n := result.NumFields() + res := sig.Results + n := res.NumFields() if n > 0 { - // result != nil + // res != nil p.print(blank) - if n == 1 && result.List[0].Names == nil { - // single anonymous result; no ()'s - p.expr(stripParensAlways(result.List[0].Type)) + if n == 1 && res.List[0].Names == nil { + // single anonymous res; no ()'s + p.expr(stripParensAlways(res.List[0].Type)) return } - p.parameters(result) + p.parameters(res, false) } } @@ -467,10 +471,18 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) } p.expr(f.Type) } else { // interface - if ftyp, isFtyp := f.Type.(*ast.FuncType); isFtyp { - // method - p.expr(f.Names[0]) - p.signature(ftyp.Params, ftyp.Results) + if len(f.Names) > 0 { + // type list type or method + name := f.Names[0] // "type" or method name + p.expr(name) + if name.Name == "type" { + // type list type + p.print(blank) + p.expr(f.Type) + } else { + // method + p.signature(f.Type.(*ast.FuncType)) // don't print "func" + } } else { // embedded interface p.expr(f.Type) @@ -538,19 +550,47 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) } else { // interface var line int + var prev *ast.Ident // previous "type" identifier for i, f := range list { + var name *ast.Ident // first name, or nil + if len(f.Names) > 0 { + name = f.Names[0] + } if i > 0 { - p.linebreak(p.lineFor(f.Pos()), 1, ignore, p.linesFrom(line) > 0) + // don't do a line break (min == 0) if we are printing a list of types + // TODO(gri) this doesn't work quite right if the list of types is + // spread across multiple lines + min := 1 + if prev != nil && name == prev { + min = 0 + } + p.linebreak(p.lineFor(f.Pos()), min, ignore, p.linesFrom(line) > 0) } p.setComment(f.Doc) p.recordLine(&line) - if ftyp, isFtyp := f.Type.(*ast.FuncType); isFtyp { - // method - p.expr(f.Names[0]) - p.signature(ftyp.Params, ftyp.Results) + if name != nil { + // type list type or method + if name.Name == "type" { + // type list type + if name == prev { + // type is part of a list of types + p.print(token.COMMA, blank) + } else { + // type starts a new list of types + p.print(name, blank) + } + p.expr(f.Type) + prev = name + } else { + // method + p.expr(name) + p.signature(f.Type.(*ast.FuncType)) // don't print "func" + prev = nil + } } else { // embedded interface p.expr(f.Type) + prev = nil } p.setComment(f.Comment) } @@ -800,7 +840,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) { p.print(x.Type.Pos(), token.FUNC) // See the comment in funcDecl about how the header size is computed. startCol := p.out.Column - len("func") - p.signature(x.Type.Params, x.Type.Results) + p.signature(x.Type) p.funcBody(p.distanceFrom(x.Type.Pos(), startCol), blank, x.Body) case *ast.ParenExpr: @@ -831,7 +871,17 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) { // TODO(gri): should treat[] like parentheses and undo one level of depth p.expr1(x.X, token.HighestPrec, 1) p.print(x.Lbrack, token.LBRACK) - p.expr0(x.Index, depth+1) + // Note: we're a bit defensive here to handle the case of a ListExpr of + // length 1. + if list := typeparams.UnpackExpr(x.Index); len(list) > 0 { + if len(list) > 1 { + p.exprList(x.Lbrack, list, depth+1, commaTerm, x.Rbrack, false) + } else { + p.expr0(list[0], depth+1) + } + } else { + p.expr0(x.Index, depth+1) + } p.print(x.Rbrack, token.RBRACK) case *ast.SliceExpr: @@ -945,7 +995,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) { case *ast.FuncType: p.print(token.FUNC) - p.signature(x.Params, x.Results) + p.signature(x) case *ast.InterfaceType: p.print(token.INTERFACE) @@ -1585,6 +1635,9 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool) { case *ast.TypeSpec: p.setComment(s.Doc) p.expr(s.Name) + if tparams := typeparams.Get(s); tparams != nil { + p.parameters(tparams, true) + } if n == 1 { p.print(blank) } else { @@ -1773,11 +1826,11 @@ func (p *printer) funcDecl(d *ast.FuncDecl) { // FUNC is emitted). startCol := p.out.Column - len("func ") if d.Recv != nil { - p.parameters(d.Recv) // method: print receiver + p.parameters(d.Recv, false) // method: print receiver p.print(blank) } p.expr(d.Name) - p.signature(d.Type.Params, d.Type.Results) + p.signature(d.Type) p.funcBody(p.distanceFrom(d.Pos(), startCol), vtab, d.Body) } diff --git a/libgo/go/go/printer/printer.go b/libgo/go/go/printer/printer.go index 0077afe..ba61f78 100644 --- a/libgo/go/go/printer/printer.go +++ b/libgo/go/go/printer/printer.go @@ -8,6 +8,7 @@ package printer import ( "fmt" "go/ast" + "go/build/constraint" "go/token" "io" "os" @@ -64,6 +65,8 @@ type printer struct { lastTok token.Token // last token printed (token.ILLEGAL if it's whitespace) prevOpen token.Token // previous non-brace "open" token (, [, or token.ILLEGAL wsbuf []whiteSpace // delayed white space + goBuild []int // start index of all //go:build comments in output + plusBuild []int // start index of all // +build comments in output // Positions // The out position differs from the pos position when the result @@ -649,6 +652,11 @@ func (p *printer) writeComment(comment *ast.Comment) { // shortcut common case of //-style comments if text[1] == '/' { + if constraint.IsGoBuild(text) { + p.goBuild = append(p.goBuild, len(p.output)) + } else if constraint.IsPlusBuild(text) { + p.plusBuild = append(p.plusBuild, len(p.output)) + } p.writeString(pos, trimRight(text), true) return } @@ -836,7 +844,7 @@ func (p *printer) writeWhitespace(n int) { // ---------------------------------------------------------------------------- // Printing interface -// nlines limits n to maxNewlines. +// nlimit limits n to maxNewlines. func nlimit(n int) int { if n > maxNewlines { n = maxNewlines @@ -1122,6 +1130,8 @@ func (p *printer) printNode(node interface{}) error { // get comments ready for use p.nextComment() + p.print(pmode(0)) + // format node switch n := node.(type) { case ast.Expr: @@ -1313,6 +1323,10 @@ func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node interface{ p.impliedSemi = false // EOF acts like a newline p.flush(token.Position{Offset: infinity, Line: infinity}, token.EOF) + // output is buffered in p.output now. + // fix //go:build and // +build comments if needed. + p.fixGoBuildLines() + // redirect output through a trimmer to eliminate trailing whitespace // (Input to a tabwriter must be untrimmed since trailing tabs provide // formatting information. The tabwriter could provide trimming diff --git a/libgo/go/go/printer/printer_test.go b/libgo/go/go/printer/printer_test.go index 45e5011..20c97b8 100644 --- a/libgo/go/go/printer/printer_test.go +++ b/libgo/go/go/printer/printer_test.go @@ -10,6 +10,7 @@ import ( "flag" "fmt" "go/ast" + "go/internal/typeparams" "go/parser" "go/token" "io" @@ -35,6 +36,7 @@ const ( rawFormat normNumber idempotent + allowTypeParams ) // format parses src, prints the corresponding AST, verifies the resulting @@ -70,7 +72,7 @@ func format(src []byte, mode checkMode) ([]byte, error) { // make sure formatted output is syntactically correct res := buf.Bytes() - if _, err := parser.ParseFile(fset, "", res, 0); err != nil { + if _, err := parser.ParseFile(fset, "", res, parser.ParseComments); err != nil { return nil, fmt.Errorf("re-parse: %s\n%s", err, buf.Bytes()) } @@ -88,8 +90,11 @@ func lineAt(text []byte, offs int) []byte { // diff compares a and b. func diff(aname, bname string, a, b []byte) error { - var buf bytes.Buffer // holding long error message + if bytes.Equal(a, b) { + return nil + } + var buf bytes.Buffer // holding long error message // compare lengths if len(a) != len(b) { fmt.Fprintf(&buf, "\nlength changed: len(%s) = %d, len(%s) = %d", aname, len(a), bname, len(b)) @@ -97,7 +102,7 @@ func diff(aname, bname string, a, b []byte) error { // compare contents line := 1 - offs := 1 + offs := 0 for i := 0; i < len(a) && i < len(b); i++ { ch := a[i] if ch != b[i] { @@ -112,10 +117,8 @@ func diff(aname, bname string, a, b []byte) error { } } - if buf.Len() > 0 { - return errors.New(buf.String()) - } - return nil + fmt.Fprintf(&buf, "\n%s:\n%s\n%s:\n%s", aname, a, bname, b) + return errors.New(buf.String()) } func runcheck(t *testing.T, source, golden string, mode checkMode) { @@ -206,11 +209,22 @@ var data = []entry{ {"complit.input", "complit.x", export}, {"go2numbers.input", "go2numbers.golden", idempotent}, {"go2numbers.input", "go2numbers.norm", normNumber | idempotent}, + {"generics.input", "generics.golden", idempotent | allowTypeParams}, + {"gobuild1.input", "gobuild1.golden", idempotent}, + {"gobuild2.input", "gobuild2.golden", idempotent}, + {"gobuild3.input", "gobuild3.golden", idempotent}, + {"gobuild4.input", "gobuild4.golden", idempotent}, + {"gobuild5.input", "gobuild5.golden", idempotent}, + {"gobuild6.input", "gobuild6.golden", idempotent}, + {"gobuild7.input", "gobuild7.golden", idempotent}, } func TestFiles(t *testing.T) { t.Parallel() for _, e := range data { + if !typeparams.Enabled && e.mode&allowTypeParams != 0 { + continue + } source := filepath.Join(dataDir, e.source) golden := filepath.Join(dataDir, e.golden) mode := e.mode diff --git a/libgo/go/go/printer/testdata/declarations.input b/libgo/go/go/printer/testdata/declarations.input index a858051..f34395b 100644 --- a/libgo/go/go/printer/testdata/declarations.input +++ b/libgo/go/go/printer/testdata/declarations.input @@ -1018,4 +1018,4 @@ type ( c = foo d = interface{} ddd = p.Foo -)
\ No newline at end of file +) diff --git a/libgo/go/go/printer/testdata/generics.golden b/libgo/go/go/printer/testdata/generics.golden new file mode 100644 index 0000000..cc7fbbe --- /dev/null +++ b/libgo/go/go/printer/testdata/generics.golden @@ -0,0 +1,43 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package generics + +func _[A, B any](a A, b B) int {} +func _[T any](x, y T) T + +type T[P any] struct{} +type T[P1, P2, P3 any] struct{} + +type T[P C] struct{} +type T[P1, P2, P3 C] struct{} + +type T[P C[P]] struct{} +type T[P1, P2, P3 C[P1, P2, P3]] struct{} + +func f[P any](x P) +func f[P1, P2, P3 any](x1 P1, x2 P2, x3 P3) struct{} + +func f[P interface{}](x P) +func f[P1, P2, P3 interface { + m1(P1) + type P2, P3 +}](x1 P1, x2 P2, x3 P3) struct{} +func f[P any](T1[P], T2[P]) T3[P] + +func (x T[P]) m() +func (T[P]) m(x T[P]) P + +func _() { + type _ []T[P] + var _ []T[P] + _ = []T[P]{} +} + +// properly format one-line type lists +type _ interface{ type a } + +type _ interface { + type a, b, c +} diff --git a/libgo/go/go/printer/testdata/generics.input b/libgo/go/go/printer/testdata/generics.input new file mode 100644 index 0000000..f4571ad --- /dev/null +++ b/libgo/go/go/printer/testdata/generics.input @@ -0,0 +1,38 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package generics + +func _[A, B any](a A, b B) int {} +func _[T any](x, y T) T + +type T[P any] struct{} +type T[P1, P2, P3 any] struct{} + +type T[P C] struct{} +type T[P1, P2, P3 C] struct{} + +type T[P C[P]] struct{} +type T[P1, P2, P3 C[P1, P2, P3]] struct{} + +func f[P any](x P) +func f[P1, P2, P3 any](x1 P1, x2 P2, x3 P3) struct{} + +func f[P interface{}](x P) +func f[P1, P2, P3 interface{ m1(P1); type P2, P3 }](x1 P1, x2 P2, x3 P3) struct{} +func f[P any](T1[P], T2[P]) T3[P] + +func (x T[P]) m() +func ((T[P])) m(x T[P]) P + +func _() { + type _ []T[P] + var _ []T[P] + _ = []T[P]{} +} + +// properly format one-line type lists +type _ interface { type a } + +type _ interface { type a,b,c } diff --git a/libgo/go/go/printer/testdata/gobuild1.golden b/libgo/go/go/printer/testdata/gobuild1.golden new file mode 100644 index 0000000..649da40 --- /dev/null +++ b/libgo/go/go/printer/testdata/gobuild1.golden @@ -0,0 +1,6 @@ +//go:build x +// +build x + +package p + +func f() diff --git a/libgo/go/go/printer/testdata/gobuild1.input b/libgo/go/go/printer/testdata/gobuild1.input new file mode 100644 index 0000000..6538ee6 --- /dev/null +++ b/libgo/go/go/printer/testdata/gobuild1.input @@ -0,0 +1,7 @@ +package p + +//go:build x + +func f() + +// +build y diff --git a/libgo/go/go/printer/testdata/gobuild2.golden b/libgo/go/go/printer/testdata/gobuild2.golden new file mode 100644 index 0000000..c46fd34 --- /dev/null +++ b/libgo/go/go/printer/testdata/gobuild2.golden @@ -0,0 +1,8 @@ +//go:build x +// +build x + +// other comment + +package p + +func f() diff --git a/libgo/go/go/printer/testdata/gobuild2.input b/libgo/go/go/printer/testdata/gobuild2.input new file mode 100644 index 0000000..f0f772a --- /dev/null +++ b/libgo/go/go/printer/testdata/gobuild2.input @@ -0,0 +1,9 @@ +// +build y + +// other comment + +package p + +func f() + +//go:build x diff --git a/libgo/go/go/printer/testdata/gobuild3.golden b/libgo/go/go/printer/testdata/gobuild3.golden new file mode 100644 index 0000000..db92c57 --- /dev/null +++ b/libgo/go/go/printer/testdata/gobuild3.golden @@ -0,0 +1,10 @@ +// other comment + +//go:build x +// +build x + +// yet another comment + +package p + +func f() diff --git a/libgo/go/go/printer/testdata/gobuild3.input b/libgo/go/go/printer/testdata/gobuild3.input new file mode 100644 index 0000000..d0c97b2 --- /dev/null +++ b/libgo/go/go/printer/testdata/gobuild3.input @@ -0,0 +1,11 @@ +// other comment + +// +build y + +// yet another comment + +package p + +//go:build x + +func f() diff --git a/libgo/go/go/printer/testdata/gobuild4.golden b/libgo/go/go/printer/testdata/gobuild4.golden new file mode 100644 index 0000000..b16477f --- /dev/null +++ b/libgo/go/go/printer/testdata/gobuild4.golden @@ -0,0 +1,6 @@ +//go:build (x || y) && z +// +build x y +// +build z + +// doc comment +package p diff --git a/libgo/go/go/printer/testdata/gobuild4.input b/libgo/go/go/printer/testdata/gobuild4.input new file mode 100644 index 0000000..29d5a0a --- /dev/null +++ b/libgo/go/go/printer/testdata/gobuild4.input @@ -0,0 +1,5 @@ +// doc comment +package p + +// +build x y +// +build z diff --git a/libgo/go/go/printer/testdata/gobuild5.golden b/libgo/go/go/printer/testdata/gobuild5.golden new file mode 100644 index 0000000..2808a53 --- /dev/null +++ b/libgo/go/go/printer/testdata/gobuild5.golden @@ -0,0 +1,4 @@ +//go:build !(x || y) && z +// +build !x,!y,z + +package p diff --git a/libgo/go/go/printer/testdata/gobuild5.input b/libgo/go/go/printer/testdata/gobuild5.input new file mode 100644 index 0000000..ec5815c --- /dev/null +++ b/libgo/go/go/printer/testdata/gobuild5.input @@ -0,0 +1,4 @@ +//go:build !(x || y) && z +// +build something else + +package p diff --git a/libgo/go/go/printer/testdata/gobuild6.golden b/libgo/go/go/printer/testdata/gobuild6.golden new file mode 100644 index 0000000..abb1e2a --- /dev/null +++ b/libgo/go/go/printer/testdata/gobuild6.golden @@ -0,0 +1,5 @@ +//go:build !(x || y) && z + +// no +build line + +package p diff --git a/libgo/go/go/printer/testdata/gobuild6.input b/libgo/go/go/printer/testdata/gobuild6.input new file mode 100644 index 0000000..1621897 --- /dev/null +++ b/libgo/go/go/printer/testdata/gobuild6.input @@ -0,0 +1,4 @@ +//go:build !(x || y) && z +// no +build line + +package p diff --git a/libgo/go/go/printer/testdata/gobuild7.golden b/libgo/go/go/printer/testdata/gobuild7.golden new file mode 100644 index 0000000..bf41dd4 --- /dev/null +++ b/libgo/go/go/printer/testdata/gobuild7.golden @@ -0,0 +1,11 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// TODO(rsc): Delete this file once Go 1.17 comes out and we can retire Go 1.15 support. + +//go:build !go1.16 +// +build !go1.16 + +// Package buildtag defines an Analyzer that checks build tags. +package buildtag diff --git a/libgo/go/go/printer/testdata/gobuild7.input b/libgo/go/go/printer/testdata/gobuild7.input new file mode 100644 index 0000000..bf41dd4 --- /dev/null +++ b/libgo/go/go/printer/testdata/gobuild7.input @@ -0,0 +1,11 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// TODO(rsc): Delete this file once Go 1.17 comes out and we can retire Go 1.15 support. + +//go:build !go1.16 +// +build !go1.16 + +// Package buildtag defines an Analyzer that checks build tags. +package buildtag diff --git a/libgo/go/go/printer/testdata/parser.go b/libgo/go/go/printer/testdata/parser.go index 80b476c..fc2812a 100644 --- a/libgo/go/go/printer/testdata/parser.go +++ b/libgo/go/go/printer/testdata/parser.go @@ -231,7 +231,7 @@ func (p *parser) next0() { // Because of one-token look-ahead, print the previous token // when tracing as it provides a more readable output. The // very first token (!p.pos.IsValid()) is not initialized - // (it is token.ILLEGAL), so don't print it . + // (it is token.ILLEGAL), so don't print it. if p.trace && p.pos.IsValid() { s := p.tok.String() switch { diff --git a/libgo/go/go/scanner/errors.go b/libgo/go/go/scanner/errors.go index bf7bfa3..3114f4b 100644 --- a/libgo/go/go/scanner/errors.go +++ b/libgo/go/go/scanner/errors.go @@ -86,7 +86,7 @@ func (p *ErrorList) RemoveMultiples() { i++ } } - (*p) = (*p)[0:i] + *p = (*p)[0:i] } // An ErrorList implements the error interface. diff --git a/libgo/go/go/scanner/scanner.go b/libgo/go/go/scanner/scanner.go index 00fe2dc..f08e28c 100644 --- a/libgo/go/go/scanner/scanner.go +++ b/libgo/go/go/scanner/scanner.go @@ -48,11 +48,16 @@ type Scanner struct { ErrorCount int // number of errors encountered } -const bom = 0xFEFF // byte order mark, only permitted as very first character +const ( + bom = 0xFEFF // byte order mark, only permitted as very first character + eof = -1 // end of file +) // Read the next Unicode char into s.ch. // s.ch < 0 means end-of-file. // +// For optimization, there is some overlap between this method and +// s.scanIdentifier. func (s *Scanner) next() { if s.rdOffset < len(s.src) { s.offset = s.rdOffset @@ -81,7 +86,7 @@ func (s *Scanner) next() { s.lineOffset = s.offset s.file.AddLine(s.offset) } - s.ch = -1 // eof + s.ch = eof } } @@ -347,11 +352,53 @@ func isDigit(ch rune) bool { return isDecimal(ch) || ch >= utf8.RuneSelf && unicode.IsDigit(ch) } +// scanIdentifier reads the string of valid identifier characters at s.offset. +// It must only be called when s.ch is known to be a valid letter. +// +// Be careful when making changes to this function: it is optimized and affects +// scanning performance significantly. func (s *Scanner) scanIdentifier() string { offs := s.offset - for isLetter(s.ch) || isDigit(s.ch) { + + // Optimize for the common case of an ASCII identifier. + // + // Ranging over s.src[s.rdOffset:] lets us avoid some bounds checks, and + // avoids conversions to runes. + // + // In case we encounter a non-ASCII character, fall back on the slower path + // of calling into s.next(). + for rdOffset, b := range s.src[s.rdOffset:] { + if 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z' || b == '_' || '0' <= b && b <= '9' { + // Avoid assigning a rune for the common case of an ascii character. + continue + } + s.rdOffset += rdOffset + if 0 < b && b < utf8.RuneSelf { + // Optimization: we've encountered an ASCII character that's not a letter + // or number. Avoid the call into s.next() and corresponding set up. + // + // Note that s.next() does some line accounting if s.ch is '\n', so this + // shortcut is only possible because we know that the preceding character + // is not '\n'. + s.ch = rune(b) + s.offset = s.rdOffset + s.rdOffset++ + goto exit + } + // We know that the preceding character is valid for an identifier because + // scanIdentifier is only called when s.ch is a letter, so calling s.next() + // at s.rdOffset resets the scanner state. s.next() + for isLetter(s.ch) || isDigit(s.ch) { + s.next() + } + goto exit } + s.offset = len(s.src) + s.rdOffset = len(s.src) + s.ch = eof + +exit: return string(s.src[offs:s.offset]) } @@ -383,7 +430,7 @@ func (s *Scanner) digits(base int, invalid *int) (digsep int) { if s.ch == '_' { ds = 2 } else if s.ch >= max && *invalid < 0 { - *invalid = int(s.offset) // record invalid rune offset + *invalid = s.offset // record invalid rune offset } digsep |= ds s.next() diff --git a/libgo/go/go/scanner/scanner_test.go b/libgo/go/go/scanner/scanner_test.go index ab4c2dd..db123c3 100644 --- a/libgo/go/go/scanner/scanner_test.go +++ b/libgo/go/go/scanner/scanner_test.go @@ -628,7 +628,7 @@ func TestInvalidLineDirectives(t *testing.T) { } if S.ErrorCount != len(invalidSegments) { - t.Errorf("go %d errors; want %d", S.ErrorCount, len(invalidSegments)) + t.Errorf("got %d errors; want %d", S.ErrorCount, len(invalidSegments)) } } @@ -812,6 +812,8 @@ var errors = []struct { {"//\ufeff", token.COMMENT, 2, "//\ufeff", "illegal byte order mark"}, // only first BOM is ignored {"'\ufeff" + `'`, token.CHAR, 1, "'\ufeff" + `'`, "illegal byte order mark"}, // only first BOM is ignored {`"` + "abc\ufeffdef" + `"`, token.STRING, 4, `"` + "abc\ufeffdef" + `"`, "illegal byte order mark"}, // only first BOM is ignored + {"abc\x00def", token.IDENT, 3, "abc", "illegal character NUL"}, + {"abc\x00", token.IDENT, 3, "abc", "illegal character NUL"}, } func TestScanErrors(t *testing.T) { @@ -889,26 +891,37 @@ func BenchmarkScan(b *testing.B) { } } -func BenchmarkScanFile(b *testing.B) { - b.StopTimer() - const filename = "scanner.go" - src, err := os.ReadFile(filename) - if err != nil { - panic(err) - } - fset := token.NewFileSet() - file := fset.AddFile(filename, fset.Base(), len(src)) - b.SetBytes(int64(len(src))) - var s Scanner - b.StartTimer() - for i := 0; i < b.N; i++ { - s.Init(file, src, nil, ScanComments) - for { - _, tok, _ := s.Scan() - if tok == token.EOF { - break +func BenchmarkScanFiles(b *testing.B) { + // Scan a few arbitrary large files, and one small one, to provide some + // variety in benchmarks. + for _, p := range []string{ + "go/types/expr.go", + "go/parser/parser.go", + "net/http/server.go", + "go/scanner/errors.go", + } { + b.Run(p, func(b *testing.B) { + b.StopTimer() + filename := filepath.Join("..", "..", filepath.FromSlash(p)) + src, err := os.ReadFile(filename) + if err != nil { + b.Fatal(err) } - } + fset := token.NewFileSet() + file := fset.AddFile(filename, fset.Base(), len(src)) + b.SetBytes(int64(len(src))) + var s Scanner + b.StartTimer() + for i := 0; i < b.N; i++ { + s.Init(file, src, nil, ScanComments) + for { + _, tok, _ := s.Scan() + if tok == token.EOF { + break + } + } + } + }) } } diff --git a/libgo/go/go/token/position.go b/libgo/go/go/token/position.go index a21f5fd..0d7982c 100644 --- a/libgo/go/go/token/position.go +++ b/libgo/go/go/token/position.go @@ -278,7 +278,7 @@ func (f *File) Pos(offset int) Pos { // func (f *File) Offset(p Pos) int { if int(p) < f.base || int(p) > f.base+f.size { - panic(fmt.Sprintf("invalid Pos value %d (should be in [%d, %d[)", p, f.base, f.base+f.size)) + panic(fmt.Sprintf("invalid Pos value %d (should be in [%d, %d])", p, f.base, f.base+f.size)) } return int(p) - f.base } @@ -346,7 +346,7 @@ func (f *File) position(p Pos, adjusted bool) (pos Position) { func (f *File) PositionFor(p Pos, adjusted bool) (pos Position) { if p != NoPos { if int(p) < f.base || int(p) > f.base+f.size { - panic(fmt.Sprintf("invalid Pos value %d (should be in [%d, %d[)", p, f.base, f.base+f.size)) + panic(fmt.Sprintf("invalid Pos value %d (should be in [%d, %d])", p, f.base, f.base+f.size)) } pos = f.position(p, adjusted) } @@ -540,7 +540,7 @@ func searchInts(a []int, x int) int { // TODO(gri): Remove this when compilers have caught up. i, j := 0, len(a) for i < j { - h := i + (j-i)/2 // avoid overflow when computing h + h := i + (j-i)>>1 // avoid overflow when computing h // i ≤ h < j if a[h] <= x { i = h + 1 diff --git a/libgo/go/go/token/position_bench_test.go b/libgo/go/go/token/position_bench_test.go new file mode 100644 index 0000000..41be728 --- /dev/null +++ b/libgo/go/go/token/position_bench_test.go @@ -0,0 +1,24 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package token + +import ( + "testing" +) + +func BenchmarkSearchInts(b *testing.B) { + data := make([]int, 10000) + for i := 0; i < 10000; i++ { + data[i] = i + } + const x = 8 + if r := searchInts(data, x); r != x { + b.Errorf("got index = %d; want %d", r, x) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + searchInts(data, x) + } +} diff --git a/libgo/go/go/types/api.go b/libgo/go/go/types/api.go index acd1899..d645b48 100644 --- a/libgo/go/go/types/api.go +++ b/libgo/go/go/types/api.go @@ -102,6 +102,13 @@ type ImporterFrom interface { // A Config specifies the configuration for type checking. // The zero value for Config is a ready-to-use default configuration. type Config struct { + // goVersion describes the accepted Go language version. The string + // must follow the format "go%d.%d" (e.g. "go1.12") or it must be + // empty; an empty string indicates the latest language version. + // If the format is invalid, invoking the type checker will cause a + // panic. + goVersion string + // If IgnoreFuncBodies is set, function bodies are not // type-checked. IgnoreFuncBodies bool @@ -155,95 +162,7 @@ func srcimporter_setUsesCgo(conf *Config) { conf.go115UsesCgo = true } -// Info holds result type information for a type-checked package. -// Only the information for which a map is provided is collected. -// If the package has type errors, the collected information may -// be incomplete. -type Info struct { - // Types maps expressions to their types, and for constant - // expressions, also their values. Invalid expressions are - // omitted. - // - // For (possibly parenthesized) identifiers denoting built-in - // functions, the recorded signatures are call-site specific: - // if the call result is not a constant, the recorded type is - // an argument-specific signature. Otherwise, the recorded type - // is invalid. - // - // The Types map does not record the type of every identifier, - // only those that appear where an arbitrary expression is - // permitted. For instance, the identifier f in a selector - // expression x.f is found only in the Selections map, the - // identifier z in a variable declaration 'var z int' is found - // only in the Defs map, and identifiers denoting packages in - // qualified identifiers are collected in the Uses map. - Types map[ast.Expr]TypeAndValue - - // Defs maps identifiers to the objects they define (including - // package names, dots "." of dot-imports, and blank "_" identifiers). - // For identifiers that do not denote objects (e.g., the package name - // in package clauses, or symbolic variables t in t := x.(type) of - // type switch headers), the corresponding objects are nil. - // - // For an embedded field, Defs returns the field *Var it defines. - // - // Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos() - Defs map[*ast.Ident]Object - - // Uses maps identifiers to the objects they denote. - // - // For an embedded field, Uses returns the *TypeName it denotes. - // - // Invariant: Uses[id].Pos() != id.Pos() - Uses map[*ast.Ident]Object - - // Implicits maps nodes to their implicitly declared objects, if any. - // The following node and object types may appear: - // - // node declared object - // - // *ast.ImportSpec *PkgName for imports without renames - // *ast.CaseClause type-specific *Var for each type switch case clause (incl. default) - // *ast.Field anonymous parameter *Var (incl. unnamed results) - // - Implicits map[ast.Node]Object - - // Selections maps selector expressions (excluding qualified identifiers) - // to their corresponding selections. - Selections map[*ast.SelectorExpr]*Selection - - // Scopes maps ast.Nodes to the scopes they define. Package scopes are not - // associated with a specific node but with all files belonging to a package. - // Thus, the package scope can be found in the type-checked Package object. - // Scopes nest, with the Universe scope being the outermost scope, enclosing - // the package scope, which contains (one or more) files scopes, which enclose - // function scopes which in turn enclose statement and function literal scopes. - // Note that even though package-level functions are declared in the package - // scope, the function scopes are embedded in the file scope of the file - // containing the function declaration. - // - // The following node types may appear in Scopes: - // - // *ast.File - // *ast.FuncType - // *ast.BlockStmt - // *ast.IfStmt - // *ast.SwitchStmt - // *ast.TypeSwitchStmt - // *ast.CaseClause - // *ast.CommClause - // *ast.ForStmt - // *ast.RangeStmt - // - Scopes map[ast.Node]*Scope - - // InitOrder is the list of package-level initializers in the order in which - // they must be executed. Initializers referring to variables related by an - // initialization dependency appear in topological order, the others appear - // in source order. Variables without an initialization expression do not - // appear in this list. - InitOrder []*Initializer -} +// The Info struct is found in api_notypeparams.go and api_typeparams.go. // TypeOf returns the type of expression e, or nil if not found. // Precondition: the Types, Uses and Defs maps are populated. @@ -335,6 +254,13 @@ func (tv TypeAndValue) HasOk() bool { return tv.mode == commaok || tv.mode == mapindex } +// _Inferred reports the _Inferred type arguments and signature +// for a parameterized function call that uses type inference. +type _Inferred struct { + Targs []Type + Sig *Signature +} + // An Initializer describes a package-level variable, or a list of variables in case // of a multi-valued initialization expression, and the corresponding initialization // expression. @@ -388,7 +314,7 @@ func AssignableTo(V, T Type) bool { // ConvertibleTo reports whether a value of type V is convertible to a value of type T. func ConvertibleTo(V, T Type) bool { x := operand{mode: value, typ: V} - return x.convertibleTo(nil, T) // check not needed for non-constant x + return x.convertibleTo(nil, T, nil) // check not needed for non-constant x } // Implements reports whether type V implements interface T. diff --git a/libgo/go/go/types/api_notypeparams.go b/libgo/go/go/types/api_notypeparams.go new file mode 100644 index 0000000..9f7cb7e --- /dev/null +++ b/libgo/go/go/types/api_notypeparams.go @@ -0,0 +1,104 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !typeparams +// +build !typeparams + +package types + +import "go/ast" + +// Info holds result type information for a type-checked package. +// Only the information for which a map is provided is collected. +// If the package has type errors, the collected information may +// be incomplete. +type Info struct { + // Types maps expressions to their types, and for constant + // expressions, also their values. Invalid expressions are + // omitted. + // + // For (possibly parenthesized) identifiers denoting built-in + // functions, the recorded signatures are call-site specific: + // if the call result is not a constant, the recorded type is + // an argument-specific signature. Otherwise, the recorded type + // is invalid. + // + // The Types map does not record the type of every identifier, + // only those that appear where an arbitrary expression is + // permitted. For instance, the identifier f in a selector + // expression x.f is found only in the Selections map, the + // identifier z in a variable declaration 'var z int' is found + // only in the Defs map, and identifiers denoting packages in + // qualified identifiers are collected in the Uses map. + Types map[ast.Expr]TypeAndValue + + // Defs maps identifiers to the objects they define (including + // package names, dots "." of dot-imports, and blank "_" identifiers). + // For identifiers that do not denote objects (e.g., the package name + // in package clauses, or symbolic variables t in t := x.(type) of + // type switch headers), the corresponding objects are nil. + // + // For an embedded field, Defs returns the field *Var it defines. + // + // Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos() + Defs map[*ast.Ident]Object + + // Uses maps identifiers to the objects they denote. + // + // For an embedded field, Uses returns the *TypeName it denotes. + // + // Invariant: Uses[id].Pos() != id.Pos() + Uses map[*ast.Ident]Object + + // Implicits maps nodes to their implicitly declared objects, if any. + // The following node and object types may appear: + // + // node declared object + // + // *ast.ImportSpec *PkgName for imports without renames + // *ast.CaseClause type-specific *Var for each type switch case clause (incl. default) + // *ast.Field anonymous parameter *Var (incl. unnamed results) + // + Implicits map[ast.Node]Object + + // Selections maps selector expressions (excluding qualified identifiers) + // to their corresponding selections. + Selections map[*ast.SelectorExpr]*Selection + + // Scopes maps ast.Nodes to the scopes they define. Package scopes are not + // associated with a specific node but with all files belonging to a package. + // Thus, the package scope can be found in the type-checked Package object. + // Scopes nest, with the Universe scope being the outermost scope, enclosing + // the package scope, which contains (one or more) files scopes, which enclose + // function scopes which in turn enclose statement and function literal scopes. + // Note that even though package-level functions are declared in the package + // scope, the function scopes are embedded in the file scope of the file + // containing the function declaration. + // + // The following node types may appear in Scopes: + // + // *ast.File + // *ast.FuncType + // *ast.BlockStmt + // *ast.IfStmt + // *ast.SwitchStmt + // *ast.TypeSwitchStmt + // *ast.CaseClause + // *ast.CommClause + // *ast.ForStmt + // *ast.RangeStmt + // + Scopes map[ast.Node]*Scope + + // InitOrder is the list of package-level initializers in the order in which + // they must be executed. Initializers referring to variables related by an + // initialization dependency appear in topological order, the others appear + // in source order. Variables without an initialization expression do not + // appear in this list. + InitOrder []*Initializer +} + +func getInferred(info *Info) map[ast.Expr]_Inferred { + return nil +} diff --git a/libgo/go/go/types/api_test.go b/libgo/go/go/types/api_test.go index ea1ae1e..0ff8da6 100644 --- a/libgo/go/go/types/api_test.go +++ b/libgo/go/go/types/api_test.go @@ -9,6 +9,7 @@ import ( "fmt" "go/ast" "go/importer" + "go/internal/typeparams" "go/parser" "go/token" "internal/testenv" @@ -20,9 +21,15 @@ import ( . "go/types" ) +// pkgFor parses and type checks the package specified by path and source, +// populating info if provided. +// +// If source begins with "package generic_" and type parameters are enabled, +// generic code is permitted. func pkgFor(path, source string, info *Info) (*Package, error) { fset := token.NewFileSet() - f, err := parser.ParseFile(fset, path, source, 0) + mode := modeForSource(source) + f, err := parser.ParseFile(fset, path, source, mode) if err != nil { return nil, err } @@ -43,9 +50,21 @@ func mustTypecheck(t *testing.T, path, source string, info *Info) string { return pkg.Name() } -func mayTypecheck(t *testing.T, path, source string, info *Info) string { +// genericPkg is a prefix for packages that should be type checked with +// generics. +const genericPkg = "package generic_" + +func modeForSource(src string) parser.Mode { + if !strings.HasPrefix(src, genericPkg) { + return typeparams.DisallowParsing + } + return 0 +} + +func mayTypecheck(t *testing.T, path, source string, info *Info) (string, error) { fset := token.NewFileSet() - f, err := parser.ParseFile(fset, path, source, 0) + mode := modeForSource(source) + f, err := parser.ParseFile(fset, path, source, mode) if f == nil { // ignore errors unless f is nil t.Fatalf("%s: unable to parse: %s", path, err) } @@ -53,8 +72,8 @@ func mayTypecheck(t *testing.T, path, source string, info *Info) string { Error: func(err error) {}, Importer: importer.Default(), } - pkg, _ := conf.Check(f.Name.Name, fset, []*ast.File{f}, info) - return pkg.Name() + pkg, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, info) + return pkg.Name(), err } func TestValuesInfo(t *testing.T) { @@ -176,6 +195,9 @@ func TestValuesInfo(t *testing.T) { } func TestTypesInfo(t *testing.T) { + // Test sources that are not expected to typecheck must start with the broken prefix. + const broken = "package broken_" + var tests = []struct { src string expr string // expression @@ -188,6 +210,39 @@ func TestTypesInfo(t *testing.T) { {`package b3; var x interface{} = 0i`, `0i`, `complex128`}, {`package b4; var x interface{} = "foo"`, `"foo"`, `string`}, + // uses of nil + {`package n0; var _ *int = nil`, `nil`, `untyped nil`}, + {`package n1; var _ func() = nil`, `nil`, `untyped nil`}, + {`package n2; var _ []byte = nil`, `nil`, `untyped nil`}, + {`package n3; var _ map[int]int = nil`, `nil`, `untyped nil`}, + {`package n4; var _ chan int = nil`, `nil`, `untyped nil`}, + {`package n5; var _ interface{} = nil`, `nil`, `untyped nil`}, + {`package n6; import "unsafe"; var _ unsafe.Pointer = nil`, `nil`, `untyped nil`}, + + {`package n10; var (x *int; _ = x == nil)`, `nil`, `untyped nil`}, + {`package n11; var (x func(); _ = x == nil)`, `nil`, `untyped nil`}, + {`package n12; var (x []byte; _ = x == nil)`, `nil`, `untyped nil`}, + {`package n13; var (x map[int]int; _ = x == nil)`, `nil`, `untyped nil`}, + {`package n14; var (x chan int; _ = x == nil)`, `nil`, `untyped nil`}, + {`package n15; var (x interface{}; _ = x == nil)`, `nil`, `untyped nil`}, + {`package n15; import "unsafe"; var (x unsafe.Pointer; _ = x == nil)`, `nil`, `untyped nil`}, + + {`package n20; var _ = (*int)(nil)`, `nil`, `untyped nil`}, + {`package n21; var _ = (func())(nil)`, `nil`, `untyped nil`}, + {`package n22; var _ = ([]byte)(nil)`, `nil`, `untyped nil`}, + {`package n23; var _ = (map[int]int)(nil)`, `nil`, `untyped nil`}, + {`package n24; var _ = (chan int)(nil)`, `nil`, `untyped nil`}, + {`package n25; var _ = (interface{})(nil)`, `nil`, `untyped nil`}, + {`package n26; import "unsafe"; var _ = unsafe.Pointer(nil)`, `nil`, `untyped nil`}, + + {`package n30; func f(*int) { f(nil) }`, `nil`, `untyped nil`}, + {`package n31; func f(func()) { f(nil) }`, `nil`, `untyped nil`}, + {`package n32; func f([]byte) { f(nil) }`, `nil`, `untyped nil`}, + {`package n33; func f(map[int]int) { f(nil) }`, `nil`, `untyped nil`}, + {`package n34; func f(chan int) { f(nil) }`, `nil`, `untyped nil`}, + {`package n35; func f(interface{}) { f(nil) }`, `nil`, `untyped nil`}, + {`package n35; import "unsafe"; func f(unsafe.Pointer) { f(nil) }`, `nil`, `untyped nil`}, + // comma-ok expressions {`package p0; var x interface{}; var _, _ = x.(int)`, `x.(int)`, @@ -268,18 +323,65 @@ func TestTypesInfo(t *testing.T) { `[][]struct{}`, }, + // issue 47243 + {`package issue47243_a; var x int32; var _ = x << 3`, `3`, `untyped int`}, + {`package issue47243_b; var x int32; var _ = x << 3.`, `3.`, `uint`}, // issue 47410: should be untyped float + {`package issue47243_c; var x int32; var _ = 1 << x`, `1 << x`, `int`}, + {`package issue47243_d; var x int32; var _ = 1 << x`, `1`, `int`}, + {`package issue47243_e; var x int32; var _ = 1 << 2`, `1`, `untyped int`}, + {`package issue47243_f; var x int32; var _ = 1 << 2`, `2`, `untyped int`}, + {`package issue47243_g; var x int32; var _ = int(1) << 2`, `2`, `untyped int`}, + {`package issue47243_h; var x int32; var _ = 1 << (2 << x)`, `1`, `int`}, + {`package issue47243_i; var x int32; var _ = 1 << (2 << x)`, `(2 << x)`, `untyped int`}, + {`package issue47243_j; var x int32; var _ = 1 << (2 << x)`, `2`, `untyped int`}, + // tests for broken code that doesn't parse or type-check - {`package x0; func _() { var x struct {f string}; x.f := 0 }`, `x.f`, `string`}, - {`package x1; func _() { var z string; type x struct {f string}; y := &x{q: z}}`, `z`, `string`}, - {`package x2; func _() { var a, b string; type x struct {f string}; z := &x{f: a; f: b;}}`, `b`, `string`}, - {`package x3; var x = panic("");`, `panic`, `func(interface{})`}, + {broken + `x0; func _() { var x struct {f string}; x.f := 0 }`, `x.f`, `string`}, + {broken + `x1; func _() { var z string; type x struct {f string}; y := &x{q: z}}`, `z`, `string`}, + {broken + `x2; func _() { var a, b string; type x struct {f string}; z := &x{f: a; f: b;}}`, `b`, `string`}, + {broken + `x3; var x = panic("");`, `panic`, `func(interface{})`}, {`package x4; func _() { panic("") }`, `panic`, `func(interface{})`}, - {`package x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`}, + {broken + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`}, + + // parameterized functions + {genericPkg + `p0; func f[T any](T); var _ = f[int]`, `f`, `func[T₁ interface{}](T₁)`}, + {genericPkg + `p1; func f[T any](T); var _ = f[int]`, `f[int]`, `func(int)`}, + {genericPkg + `p2; func f[T any](T); func _() { f(42) }`, `f`, `func[T₁ interface{}](T₁)`}, + {genericPkg + `p3; func f[T any](T); func _() { f(42) }`, `f(42)`, `()`}, + + // type parameters + {genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t + {genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[P₁ interface{}]`}, + {genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[P₁ interface{}]`}, + {genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[P₁, Q₂ interface{}]`}, + + // TODO (rFindley): compare with types2, which resolves the type broken_t4.t[P₁, Q₂ interface{m()}] here + {broken + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t`}, + + // instantiated types must be sanitized + {genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`}, + + // issue 45096 + {genericPkg + `issue45096; func _[T interface{ type int8, int16, int32 }](x T) { _ = x < 0 }`, `0`, `T₁`}, } for _, test := range tests { + ResetId() // avoid renumbering of type parameter ids when adding tests + if strings.HasPrefix(test.src, genericPkg) && !typeparams.Enabled { + continue + } info := Info{Types: make(map[ast.Expr]TypeAndValue)} - name := mayTypecheck(t, "TypesInfo", test.src, &info) + var name string + if strings.HasPrefix(test.src, broken) { + var err error + name, err = mayTypecheck(t, "TypesInfo", test.src, &info) + if err == nil { + t.Errorf("package %s: expected to fail but passed", name) + continue + } + } else { + name = mustTypecheck(t, "TypesInfo", test.src, &info) + } // look for expression type var typ Type @@ -301,6 +403,103 @@ func TestTypesInfo(t *testing.T) { } } +func TestDefsInfo(t *testing.T) { + var tests = []struct { + src string + obj string + want string + }{ + {`package p0; const x = 42`, `x`, `const p0.x untyped int`}, + {`package p1; const x int = 42`, `x`, `const p1.x int`}, + {`package p2; var x int`, `x`, `var p2.x int`}, + {`package p3; type x int`, `x`, `type p3.x int`}, + {`package p4; func f()`, `f`, `func p4.f()`}, + {`package p5; func f() int { x, _ := 1, 2; return x }`, `_`, `var _ int`}, + + // generic types must be sanitized + // (need to use sufficiently nested types to provoke unexpanded types) + {genericPkg + `g0; type t[P any] P; const x = t[int](42)`, `x`, `const generic_g0.x generic_g0.t[int]`}, + {genericPkg + `g1; type t[P any] P; var x = t[int](42)`, `x`, `var generic_g1.x generic_g1.t[int]`}, + {genericPkg + `g2; type t[P any] P; type x struct{ f t[int] }`, `x`, `type generic_g2.x struct{f generic_g2.t[int]}`}, + {genericPkg + `g3; type t[P any] P; func f(x struct{ f t[string] }); var g = f`, `g`, `var generic_g3.g func(x struct{f generic_g3.t[string]})`}, + } + + for _, test := range tests { + if strings.HasPrefix(test.src, genericPkg) && !typeparams.Enabled { + continue + } + info := Info{ + Defs: make(map[*ast.Ident]Object), + } + name := mustTypecheck(t, "DefsInfo", test.src, &info) + + // find object + var def Object + for id, obj := range info.Defs { + if id.Name == test.obj { + def = obj + break + } + } + if def == nil { + t.Errorf("package %s: %s not found", name, test.obj) + continue + } + + if got := def.String(); got != test.want { + t.Errorf("package %s: got %s; want %s", name, got, test.want) + } + } +} + +func TestUsesInfo(t *testing.T) { + var tests = []struct { + src string + obj string + want string + }{ + {`package p0; func _() { _ = x }; const x = 42`, `x`, `const p0.x untyped int`}, + {`package p1; func _() { _ = x }; const x int = 42`, `x`, `const p1.x int`}, + {`package p2; func _() { _ = x }; var x int`, `x`, `var p2.x int`}, + {`package p3; func _() { type _ x }; type x int`, `x`, `type p3.x int`}, + {`package p4; func _() { _ = f }; func f()`, `f`, `func p4.f()`}, + + // generic types must be sanitized + // (need to use sufficiently nested types to provoke unexpanded types) + {genericPkg + `g0; func _() { _ = x }; type t[P any] P; const x = t[int](42)`, `x`, `const generic_g0.x generic_g0.t[int]`}, + {genericPkg + `g1; func _() { _ = x }; type t[P any] P; var x = t[int](42)`, `x`, `var generic_g1.x generic_g1.t[int]`}, + {genericPkg + `g2; func _() { type _ x }; type t[P any] P; type x struct{ f t[int] }`, `x`, `type generic_g2.x struct{f generic_g2.t[int]}`}, + {genericPkg + `g3; func _() { _ = f }; type t[P any] P; func f(x struct{ f t[string] })`, `f`, `func generic_g3.f(x struct{f generic_g3.t[string]})`}, + } + + for _, test := range tests { + if strings.HasPrefix(test.src, genericPkg) && !typeparams.Enabled { + continue + } + info := Info{ + Uses: make(map[*ast.Ident]Object), + } + name := mustTypecheck(t, "UsesInfo", test.src, &info) + + // find object + var use Object + for id, obj := range info.Uses { + if id.Name == test.obj { + use = obj + break + } + } + if use == nil { + t.Errorf("package %s: %s not found", name, test.obj) + continue + } + + if got := use.String(); got != test.want { + t.Errorf("package %s: got %s; want %s", name, got, test.want) + } + } +} + func TestImplicitsInfo(t *testing.T) { testenv.MustHaveGoBuild(t) @@ -1035,6 +1234,8 @@ func TestLookupFieldOrMethod(t *testing.T) { // Test cases assume a lookup of the form a.f or x.f, where a stands for an // addressable value, and x for a non-addressable value (even though a variable // for ease of test case writing). + // + // Should be kept in sync with TestMethodSet. var tests = []struct { src string found bool @@ -1245,6 +1446,9 @@ func TestConvertibleTo(t *testing.T) { {newDefined(new(Struct)), new(Struct), true}, {newDefined(Typ[Int]), new(Struct), false}, {Typ[UntypedInt], Typ[Int], true}, + {NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Int], 10)), true}, + {NewSlice(Typ[Int]), NewArray(Typ[Int], 10), false}, + {NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Uint], 10)), false}, // Untyped string values are not permitted by the spec, so the below // behavior is undefined. {Typ[UntypedString], Typ[String], true}, diff --git a/libgo/go/go/types/api_typeparams.go b/libgo/go/go/types/api_typeparams.go new file mode 100644 index 0000000..ed744c4 --- /dev/null +++ b/libgo/go/go/types/api_typeparams.go @@ -0,0 +1,53 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build typeparams +// +build typeparams + +package types + +import ( + "go/ast" +) + +type ( + Inferred = _Inferred + Sum = _Sum + TypeParam = _TypeParam +) + +func NewSum(types []Type) Type { return _NewSum(types) } + +func (s *Signature) TParams() []*TypeName { return s._TParams() } +func (s *Signature) SetTParams(tparams []*TypeName) { s._SetTParams(tparams) } + +func (t *Interface) HasTypeList() bool { return t._HasTypeList() } +func (t *Interface) IsComparable() bool { return t._IsComparable() } +func (t *Interface) IsConstraint() bool { return t._IsConstraint() } + +func (t *Named) TParams() []*TypeName { return t._TParams() } +func (t *Named) TArgs() []Type { return t._TArgs() } +func (t *Named) SetTArgs(args []Type) { t._SetTArgs(args) } + +// Info is documented in api_notypeparams.go. +type Info struct { + Types map[ast.Expr]TypeAndValue + + // Inferred maps calls of parameterized functions that use type inference to + // the Inferred type arguments and signature of the function called. The + // recorded "call" expression may be an *ast.CallExpr (as in f(x)), or an + // *ast.IndexExpr (s in f[T]). + Inferred map[ast.Expr]_Inferred + + Defs map[*ast.Ident]Object + Uses map[*ast.Ident]Object + Implicits map[ast.Node]Object + Selections map[*ast.SelectorExpr]*Selection + Scopes map[ast.Node]*Scope + InitOrder []*Initializer +} + +func getInferred(info *Info) map[ast.Expr]_Inferred { + return info.Inferred +} diff --git a/libgo/go/go/types/api_typeparams_test.go b/libgo/go/go/types/api_typeparams_test.go new file mode 100644 index 0000000..15c9bf0 --- /dev/null +++ b/libgo/go/go/types/api_typeparams_test.go @@ -0,0 +1,139 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build typeparams +// +build typeparams + +package types_test + +import ( + "fmt" + "go/ast" + "testing" + + . "go/types" +) + +func TestInferredInfo(t *testing.T) { + var tests = []struct { + src string + fun string + targs []string + sig string + }{ + {genericPkg + `p0; func f[T any](T); func _() { f(42) }`, + `f`, + []string{`int`}, + `func(int)`, + }, + {genericPkg + `p1; func f[T any](T) T; func _() { f('@') }`, + `f`, + []string{`rune`}, + `func(rune) rune`, + }, + {genericPkg + `p2; func f[T any](...T) T; func _() { f(0i) }`, + `f`, + []string{`complex128`}, + `func(...complex128) complex128`, + }, + {genericPkg + `p3; func f[A, B, C any](A, *B, []C); func _() { f(1.2, new(string), []byte{}) }`, + `f`, + []string{`float64`, `string`, `byte`}, + `func(float64, *string, []byte)`, + }, + {genericPkg + `p4; func f[A, B any](A, *B, ...[]B); func _() { f(1.2, new(byte)) }`, + `f`, + []string{`float64`, `byte`}, + `func(float64, *byte, ...[]byte)`, + }, + + {genericPkg + `s1; func f[T any, P interface{type *T}](x T); func _(x string) { f(x) }`, + `f`, + []string{`string`, `*string`}, + `func(x string)`, + }, + {genericPkg + `s2; func f[T any, P interface{type *T}](x []T); func _(x []int) { f(x) }`, + `f`, + []string{`int`, `*int`}, + `func(x []int)`, + }, + {genericPkg + `s3; type C[T any] interface{type chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`, + `f`, + []string{`int`, `chan<- int`}, + `func(x []int)`, + }, + {genericPkg + `s4; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`, + `f`, + []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, + `func(x []int)`, + }, + + {genericPkg + `t1; func f[T any, P interface{type *T}]() T; func _() { _ = f[string] }`, + `f`, + []string{`string`, `*string`}, + `func() string`, + }, + {genericPkg + `t2; type C[T any] interface{type chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`, + `f`, + []string{`int`, `chan<- int`}, + `func() []int`, + }, + {genericPkg + `t3; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`, + `f`, + []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, + `func() []int`, + }, + } + + for _, test := range tests { + info := Info{} + info.Inferred = make(map[ast.Expr]Inferred) + name, err := mayTypecheck(t, "InferredInfo", test.src, &info) + if err != nil { + t.Errorf("package %s: %v", name, err) + continue + } + + // look for inferred type arguments and signature + var targs []Type + var sig *Signature + for call, inf := range info.Inferred { + var fun ast.Expr + switch x := call.(type) { + case *ast.CallExpr: + fun = x.Fun + case *ast.IndexExpr: + fun = x.X + default: + panic(fmt.Sprintf("unexpected call expression type %T", call)) + } + if ExprString(fun) == test.fun { + targs = inf.Targs + sig = inf.Sig + break + } + } + if targs == nil { + t.Errorf("package %s: no inferred information found for %s", name, test.fun) + continue + } + + // check that type arguments are correct + if len(targs) != len(test.targs) { + t.Errorf("package %s: got %d type arguments; want %d", name, len(targs), len(test.targs)) + continue + } + for i, targ := range targs { + if got := targ.String(); got != test.targs[i] { + t.Errorf("package %s, %d. type argument: got %s; want %s", name, i, got, test.targs[i]) + continue + } + } + + // check that signature is correct + if got := sig.String(); got != test.sig { + t.Errorf("package %s: got %s; want %s", name, got, test.sig) + } + } +} diff --git a/libgo/go/go/types/assignments.go b/libgo/go/go/types/assignments.go index 616564b..18eae62 100644 --- a/libgo/go/go/types/assignments.go +++ b/libgo/go/go/types/assignments.go @@ -7,7 +7,6 @@ package types import ( - "errors" "go/ast" "go/token" ) @@ -26,7 +25,9 @@ func (check *Checker) assignment(x *operand, T Type, context string) { case constant_, variable, mapindex, value, commaok, commaerr: // ok default: - unreachable() + // we may get here because of other problems (issue #39634, crash 12) + check.errorf(x, 0, "cannot assign %s to %s in %s", x, T, context) + return } if isUntyped(x.typ) { @@ -44,27 +45,35 @@ func (check *Checker) assignment(x *operand, T Type, context string) { } target = Default(x.typ) } - if err := check.canConvertUntyped(x, target); err != nil { + newType, val, code := check.implicitTypeAndValue(x, target) + if code != 0 { msg := check.sprintf("cannot use %s as %s value in %s", x, target, context) - code := _IncompatibleAssign - var ierr Error - if errors.As(err, &ierr) { - // Preserve these inner errors, as they are informative. - switch ierr.go116code { - case _TruncatedFloat: - msg += " (truncated)" - code = ierr.go116code - case _NumericOverflow: - msg += " (overflows)" - code = ierr.go116code - } + switch code { + case _TruncatedFloat: + msg += " (truncated)" + case _NumericOverflow: + msg += " (overflows)" + default: + code = _IncompatibleAssign } check.error(x, code, msg) x.mode = invalid return } + if val != nil { + x.val = val + check.updateExprVal(x.expr, val) + } + if newType != x.typ { + x.typ = newType + check.updateExprType(x.expr, newType, false) + } + } + + // A generic (non-instantiated) function value cannot be assigned to a variable. + if sig := asSignature(x.typ); sig != nil && len(sig.tparams) > 0 { + check.errorf(x, _Todo, "cannot use generic function %s without instantiation in %s", x, context) } - // x.typ is typed // spec: "If a left-hand side is the blank identifier, any typed or // non-constant value except for the predeclared identifier nil may @@ -148,6 +157,7 @@ func (check *Checker) initVar(lhs *Var, x *operand, context string) Type { func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type { if x.mode == invalid || x.typ == Typ[Invalid] { + check.useLHS(lhs) return nil } @@ -221,25 +231,27 @@ func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type { // If returnPos is valid, initVars is called to type-check the assignment of // return expressions, and returnPos is the position of the return statement. -func (check *Checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos) { - l := len(lhs) - get, r, commaOk := unpack(func(x *operand, i int) { check.multiExpr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid()) - if get == nil || l != r { - // invalidate lhs and use rhs +func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnPos token.Pos) { + rhs, commaOk := check.exprList(origRHS, len(lhs) == 2 && !returnPos.IsValid()) + + if len(lhs) != len(rhs) { + // invalidate lhs for _, obj := range lhs { if obj.typ == nil { obj.typ = Typ[Invalid] } } - if get == nil { - return // error reported by unpack + // don't report an error if we already reported one + for _, x := range rhs { + if x.mode == invalid { + return + } } - check.useGetter(get, r) if returnPos.IsValid() { - check.errorf(atPos(returnPos), _WrongResultCount, "wrong number of return values (want %d, got %d)", l, r) + check.errorf(atPos(returnPos), _WrongResultCount, "wrong number of return values (want %d, got %d)", len(lhs), len(rhs)) return } - check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", l, r) + check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", len(lhs), len(rhs)) return } @@ -248,50 +260,46 @@ func (check *Checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos) context = "return statement" } - var x operand if commaOk { var a [2]Type for i := range a { - get(&x, i) - a[i] = check.initVar(lhs[i], &x, context) + a[i] = check.initVar(lhs[i], rhs[i], context) } - check.recordCommaOkTypes(rhs[0], a) + check.recordCommaOkTypes(origRHS[0], a) return } for i, lhs := range lhs { - get(&x, i) - check.initVar(lhs, &x, context) + check.initVar(lhs, rhs[i], context) } } -func (check *Checker) assignVars(lhs, rhs []ast.Expr) { - l := len(lhs) - get, r, commaOk := unpack(func(x *operand, i int) { check.multiExpr(x, rhs[i]) }, len(rhs), l == 2) - if get == nil { +func (check *Checker) assignVars(lhs, origRHS []ast.Expr) { + rhs, commaOk := check.exprList(origRHS, len(lhs) == 2) + + if len(lhs) != len(rhs) { check.useLHS(lhs...) - return // error reported by unpack - } - if l != r { - check.useGetter(get, r) - check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", r, l) + // don't report an error if we already reported one + for _, x := range rhs { + if x.mode == invalid { + return + } + } + check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", len(rhs), len(lhs)) return } - var x operand if commaOk { var a [2]Type for i := range a { - get(&x, i) - a[i] = check.assignVar(lhs[i], &x) + a[i] = check.assignVar(lhs[i], rhs[i]) } - check.recordCommaOkTypes(rhs[0], a) + check.recordCommaOkTypes(origRHS[0], a) return } for i, lhs := range lhs { - get(&x, i) - check.assignVar(lhs, &x) + check.assignVar(lhs, rhs[i]) } } @@ -300,40 +308,60 @@ func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) { scope := check.scope // collect lhs variables - var newVars []*Var - var lhsVars = make([]*Var, len(lhs)) + seen := make(map[string]bool, len(lhs)) + lhsVars := make([]*Var, len(lhs)) + newVars := make([]*Var, 0, len(lhs)) + hasErr := false for i, lhs := range lhs { - var obj *Var - if ident, _ := lhs.(*ast.Ident); ident != nil { - // Use the correct obj if the ident is redeclared. The - // variable's scope starts after the declaration; so we - // must use Scope.Lookup here and call Scope.Insert - // (via check.declare) later. - name := ident.Name - if alt := scope.Lookup(name); alt != nil { - // redeclared object must be a variable - if alt, _ := alt.(*Var); alt != nil { - obj = alt - } else { - check.errorf(lhs, _UnassignableOperand, "cannot assign to %s", lhs) - } - check.recordUse(ident, alt) + ident, _ := lhs.(*ast.Ident) + if ident == nil { + check.useLHS(lhs) + // TODO(rFindley) this is redundant with a parser error. Consider omitting? + check.errorf(lhs, _BadDecl, "non-name %s on left side of :=", lhs) + hasErr = true + continue + } + + name := ident.Name + if name != "_" { + if seen[name] { + check.errorf(lhs, _RepeatedDecl, "%s repeated on left side of :=", lhs) + hasErr = true + continue + } + seen[name] = true + } + + // Use the correct obj if the ident is redeclared. The + // variable's scope starts after the declaration; so we + // must use Scope.Lookup here and call Scope.Insert + // (via check.declare) later. + if alt := scope.Lookup(name); alt != nil { + check.recordUse(ident, alt) + // redeclared object must be a variable + if obj, _ := alt.(*Var); obj != nil { + lhsVars[i] = obj } else { - // declare new variable, possibly a blank (_) variable - obj = NewVar(ident.Pos(), check.pkg, name, nil) - if name != "_" { - newVars = append(newVars, obj) - } - check.recordDef(ident, obj) + check.errorf(lhs, _UnassignableOperand, "cannot assign to %s", lhs) + hasErr = true } - } else { - check.useLHS(lhs) - check.invalidAST(lhs, "cannot declare %s", lhs) + continue } + + // declare new variable + obj := NewVar(ident.Pos(), check.pkg, name, nil) + lhsVars[i] = obj + if name != "_" { + newVars = append(newVars, obj) + } + check.recordDef(ident, obj) + } + + // create dummy variables where the lhs is invalid + for i, obj := range lhsVars { if obj == nil { - obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable + lhsVars[i] = NewVar(lhs[i].Pos(), check.pkg, "_", nil) } - lhsVars[i] = obj } check.initVars(lhsVars, rhs, token.NoPos) @@ -341,17 +369,18 @@ func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) { // process function literals in rhs expressions before scope changes check.processDelayed(top) - // declare new variables - if len(newVars) > 0 { - // spec: "The scope of a constant or variable identifier declared inside - // a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl - // for short variable declarations) and ends at the end of the innermost - // containing block." - scopePos := rhs[len(rhs)-1].End() - for _, obj := range newVars { - check.declare(scope, nil, obj, scopePos) // recordObject already called - } - } else { + if len(newVars) == 0 && !hasErr { check.softErrorf(pos, _NoNewVar, "no new variables on left side of :=") + return + } + + // declare new variables + // spec: "The scope of a constant or variable identifier declared inside + // a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl + // for short variable declarations) and ends at the end of the innermost + // containing block." + scopePos := rhs[len(rhs)-1].End() + for _, obj := range newVars { + check.declare(scope, nil, obj, scopePos) // id = nil: recordDef already called } } diff --git a/libgo/go/go/types/builtins.go b/libgo/go/go/types/builtins.go index fd35f78..2a2d54d 100644 --- a/libgo/go/go/types/builtins.go +++ b/libgo/go/go/types/builtins.go @@ -31,8 +31,8 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // For len(x) and cap(x) we need to know if x contains any function calls or // receive operations. Save/restore current setting and set hasCallOrRecv to // false for the evaluation of x so that we can check it afterwards. - // Note: We must do this _before_ calling unpack because unpack evaluates the - // first argument before we even call arg(x, 0)! + // Note: We must do this _before_ calling exprList because exprList evaluates + // all arguments. if id == _Len || id == _Cap { defer func(b bool) { check.hasCallOrRecv = b @@ -41,15 +41,14 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } // determine actual arguments - var arg getter + var arg func(*operand, int) // TODO(gri) remove use of arg getter in favor of using xlist directly nargs := len(call.Args) switch id { default: // make argument getter - arg, nargs, _ = unpack(func(x *operand, i int) { check.multiExpr(x, call.Args[i]) }, nargs, false) - if arg == nil { - return - } + xlist, _ := check.exprList(call.Args, false) + arg = func(x *operand, i int) { *x = *xlist[i]; x.typ = expand(x.typ) } + nargs = len(xlist) // evaluate first argument, if present if nargs > 0 { arg(x, 0) @@ -84,7 +83,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // of S and the respective parameter passing rules apply." S := x.typ var T Type - if s, _ := S.Underlying().(*Slice); s != nil { + if s := asSlice(S); s != nil { T = s.elem } else { check.invalidArg(x, _InvalidAppend, "%s is not a slice", x) @@ -121,14 +120,17 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // check general case by creating custom signature sig := makeSig(S, S, NewSlice(T)) // []T required for variadic signature sig.variadic = true - check.arguments(x, call, sig, func(x *operand, i int) { - // only evaluate arguments that have not been evaluated before - if i < len(alist) { - *x = alist[i] - return - } - arg(x, i) - }, nargs) + var xlist []*operand + // convert []operand to []*operand + for i := range alist { + xlist = append(xlist, &alist[i]) + } + for i := len(alist); i < nargs; i++ { + var x operand + arg(&x, i) + xlist = append(xlist, &x) + } + check.arguments(call, sig, nil, xlist) // discard result (we know the result type) // ok to continue even if check.arguments reported errors x.mode = value @@ -143,7 +145,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b mode := invalid var typ Type var val constant.Value - switch typ = implicitArrayDeref(x.typ.Underlying()); t := typ.(type) { + switch typ = implicitArrayDeref(optype(x.typ)); t := typ.(type) { case *Basic: if isString(t) && id == _Len { if x.mode == constant_ { @@ -176,6 +178,25 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b if id == _Len { mode = value } + + case *_Sum: + if t.is(func(t Type) bool { + switch t := under(t).(type) { + case *Basic: + if isString(t) && id == _Len { + return true + } + case *Array, *Slice, *Chan: + return true + case *Map: + if id == _Len { + return true + } + } + return false + }) { + mode = value + } } if mode == invalid && typ != Typ[Invalid] { @@ -196,7 +217,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b case _Close: // close(c) - c, _ := x.typ.Underlying().(*Chan) + c := asChan(x.typ) if c == nil { check.invalidArg(x, _InvalidClose, "%s is not a channel", x) return @@ -271,7 +292,21 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } // the argument types must be of floating-point type - if !isFloat(x.typ) { + f := func(x Type) Type { + if t := asBasic(x); t != nil { + switch t.kind { + case Float32: + return Typ[Complex64] + case Float64: + return Typ[Complex128] + case UntypedFloat: + return Typ[UntypedComplex] + } + } + return nil + } + resTyp := check.applyTypeFunc(f, x.typ) + if resTyp == nil { check.invalidArg(x, _InvalidComplex, "arguments have type %s, expected floating-point", x.typ) return } @@ -283,20 +318,6 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b x.mode = value } - // determine result type - var res BasicKind - switch x.typ.Underlying().(*Basic).kind { - case Float32: - res = Complex64 - case Float64: - res = Complex128 - case UntypedFloat: - res = UntypedComplex - default: - unreachable() - } - resTyp := Typ[res] - if check.Types != nil && x.mode != constant_ { check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ, x.typ)) } @@ -306,7 +327,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b case _Copy: // copy(x, y []T) int var dst Type - if t, _ := x.typ.Underlying().(*Slice); t != nil { + if t := asSlice(x.typ); t != nil { dst = t.elem } @@ -316,7 +337,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return } var src Type - switch t := y.typ.Underlying().(type) { + switch t := optype(y.typ).(type) { case *Basic: if isString(y.typ) { src = universeByte @@ -343,7 +364,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b case _Delete: // delete(m, k) - m, _ := x.typ.Underlying().(*Map) + m := asMap(x.typ) if m == nil { check.invalidArg(x, _InvalidDelete, "%s is not a map", x) return @@ -353,8 +374,8 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return } - if ok, code := x.assignableTo(check, m.key, nil); !ok { - check.invalidArg(x, code, "%s is not assignable to %s", x, m.key) + check.assignment(x, m.key, "argument to delete") + if x.mode == invalid { return } @@ -389,7 +410,21 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } // the argument must be of complex type - if !isComplex(x.typ) { + f := func(x Type) Type { + if t := asBasic(x); t != nil { + switch t.kind { + case Complex64: + return Typ[Float32] + case Complex128: + return Typ[Float64] + case UntypedComplex: + return Typ[UntypedFloat] + } + } + return nil + } + resTyp := check.applyTypeFunc(f, x.typ) + if resTyp == nil { code := _InvalidImag if id == _Real { code = _InvalidReal @@ -409,20 +444,6 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b x.mode = value } - // determine result type - var res BasicKind - switch x.typ.Underlying().(*Basic).kind { - case Complex64: - res = Float32 - case Complex128: - res = Float64 - case UntypedComplex: - res = UntypedFloat - default: - unreachable() - } - resTyp := Typ[res] - if check.Types != nil && x.mode != constant_ { check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ)) } @@ -434,25 +455,47 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // make(T, n, m) // (no argument evaluated yet) arg0 := call.Args[0] - T := check.typ(arg0) + T := check.varType(arg0) if T == Typ[Invalid] { return } - var min int // minimum number of arguments - switch T.Underlying().(type) { - case *Slice: - min = 2 - case *Map, *Chan: - min = 1 - default: + min, max := -1, 10 + var valid func(t Type) bool + valid = func(t Type) bool { + var m int + switch t := optype(t).(type) { + case *Slice: + m = 2 + case *Map, *Chan: + m = 1 + case *_Sum: + return t.is(valid) + default: + return false + } + if m > min { + min = m + } + if m+1 < max { + max = m + 1 + } + return true + } + + if !valid(T) { check.invalidArg(arg0, _InvalidMake, "cannot make %s; type must be slice, map, or channel", arg0) return } - if nargs < min || min+1 < nargs { - check.errorf(call, _WrongArgCount, "%v expects %d or %d arguments; found %d", call, min, min+1, nargs) + if nargs < min || max < nargs { + if min == max { + check.errorf(call, _WrongArgCount, "%v expects %d arguments; found %d", call, min, nargs) + } else { + check.errorf(call, _WrongArgCount, "%v expects %d or %d arguments; found %d", call, min, max, nargs) + } return } + types := []Type{T} var sizes []int64 // constant integer arguments, if any for _, arg := range call.Args[1:] { @@ -475,7 +518,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b case _New: // new(T) // (no argument evaluated yet) - T := check.typ(call.Args[0]) + T := check.varType(call.Args[0]) if T == Typ[Invalid] { return } @@ -543,8 +586,36 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b check.recordBuiltinType(call.Fun, makeSig(x.typ)) } + case _Add: + // unsafe.Add(ptr unsafe.Pointer, len IntegerType) unsafe.Pointer + if !check.allowVersion(check.pkg, 1, 17) { + check.errorf(call.Fun, _InvalidUnsafeAdd, "unsafe.Add requires go1.17 or later") + return + } + + check.assignment(x, Typ[UnsafePointer], "argument to unsafe.Add") + if x.mode == invalid { + return + } + + var y operand + arg(&y, 1) + if !check.isValidIndex(&y, _InvalidUnsafeAdd, "length", true) { + return + } + + x.mode = value + x.typ = Typ[UnsafePointer] + if check.Types != nil { + check.recordBuiltinType(call.Fun, makeSig(x.typ, x.typ, y.typ)) + } + case _Alignof: // unsafe.Alignof(x T) uintptr + if asTypeParam(x.typ) != nil { + check.invalidOp(call, _Todo, "unsafe.Alignof undefined for %s", x) + return + } check.assignment(x, nil, "argument to unsafe.Alignof") if x.mode == invalid { return @@ -602,6 +673,10 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b case _Sizeof: // unsafe.Sizeof(x T) uintptr + if asTypeParam(x.typ) != nil { + check.invalidOp(call, _Todo, "unsafe.Sizeof undefined for %s", x) + return + } check.assignment(x, nil, "argument to unsafe.Sizeof") if x.mode == invalid { return @@ -612,6 +687,31 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b x.typ = Typ[Uintptr] // result is constant - no need to record signature + case _Slice: + // unsafe.Slice(ptr *T, len IntegerType) []T + if !check.allowVersion(check.pkg, 1, 17) { + check.errorf(call.Fun, _InvalidUnsafeSlice, "unsafe.Slice requires go1.17 or later") + return + } + + typ := asPointer(x.typ) + if typ == nil { + check.invalidArg(x, _InvalidUnsafeSlice, "%s is not a pointer", x) + return + } + + var y operand + arg(&y, 1) + if !check.isValidIndex(&y, _InvalidUnsafeSlice, "length", false) { + return + } + + x.mode = value + x.typ = NewSlice(typ.base) + if check.Types != nil { + check.recordBuiltinType(call.Fun, makeSig(x.typ, typ, y.typ)) + } + case _Assert: // assert(pred) causes a typechecker error if pred is false. // The result of assert is the value of pred if there is no error. @@ -657,6 +757,40 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b return true } +// applyTypeFunc applies f to x. If x is a type parameter, +// the result is a type parameter constrained by an new +// interface bound. The type bounds for that interface +// are computed by applying f to each of the type bounds +// of x. If any of these applications of f return nil, +// applyTypeFunc returns nil. +// If x is not a type parameter, the result is f(x). +func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type { + if tp := asTypeParam(x); tp != nil { + // Test if t satisfies the requirements for the argument + // type and collect possible result types at the same time. + var rtypes []Type + if !tp.Bound().is(func(x Type) bool { + if r := f(x); r != nil { + rtypes = append(rtypes, r) + return true + } + return false + }) { + return nil + } + + // construct a suitable new type parameter + tpar := NewTypeName(token.NoPos, nil /* = Universe pkg */, "<type parameter>", nil) + ptyp := check.newTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect + tsum := _NewSum(rtypes) + ptyp.bound = &Interface{types: tsum, allMethods: markComplete, allTypes: tsum} + + return ptyp + } + + return f(x) +} + // makeSig makes a signature for the given argument and result types. // Default types are used for untyped arguments, and res may be nil. func makeSig(res Type, args ...Type) *Signature { @@ -678,7 +812,7 @@ func makeSig(res Type, args ...Type) *Signature { // func implicitArrayDeref(typ Type) Type { if p, ok := typ.(*Pointer); ok { - if a, ok := p.base.Underlying().(*Array); ok { + if a := asArray(p.base); a != nil { return a } } diff --git a/libgo/go/go/types/builtins_test.go b/libgo/go/go/types/builtins_test.go index 092e524..c4830d9 100644 --- a/libgo/go/go/types/builtins_test.go +++ b/libgo/go/go/types/builtins_test.go @@ -87,6 +87,9 @@ var builtinCalls = []struct { {"make", `var c int32; _ = make([]float64 , 0, c)`, `func([]float64, int, int32) []float64`}, {"make", `var l, c uint ; _ = make([]complex128, l, c)`, `func([]complex128, uint, uint) []complex128`}, + // issue #45667 + {"make", `const l uint = 1; _ = make([]int, l)`, `func([]int, uint) []int`}, + {"new", `_ = new(int)`, `func(int) *int`}, {"new", `type T struct{}; _ = new(T)`, `func(p.T) *p.T`}, @@ -104,6 +107,10 @@ var builtinCalls = []struct { {"recover", `recover()`, `func() interface{}`}, {"recover", `_ = recover()`, `func() interface{}`}, + {"Add", `var p unsafe.Pointer; _ = unsafe.Add(p, -1.0)`, `func(unsafe.Pointer, int) unsafe.Pointer`}, + {"Add", `var p unsafe.Pointer; var n uintptr; _ = unsafe.Add(p, n)`, `func(unsafe.Pointer, uintptr) unsafe.Pointer`}, + {"Add", `_ = unsafe.Add(nil, 0)`, `func(unsafe.Pointer, int) unsafe.Pointer`}, + {"Alignof", `_ = unsafe.Alignof(0)`, `invalid type`}, // constant {"Alignof", `var x struct{}; _ = unsafe.Alignof(x)`, `invalid type`}, // constant @@ -113,6 +120,9 @@ var builtinCalls = []struct { {"Sizeof", `_ = unsafe.Sizeof(0)`, `invalid type`}, // constant {"Sizeof", `var x struct{}; _ = unsafe.Sizeof(x)`, `invalid type`}, // constant + {"Slice", `var p *int; _ = unsafe.Slice(p, 1)`, `func(*int, int) []int`}, + {"Slice", `var p *byte; var n uintptr; _ = unsafe.Slice(p, n)`, `func(*byte, uintptr) []byte`}, + {"assert", `assert(true)`, `invalid type`}, // constant {"assert", `type B bool; const pred B = 1 < 2; assert(pred)`, `invalid type`}, // constant diff --git a/libgo/go/go/types/call.go b/libgo/go/go/types/call.go index 6765b17..631ea42 100644 --- a/libgo/go/go/types/call.go +++ b/libgo/go/go/types/call.go @@ -8,313 +8,352 @@ package types import ( "go/ast" + "go/internal/typeparams" "go/token" "strings" "unicode" ) -func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind { - check.exprOrType(x, e.Fun) +// funcInst type-checks a function instantiation inst and returns the result in x. +// The operand x must be the evaluation of inst.X and its type must be a signature. +func (check *Checker) funcInst(x *operand, inst *ast.IndexExpr) { + xlist := typeparams.UnpackExpr(inst.Index) + targs := check.typeList(xlist) + if targs == nil { + x.mode = invalid + x.expr = inst + return + } + assert(len(targs) == len(xlist)) + + // check number of type arguments (got) vs number of type parameters (want) + sig := x.typ.(*Signature) + got, want := len(targs), len(sig.tparams) + if got > want { + check.errorf(xlist[got-1], _Todo, "got %d type arguments but want %d", got, want) + x.mode = invalid + x.expr = inst + return + } + + // if we don't have enough type arguments, try type inference + inferred := false + + if got < want { + targs = check.infer(inst, sig.tparams, targs, nil, nil, true) + if targs == nil { + // error was already reported + x.mode = invalid + x.expr = inst + return + } + got = len(targs) + inferred = true + } + assert(got == want) + + // determine argument positions (for error reporting) + // TODO(rFindley) use a positioner here? instantiate would need to be + // updated accordingly. + poslist := make([]token.Pos, len(xlist)) + for i, x := range xlist { + poslist[i] = x.Pos() + } + + // instantiate function signature + res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature) + assert(res.tparams == nil) // signature is not generic anymore + if inferred { + check.recordInferred(inst, targs, res) + } + x.typ = res + x.mode = value + x.expr = inst +} + +func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { + var inst *ast.IndexExpr + if iexpr, _ := call.Fun.(*ast.IndexExpr); iexpr != nil { + if check.indexExpr(x, iexpr) { + // Delay function instantiation to argument checking, + // where we combine type and value arguments for type + // inference. + assert(x.mode == value) + inst = iexpr + } + x.expr = iexpr + check.record(x) + } else { + check.exprOrType(x, call.Fun) + } switch x.mode { case invalid: - check.use(e.Args...) - x.mode = invalid - x.expr = e + check.use(call.Args...) + x.expr = call return statement case typexpr: // conversion T := x.typ x.mode = invalid - switch n := len(e.Args); n { + switch n := len(call.Args); n { case 0: - check.errorf(inNode(e, e.Rparen), _WrongArgCount, "missing argument in conversion to %s", T) + check.errorf(inNode(call, call.Rparen), _WrongArgCount, "missing argument in conversion to %s", T) case 1: - check.expr(x, e.Args[0]) + check.expr(x, call.Args[0]) if x.mode != invalid { - if e.Ellipsis.IsValid() { - check.errorf(e.Args[0], _BadDotDotDotSyntax, "invalid use of ... in conversion to %s", T) + if call.Ellipsis.IsValid() { + check.errorf(call.Args[0], _BadDotDotDotSyntax, "invalid use of ... in conversion to %s", T) break } + if t := asInterface(T); t != nil { + check.completeInterface(token.NoPos, t) + if t._IsConstraint() { + check.errorf(call, _Todo, "cannot use interface %s in conversion (contains type list or is comparable)", T) + break + } + } check.conversion(x, T) } default: - check.use(e.Args...) - check.errorf(e.Args[n-1], _WrongArgCount, "too many arguments in conversion to %s", T) + check.use(call.Args...) + check.errorf(call.Args[n-1], _WrongArgCount, "too many arguments in conversion to %s", T) } - x.expr = e + x.expr = call return conversion case builtin: id := x.id - if !check.builtin(x, e, id) { + if !check.builtin(x, call, id) { x.mode = invalid } - x.expr = e + x.expr = call // a non-constant result implies a function call if x.mode != invalid && x.mode != constant_ { check.hasCallOrRecv = true } return predeclaredFuncs[id].kind + } - default: - // function/method call - cgocall := x.mode == cgofunc + // ordinary function/method call + cgocall := x.mode == cgofunc - sig, _ := x.typ.Underlying().(*Signature) - if sig == nil { - check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x) + sig := asSignature(x.typ) + if sig == nil { + check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x) + x.mode = invalid + x.expr = call + return statement + } + + // evaluate type arguments, if any + var targs []Type + if inst != nil { + xlist := typeparams.UnpackExpr(inst.Index) + targs = check.typeList(xlist) + if targs == nil { + check.use(call.Args...) x.mode = invalid - x.expr = e + x.expr = call return statement } + assert(len(targs) == len(xlist)) - arg, n, _ := unpack(func(x *operand, i int) { check.multiExpr(x, e.Args[i]) }, len(e.Args), false) - if arg != nil { - check.arguments(x, e, sig, arg, n) - } else { + // check number of type arguments (got) vs number of type parameters (want) + got, want := len(targs), len(sig.tparams) + if got > want { + check.errorf(xlist[want], _Todo, "got %d type arguments but want %d", got, want) + check.use(call.Args...) x.mode = invalid + x.expr = call + return statement } + } - // determine result - switch sig.results.Len() { - case 0: - x.mode = novalue - case 1: - if cgocall { - x.mode = commaerr - } else { - x.mode = value - } - x.typ = sig.results.vars[0].typ // unpack tuple - default: + // evaluate arguments + args, _ := check.exprList(call.Args, false) + sig = check.arguments(call, sig, targs, args) + + // determine result + switch sig.results.Len() { + case 0: + x.mode = novalue + case 1: + if cgocall { + x.mode = commaerr + } else { x.mode = value - x.typ = sig.results } - - x.expr = e - check.hasCallOrRecv = true - - return statement + x.typ = sig.results.vars[0].typ // unpack tuple + default: + x.mode = value + x.typ = sig.results } -} + x.expr = call + check.hasCallOrRecv = true -// use type-checks each argument. -// Useful to make sure expressions are evaluated -// (and variables are "used") in the presence of other errors. -// The arguments may be nil. -func (check *Checker) use(arg ...ast.Expr) { - var x operand - for _, e := range arg { - // The nil check below is necessary since certain AST fields - // may legally be nil (e.g., the ast.SliceExpr.High field). - if e != nil { - check.rawExpr(&x, e, nil) - } + // if type inference failed, a parametrized result must be invalidated + // (operands cannot have a parametrized type) + if x.mode == value && len(sig.tparams) > 0 && isParameterized(sig.tparams, x.typ) { + x.mode = invalid } + + return statement } -// useLHS is like use, but doesn't "use" top-level identifiers. -// It should be called instead of use if the arguments are -// expressions on the lhs of an assignment. -// The arguments must not be nil. -func (check *Checker) useLHS(arg ...ast.Expr) { - var x operand - for _, e := range arg { - // If the lhs is an identifier denoting a variable v, this assignment - // is not a 'use' of v. Remember current value of v.used and restore - // after evaluating the lhs via check.rawExpr. - var v *Var - var v_used bool - if ident, _ := unparen(e).(*ast.Ident); ident != nil { - // never type-check the blank name on the lhs - if ident.Name == "_" { - continue +func (check *Checker) exprList(elist []ast.Expr, allowCommaOk bool) (xlist []*operand, commaOk bool) { + switch len(elist) { + case 0: + // nothing to do + + case 1: + // single (possibly comma-ok) value, or function returning multiple values + e := elist[0] + var x operand + check.multiExpr(&x, e) + if t, ok := x.typ.(*Tuple); ok && x.mode != invalid { + // multiple values + xlist = make([]*operand, t.Len()) + for i, v := range t.vars { + xlist[i] = &operand{mode: value, expr: e, typ: v.typ} } - if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil { - // It's ok to mark non-local variables, but ignore variables - // from other packages to avoid potential race conditions with - // dot-imported variables. - if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg { - v = w - v_used = v.used - } - } - } - check.rawExpr(&x, e, nil) - if v != nil { - v.used = v_used // restore v.used + break } - } -} - -// useGetter is like use, but takes a getter instead of a list of expressions. -// It should be called instead of use if a getter is present to avoid repeated -// evaluation of the first argument (since the getter was likely obtained via -// unpack, which may have evaluated the first argument already). -func (check *Checker) useGetter(get getter, n int) { - var x operand - for i := 0; i < n; i++ { - get(&x, i) - } -} -// A getter sets x as the i'th operand, where 0 <= i < n and n is the total -// number of operands (context-specific, and maintained elsewhere). A getter -// type-checks the i'th operand; the details of the actual check are getter- -// specific. -type getter func(x *operand, i int) - -// unpack takes a getter get and a number of operands n. If n == 1, unpack -// calls the incoming getter for the first operand. If that operand is -// invalid, unpack returns (nil, 0, false). Otherwise, if that operand is a -// function call, or a comma-ok expression and allowCommaOk is set, the result -// is a new getter and operand count providing access to the function results, -// or comma-ok values, respectively. The third result value reports if it -// is indeed the comma-ok case. In all other cases, the incoming getter and -// operand count are returned unchanged, and the third result value is false. -// -// In other words, if there's exactly one operand that - after type-checking -// by calling get - stands for multiple operands, the resulting getter provides -// access to those operands instead. -// -// If the returned getter is called at most once for a given operand index i -// (including i == 0), that operand is guaranteed to cause only one call of -// the incoming getter with that i. -// -func unpack(get getter, n int, allowCommaOk bool) (getter, int, bool) { - if n != 1 { - // zero or multiple values - return get, n, false - } - // possibly result of an n-valued function call or comma,ok value - var x0 operand - get(&x0, 0) - if x0.mode == invalid { - return nil, 0, false - } - - if t, ok := x0.typ.(*Tuple); ok { - // result of an n-valued function call - return func(x *operand, i int) { + // exactly one (possibly invalid or comma-ok) value + xlist = []*operand{&x} + if allowCommaOk && (x.mode == mapindex || x.mode == commaok || x.mode == commaerr) { x.mode = value - x.expr = x0.expr - x.typ = t.At(i).typ - }, t.Len(), false - } - - if x0.mode == mapindex || x0.mode == commaok || x0.mode == commaerr { - // comma-ok value - if allowCommaOk { - a := [2]Type{x0.typ, Typ[UntypedBool]} - if x0.mode == commaerr { - a[1] = universeError + x2 := &operand{mode: value, expr: e, typ: Typ[UntypedBool]} + if x.mode == commaerr { + x2.typ = universeError } - return func(x *operand, i int) { - x.mode = value - x.expr = x0.expr - x.typ = a[i] - }, 2, true + xlist = append(xlist, x2) + commaOk = true } - x0.mode = value - } - // single value - return func(x *operand, i int) { - if i != 0 { - unreachable() + default: + // multiple (possibly invalid) values + xlist = make([]*operand, len(elist)) + for i, e := range elist { + var x operand + check.expr(&x, e) + xlist[i] = &x } - *x = x0 - }, 1, false + } + + return } -// arguments checks argument passing for the call with the given signature. -// The arg function provides the operand for the i'th argument. -func (check *Checker) arguments(x *operand, call *ast.CallExpr, sig *Signature, arg getter, n int) { - if call.Ellipsis.IsValid() { - // last argument is of the form x... - if !sig.variadic { - check.errorf(atPos(call.Ellipsis), _NonVariadicDotDotDot, "cannot use ... in call to non-variadic %s", call.Fun) - check.useGetter(arg, n) +func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type, args []*operand) (rsig *Signature) { + rsig = sig + + // TODO(gri) try to eliminate this extra verification loop + for _, a := range args { + switch a.mode { + case typexpr: + check.errorf(a, 0, "%s used as value", a) return - } - if len(call.Args) == 1 && n > 1 { - // f()... is not permitted if f() is multi-valued - check.errorf(atPos(call.Ellipsis), _InvalidDotDotDotOperand, "cannot use ... with %d-valued %s", n, call.Args[0]) - check.useGetter(arg, n) + case invalid: return } } - // evaluate arguments - context := check.sprintf("argument to %s", call.Fun) - for i := 0; i < n; i++ { - arg(x, i) - if x.mode != invalid { - var ellipsis token.Pos - if i == n-1 && call.Ellipsis.IsValid() { - ellipsis = call.Ellipsis + // Function call argument/parameter count requirements + // + // | standard call | dotdotdot call | + // --------------+------------------+----------------+ + // standard func | nargs == npars | invalid | + // --------------+------------------+----------------+ + // variadic func | nargs >= npars-1 | nargs == npars | + // --------------+------------------+----------------+ + + nargs := len(args) + npars := sig.params.Len() + ddd := call.Ellipsis.IsValid() + + // set up parameters + sigParams := sig.params // adjusted for variadic functions (may be nil for empty parameter lists!) + adjusted := false // indicates if sigParams is different from t.params + if sig.variadic { + if ddd { + // variadic_func(a, b, c...) + if len(call.Args) == 1 && nargs > 1 { + // f()... is not permitted if f() is multi-valued + check.errorf(inNode(call, call.Ellipsis), _InvalidDotDotDot, "cannot use ... with %d-valued %s", nargs, call.Args[0]) + return + } + } else { + // variadic_func(a, b, c) + if nargs >= npars-1 { + // Create custom parameters for arguments: keep + // the first npars-1 parameters and add one for + // each argument mapping to the ... parameter. + vars := make([]*Var, npars-1) // npars > 0 for variadic functions + copy(vars, sig.params.vars) + last := sig.params.vars[npars-1] + typ := last.typ.(*Slice).elem + for len(vars) < nargs { + vars = append(vars, NewParam(last.pos, last.pkg, last.name, typ)) + } + sigParams = NewTuple(vars...) // possibly nil! + adjusted = true + npars = nargs + } else { + // nargs < npars-1 + npars-- // for correct error message below } - check.argument(sig, i, x, ellipsis, context) } + } else { + if ddd { + // standard_func(a, b, c...) + check.errorf(inNode(call, call.Ellipsis), _NonVariadicDotDotDot, "cannot use ... in call to non-variadic %s", call.Fun) + return + } + // standard_func(a, b, c) } // check argument count - if sig.variadic { - // a variadic function accepts an "empty" - // last argument: count one extra - n++ - } - if n < sig.params.Len() { - check.errorf(inNode(call, call.Rparen), _WrongArgCount, "too few arguments in call to %s", call.Fun) - // ok to continue - } -} - -// argument checks passing of argument x to the i'th parameter of the given signature. -// If ellipsis is valid, the argument is followed by ... at that position in the call. -func (check *Checker) argument(sig *Signature, i int, x *operand, ellipsis token.Pos, context string) { - check.singleValue(x) - if x.mode == invalid { + switch { + case nargs < npars: + check.errorf(inNode(call, call.Rparen), _WrongArgCount, "not enough arguments in call to %s", call.Fun) + return + case nargs > npars: + check.errorf(args[npars], _WrongArgCount, "too many arguments in call to %s", call.Fun) // report at first extra argument return } - n := sig.params.Len() + // infer type arguments and instantiate signature if necessary + if len(sig.tparams) > 0 { + // TODO(gri) provide position information for targs so we can feed + // it to the instantiate call for better error reporting + targs := check.infer(call, sig.tparams, targs, sigParams, args, true) + if targs == nil { + return // error already reported + } + + // compute result signature + rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature) + assert(rsig.tparams == nil) // signature is not generic anymore + check.recordInferred(call, targs, rsig) - // determine parameter type - var typ Type - switch { - case i < n: - typ = sig.params.vars[i].typ - case sig.variadic: - typ = sig.params.vars[n-1].typ - if debug { - if _, ok := typ.(*Slice); !ok { - check.dump("%v: expected unnamed slice type, got %s", sig.params.vars[n-1].Pos(), typ) - } + // Optimization: Only if the parameter list was adjusted do we + // need to compute it from the adjusted list; otherwise we can + // simply use the result signature's parameter list. + if adjusted { + sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.tparams, targs)).(*Tuple) + } else { + sigParams = rsig.params } - default: - check.errorf(x, _WrongArgCount, "too many arguments") - return } - if ellipsis.IsValid() { - if i != n-1 { - check.errorf(atPos(ellipsis), _MisplacedDotDotDot, "can only use ... with matching parameter") - return - } - // argument is of the form x... and x is single-valued - if _, ok := x.typ.Underlying().(*Slice); !ok && x.typ != Typ[UntypedNil] { // see issue #18268 - check.errorf(x, _InvalidDotDotDotOperand, "cannot use %s as parameter of type %s", x, typ) - return - } - } else if sig.variadic && i >= n-1 { - // use the variadic parameter slice's element type - typ = typ.(*Slice).elem + // check arguments + for i, a := range args { + check.assignment(a, sigParams.vars[i].typ, check.sprintf("argument to %s", call.Fun)) } - check.assignment(x, typ, context) + return } var cgoPrefixes = [...]string{ @@ -417,7 +456,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { x.typ = exp.typ x.id = exp.id default: - check.dump("unexpected object %v", exp) + check.dump("%v: unexpected object %v", e.Sel.Pos(), exp) unreachable() } x.expr = e @@ -430,6 +469,8 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { goto Error } + check.instantiatedOperand(x) + obj, index, indirect = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel) if obj == nil { switch { @@ -439,8 +480,20 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { case indirect: check.errorf(e.Sel, _InvalidMethodExpr, "cannot call pointer method %s on %s", sel, x.typ) default: - // Check if capitalization of sel matters and provide better error - // message in that case. + var why string + if tpar := asTypeParam(x.typ); tpar != nil { + // Type parameter bounds don't specify fields, so don't mention "field". + switch obj := tpar.Bound().obj.(type) { + case nil: + why = check.sprintf("type bound for %s has no method %s", x.typ, sel) + case *TypeName: + why = check.sprintf("interface %s has no method %s", obj.name, sel) + } + } else { + why = check.sprintf("type %s has no field or method %s", x.typ, sel) + } + + // Check if capitalization of sel matters and provide better error message in that case. if len(sel) > 0 { var changeCase string if r := rune(sel[0]); unicode.IsUpper(r) { @@ -449,11 +502,11 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { changeCase = string(unicode.ToUpper(r)) + sel[1:] } if obj, _, _ = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, changeCase); obj != nil { - check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no field or method %s, but does have %s)", x.expr, sel, x.typ, sel, changeCase) - break + why += ", but does have " + changeCase } } - check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no field or method %s)", x.expr, sel, x.typ, sel) + + check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (%s)", x.expr, sel, why) } goto Error } @@ -461,6 +514,54 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { // methods may not have a fully set up signature yet if m, _ := obj.(*Func); m != nil { check.objDecl(m, nil) + // If m has a parameterized receiver type, infer the type arguments from + // the actual receiver provided and then substitute the type parameters in + // the signature accordingly. + // TODO(gri) factor this code out + sig := m.typ.(*Signature) + if len(sig.rparams) > 0 { + // For inference to work, we must use the receiver type + // matching the receiver in the actual method declaration. + // If the method is embedded, the matching receiver is the + // embedded struct or interface that declared the method. + // Traverse the embedding to find that type (issue #44688). + recv := x.typ + for i := 0; i < len(index)-1; i++ { + // The embedded type is either a struct or a pointer to + // a struct except for the last one (which we don't need). + recv = asStruct(derefStructPtr(recv)).Field(index[i]).typ + } + + // The method may have a pointer receiver, but the actually provided receiver + // may be a (hopefully addressable) non-pointer value, or vice versa. Here we + // only care about inferring receiver type parameters; to make the inference + // work, match up pointer-ness of receiver and argument. + if ptrRecv := isPointer(sig.recv.typ); ptrRecv != isPointer(recv) { + if ptrRecv { + recv = NewPointer(recv) + } else { + recv = recv.(*Pointer).base + } + } + // Disable reporting of errors during inference below. If we're unable to infer + // the receiver type arguments here, the receiver must be be otherwise invalid + // and an error has been reported elsewhere. + arg := operand{mode: variable, expr: x.expr, typ: recv} + targs := check.infer(m, sig.rparams, nil, NewTuple(sig.recv), []*operand{&arg}, false /* no error reporting */) + if targs == nil { + // We may reach here if there were other errors (see issue #40056). + goto Error + } + // Don't modify m. Instead - for now - make a copy of m and use that instead. + // (If we modify m, some tests will fail; possibly because the m is in use.) + // TODO(gri) investigate and provide a correct explanation here + copy := *m + copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.rparams, targs)) + obj = © + } + // TODO(gri) we also need to do substitution for parameterized interface methods + // (this breaks code in testdata/linalg.go2 at the moment) + // 12/20/2019: Is this TODO still correct? } if x.mode == typexpr { @@ -483,7 +584,8 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { } x.mode = value x.typ = &Signature{ - params: NewTuple(append([]*Var{NewVar(token.NoPos, check.pkg, "", x.typ)}, params...)...), + tparams: sig.tparams, + params: NewTuple(append([]*Var{NewVar(token.NoPos, check.pkg, "_", x.typ)}, params...)...), results: sig.results, variadic: sig.variadic, } @@ -507,7 +609,14 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { // addressability, should we report the type &(x.typ) instead? check.recordSelection(e, MethodVal, x.typ, obj, index, indirect) - if debug { + // TODO(gri) The verification pass below is disabled for now because + // method sets don't match method lookup in some cases. + // For instance, if we made a copy above when creating a + // custom method for a parameterized received type, the + // method set method doesn't match (no copy there). There + /// may be other situations. + disabled := true + if !disabled && debug { // Verify that LookupFieldOrMethod and MethodSet.Lookup agree. // TODO(gri) This only works because we call LookupFieldOrMethod // _before_ calling NewMethodSet: LookupFieldOrMethod completes @@ -567,3 +676,60 @@ Error: x.mode = invalid x.expr = e } + +// use type-checks each argument. +// Useful to make sure expressions are evaluated +// (and variables are "used") in the presence of other errors. +// The arguments may be nil. +func (check *Checker) use(arg ...ast.Expr) { + var x operand + for _, e := range arg { + // The nil check below is necessary since certain AST fields + // may legally be nil (e.g., the ast.SliceExpr.High field). + if e != nil { + check.rawExpr(&x, e, nil) + } + } +} + +// useLHS is like use, but doesn't "use" top-level identifiers. +// It should be called instead of use if the arguments are +// expressions on the lhs of an assignment. +// The arguments must not be nil. +func (check *Checker) useLHS(arg ...ast.Expr) { + var x operand + for _, e := range arg { + // If the lhs is an identifier denoting a variable v, this assignment + // is not a 'use' of v. Remember current value of v.used and restore + // after evaluating the lhs via check.rawExpr. + var v *Var + var v_used bool + if ident, _ := unparen(e).(*ast.Ident); ident != nil { + // never type-check the blank name on the lhs + if ident.Name == "_" { + continue + } + if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil { + // It's ok to mark non-local variables, but ignore variables + // from other packages to avoid potential race conditions with + // dot-imported variables. + if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg { + v = w + v_used = v.used + } + } + } + check.rawExpr(&x, e, nil) + if v != nil { + v.used = v_used // restore v.used + } + } +} + +// instantiatedOperand reports an error of x is an uninstantiated (generic) type and sets x.typ to Typ[Invalid]. +func (check *Checker) instantiatedOperand(x *operand) { + if x.mode == typexpr && isGeneric(x.typ) { + check.errorf(x, _Todo, "cannot use generic type %s without instantiation", x.typ) + x.typ = Typ[Invalid] + } +} diff --git a/libgo/go/go/types/check.go b/libgo/go/go/types/check.go index 280792e..a923c3c 100644 --- a/libgo/go/go/types/check.go +++ b/libgo/go/go/types/check.go @@ -8,6 +8,7 @@ package types import ( "errors" + "fmt" "go/ast" "go/constant" "go/token" @@ -19,18 +20,18 @@ const ( trace = false // turn on for detailed type resolution traces ) -// If Strict is set, the type-checker enforces additional +// If forceStrict is set, the type-checker enforces additional // rules not specified by the Go 1 spec, but which will // catch guaranteed run-time errors if the respective // code is executed. In other words, programs passing in -// Strict mode are Go 1 compliant, but not all Go 1 programs -// will pass in Strict mode. The additional rules are: +// strict mode are Go 1 compliant, but not all Go 1 programs +// will pass in strict mode. The additional rules are: // // - A type assertion x.(T) where T is an interface type // is invalid if any (statically known) method that exists // for both x and T have different signatures. // -const strict = false +const forceStrict = false // exprInfo stores information about an untyped expression. type exprInfo struct { @@ -69,6 +70,12 @@ type importKey struct { path, dir string } +// A dotImportKey describes a dot-imported object in the given scope. +type dotImportKey struct { + scope *Scope + obj Object +} + // A Checker maintains the state of the type checker. // It must be created with NewChecker. type Checker struct { @@ -78,22 +85,33 @@ type Checker struct { fset *token.FileSet pkg *Package *Info - objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info - impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package - posMap map[*Interface][]token.Pos // maps interface types to lists of embedded interface positions - pkgCnt map[string]int // counts number of imported packages with a given name (for better error messages) + version version // accepted language version + objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info + impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package + posMap map[*Interface][]token.Pos // maps interface types to lists of embedded interface positions + typMap map[string]*Named // maps an instantiated named type hash to a *Named type + + // pkgPathMap maps package names to the set of distinct import paths we've + // seen for that name, anywhere in the import graph. It is used for + // disambiguating package names in error messages. + // + // pkgPathMap is allocated lazily, so that we don't pay the price of building + // it on the happy path. seenPkgMap tracks the packages that we've already + // walked. + pkgPathMap map[string]map[string]bool + seenPkgMap map[*Package]bool // information collected during type-checking of a set of package files // (initialized by Files, valid only for the duration of check.Files; // maps and lists are allocated on demand) - files []*ast.File // package files - unusedDotImports map[*Scope]map[*Package]*ast.ImportSpec // unused dot-imported packages + files []*ast.File // package files + imports []*PkgName // list of imported packages + dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through firstErr error // first error encountered methods map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods untyped map[ast.Expr]exprInfo // map of expressions without final type delayed []func() // stack of delayed action segments; segments are processed in FIFO order - finals []func() // list of final actions; processed at the end of type-checking the current set of files objPath []Object // path of object dependencies during type inference (for cycle reporting) // context within which the current object is type-checked @@ -104,22 +122,6 @@ type Checker struct { indent int // indentation for tracing } -// addUnusedImport adds the position of a dot-imported package -// pkg to the map of dot imports for the given file scope. -func (check *Checker) addUnusedDotImport(scope *Scope, pkg *Package, spec *ast.ImportSpec) { - mm := check.unusedDotImports - if mm == nil { - mm = make(map[*Scope]map[*Package]*ast.ImportSpec) - check.unusedDotImports = mm - } - m := mm[scope] - if m == nil { - m = make(map[*Package]*ast.ImportSpec) - mm[scope] = m - } - m[pkg] = spec -} - // addDeclDep adds the dependency edge (check.decl -> to) if check.decl exists func (check *Checker) addDeclDep(to Object) { from := check.decl @@ -149,14 +151,6 @@ func (check *Checker) later(f func()) { check.delayed = append(check.delayed, f) } -// atEnd adds f to the list of actions processed at the end -// of type-checking, before initialization order computation. -// Actions added by atEnd are processed after any actions -// added by later. -func (check *Checker) atEnd(f func()) { - check.finals = append(check.finals, f) -} - // push pushes obj onto the object path and returns its index in the path. func (check *Checker) push(obj Object) int { check.objPath = append(check.objPath, obj) @@ -185,15 +179,21 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch info = new(Info) } + version, err := parseGoVersion(conf.goVersion) + if err != nil { + panic(fmt.Sprintf("invalid Go version %q (%v)", conf.goVersion, err)) + } + return &Checker{ - conf: conf, - fset: fset, - pkg: pkg, - Info: info, - objMap: make(map[Object]*declInfo), - impMap: make(map[importKey]*Package), - posMap: make(map[*Interface][]token.Pos), - pkgCnt: make(map[string]int), + conf: conf, + fset: fset, + pkg: pkg, + Info: info, + version: version, + objMap: make(map[Object]*declInfo), + impMap: make(map[importKey]*Package), + posMap: make(map[*Interface][]token.Pos), + typMap: make(map[string]*Named), } } @@ -202,13 +202,13 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch func (check *Checker) initFiles(files []*ast.File) { // start with a clean slate (check.Files may be called multiple times) check.files = nil - check.unusedDotImports = nil + check.imports = nil + check.dotImportMap = nil check.firstErr = nil check.methods = nil check.untyped = nil check.delayed = nil - check.finals = nil // determine package name and collect valid files pkg := check.pkg @@ -265,7 +265,6 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) { check.packageObjects() check.processDelayed(0) // incl. all functions - check.processFinals() check.initOrder() @@ -275,7 +274,20 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) { check.recordUntyped() + if check.Info != nil { + sanitizeInfo(check.Info) + } + check.pkg.complete = true + + // no longer needed - release memory + check.imports = nil + check.dotImportMap = nil + check.pkgPathMap = nil + check.seenPkgMap = nil + + // TODO(rFindley) There's more memory we should release at this point. + return } @@ -294,13 +306,30 @@ func (check *Checker) processDelayed(top int) { check.delayed = check.delayed[:top] } -func (check *Checker) processFinals() { - n := len(check.finals) - for _, f := range check.finals { - f() // must not append to check.finals +func (check *Checker) record(x *operand) { + // convert x into a user-friendly set of values + // TODO(gri) this code can be simplified + var typ Type + var val constant.Value + switch x.mode { + case invalid: + typ = Typ[Invalid] + case novalue: + typ = (*Tuple)(nil) + case constant_: + typ = x.typ + val = x.val + default: + typ = x.typ } - if len(check.finals) != n { - panic("internal error: final action list grew") + assert(x.expr != nil && typ != nil) + + if isUntyped(typ) { + // delay type and value recording until we know the type + // or until the end of type checking + check.rememberUntyped(x.expr, false, x.mode, typ.(*Basic), val) + } else { + check.recordTypeAndValue(x.expr, x.mode, typ, val) } } @@ -326,7 +355,9 @@ func (check *Checker) recordTypeAndValue(x ast.Expr, mode operandMode, typ Type, } if mode == constant_ { assert(val != nil) - assert(typ == Typ[Invalid] || isConstType(typ)) + // We check is(typ, IsConstType) here as constant expressions may be + // recorded as type parameters. + assert(typ == Typ[Invalid] || is(typ, IsConstType)) } if m := check.Types; m != nil { m[x] = TypeAndValue{mode, typ, val} @@ -334,14 +365,14 @@ func (check *Checker) recordTypeAndValue(x ast.Expr, mode operandMode, typ Type, } func (check *Checker) recordBuiltinType(f ast.Expr, sig *Signature) { - // f must be a (possibly parenthesized) identifier denoting a built-in - // (built-ins in package unsafe always produce a constant result and - // we don't record their signatures, so we don't see qualified idents - // here): record the signature for f and possible children. + // f must be a (possibly parenthesized, possibly qualified) + // identifier denoting a built-in (including unsafe's non-constant + // functions Add and Slice): record the signature for f and possible + // children. for { check.recordTypeAndValue(f, builtin, sig, nil) switch p := f.(type) { - case *ast.Ident: + case *ast.Ident, *ast.SelectorExpr: return // we're done case *ast.ParenExpr: f = p.X @@ -377,6 +408,14 @@ func (check *Checker) recordCommaOkTypes(x ast.Expr, a [2]Type) { } } +func (check *Checker) recordInferred(call ast.Expr, targs []Type, sig *Signature) { + assert(call != nil) + assert(sig != nil) + if m := getInferred(check.Info); m != nil { + m[call] = _Inferred{targs, sig} + } +} + func (check *Checker) recordDef(id *ast.Ident, obj Object) { assert(id != nil) if m := check.Defs; m != nil { diff --git a/libgo/go/go/types/check_test.go b/libgo/go/go/types/check_test.go index ce31dab..f83abf1 100644 --- a/libgo/go/go/types/check_test.go +++ b/libgo/go/go/types/check_test.go @@ -27,8 +27,10 @@ package types_test import ( "flag" + "fmt" "go/ast" "go/importer" + "go/internal/typeparams" "go/parser" "go/scanner" "go/token" @@ -43,59 +45,11 @@ import ( ) var ( - haltOnError = flag.Bool("halt", false, "halt on error") - listErrors = flag.Bool("errlist", false, "list errors") - testFiles = flag.String("files", "", "space-separated list of test files") + haltOnError = flag.Bool("halt", false, "halt on error") + verifyErrors = flag.Bool("verify", false, "verify errors (rather than list them) in TestManual") + goVersion = flag.String("lang", "", "Go language version (e.g. \"go1.12\") for TestManual") ) -// The test filenames do not end in .go so that they are invisible -// to gofmt since they contain comments that must not change their -// positions relative to surrounding tokens. - -// Each tests entry is list of files belonging to the same package. -var tests = [][]string{ - {"testdata/errors.src"}, - {"testdata/importdecl0a.src", "testdata/importdecl0b.src"}, - {"testdata/importdecl1a.src", "testdata/importdecl1b.src"}, - {"testdata/importC.src"}, // special handling in checkFiles - {"testdata/cycles.src"}, - {"testdata/cycles1.src"}, - {"testdata/cycles2.src"}, - {"testdata/cycles3.src"}, - {"testdata/cycles4.src"}, - {"testdata/cycles5.src"}, - {"testdata/init0.src"}, - {"testdata/init1.src"}, - {"testdata/init2.src"}, - {"testdata/decls0.src"}, - {"testdata/decls1.src"}, - {"testdata/decls2a.src", "testdata/decls2b.src"}, - {"testdata/decls3.src"}, - {"testdata/decls4.src"}, - {"testdata/decls5.src"}, - {"testdata/const0.src"}, - {"testdata/const1.src"}, - {"testdata/constdecl.src"}, - {"testdata/vardecl.src"}, - {"testdata/expr0.src"}, - {"testdata/expr1.src"}, - {"testdata/expr2.src"}, - {"testdata/expr3.src"}, - {"testdata/methodsets.src"}, - {"testdata/shifts.src"}, - {"testdata/builtins.src"}, - {"testdata/conversions.src"}, - {"testdata/conversions2.src"}, - {"testdata/stmt0.src"}, - {"testdata/stmt1.src"}, - {"testdata/gotos.src"}, - {"testdata/labels.src"}, - {"testdata/literals.src"}, - {"testdata/issues.src"}, - {"testdata/blank.src"}, - {"testdata/issue25008b.src", "testdata/issue25008a.src"}, // order (b before a) is crucial! -} - var fset = token.NewFileSet() // Positioned errors are of the form filename:line:column: message . @@ -114,11 +68,11 @@ func splitError(err error) (pos, msg string) { return } -func parseFiles(t *testing.T, filenames []string) ([]*ast.File, []error) { +func parseFiles(t *testing.T, filenames []string, srcs [][]byte, mode parser.Mode) ([]*ast.File, []error) { var files []*ast.File var errlist []error - for _, filename := range filenames { - file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors) + for i, filename := range filenames { + file, err := parser.ParseFile(fset, filename, srcs[i], mode) if file == nil { t.Fatalf("%s: %s", filename, err) } @@ -147,19 +101,17 @@ var errRx = regexp.MustCompile(`^ *ERROR *(HERE)? *"?([^"]*)"?`) // errMap collects the regular expressions of ERROR comments found // in files and returns them as a map of error positions to error messages. // -func errMap(t *testing.T, testname string, files []*ast.File) map[string][]string { +// srcs must be a slice of the same length as files, containing the original +// source for the parsed AST. +func errMap(t *testing.T, files []*ast.File, srcs [][]byte) map[string][]string { // map of position strings to lists of error message patterns errmap := make(map[string][]string) - for _, file := range files { - filename := fset.Position(file.Package).Filename - src, err := os.ReadFile(filename) - if err != nil { - t.Fatalf("%s: could not read %s", testname, filename) - } - + for i, file := range files { + tok := fset.File(file.Package) + src := srcs[i] var s scanner.Scanner - s.Init(fset.AddFile(filename, -1, len(src)), src, nil, scanner.ScanComments) + s.Init(tok, src, nil, scanner.ScanComments) var prev token.Pos // position of last non-comment, non-semicolon token var here token.Pos // position immediately after the token at position prev @@ -236,16 +188,52 @@ func eliminate(t *testing.T, errmap map[string][]string, errlist []error) { } } -func checkFiles(t *testing.T, testfiles []string) { +// goVersionRx matches a Go version string using '_', e.g. "go1_12". +var goVersionRx = regexp.MustCompile(`^go[1-9][0-9]*_(0|[1-9][0-9]*)$`) + +// asGoVersion returns a regular Go language version string +// if s is a Go version string using '_' rather than '.' to +// separate the major and minor version numbers (e.g. "go1_12"). +// Otherwise it returns the empty string. +func asGoVersion(s string) string { + if goVersionRx.MatchString(s) { + return strings.Replace(s, "_", ".", 1) + } + return "" +} + +func checkFiles(t *testing.T, sizes Sizes, goVersion string, filenames []string, srcs [][]byte, manual bool, imp Importer) { + if len(filenames) == 0 { + t.Fatal("no source files") + } + + if strings.HasSuffix(filenames[0], ".go2") && !typeparams.Enabled { + t.Skip("type params are not enabled") + } + if strings.HasSuffix(filenames[0], ".go1") && typeparams.Enabled { + t.Skip("type params are enabled") + } + + mode := parser.AllErrors + if !strings.HasSuffix(filenames[0], ".go2") { + mode |= typeparams.DisallowParsing + } + // parse files and collect parser errors - files, errlist := parseFiles(t, testfiles) + files, errlist := parseFiles(t, filenames, srcs, mode) pkgName := "<no package>" if len(files) > 0 { pkgName = files[0].Name.Name } - if *listErrors && len(errlist) > 0 { + // if no Go version is given, consider the package name + if goVersion == "" { + goVersion = asGoVersion(pkgName) + } + + listErrors := manual && !*verifyErrors + if listErrors && len(errlist) > 0 { t.Errorf("--- %s:", pkgName) for _, err := range errlist { t.Error(err) @@ -254,16 +242,25 @@ func checkFiles(t *testing.T, testfiles []string) { // typecheck and collect typechecker errors var conf Config + conf.Sizes = sizes + SetGoVersion(&conf, goVersion) + // special case for importC.src - if len(testfiles) == 1 && strings.HasSuffix(testfiles[0], "importC.src") { - conf.FakeImportC = true + if len(filenames) == 1 { + if strings.HasSuffix(filenames[0], "importC.src") { + conf.FakeImportC = true + } + } + + conf.Importer = imp + if imp == nil { + conf.Importer = importer.Default() } - conf.Importer = importer.Default() conf.Error = func(err error) { if *haltOnError { defer panic(err) } - if *listErrors { + if listErrors { t.Error(err) return } @@ -275,7 +272,7 @@ func checkFiles(t *testing.T, testfiles []string) { } conf.Check(pkgName, fset, files, nil) - if *listErrors { + if listErrors { return } @@ -292,7 +289,7 @@ func checkFiles(t *testing.T, testfiles []string) { // match and eliminate errors; // we are expecting the following errors - errmap := errMap(t, pkgName, files) + errmap := errMap(t, files, srcs) eliminate(t, errmap, errlist) // there should be no expected errors left @@ -306,44 +303,100 @@ func checkFiles(t *testing.T, testfiles []string) { } } -func TestCheck(t *testing.T) { +// TestManual is for manual testing of input files, provided as a list +// of arguments after the test arguments (and a separating "--"). For +// instance, to check the files foo.go and bar.go, use: +// +// go test -run Manual -- foo.go bar.go +// +// Provide the -verify flag to verify errors against ERROR comments in +// the input files rather than having a list of errors reported. +// The accepted Go language version can be controlled with the -lang flag. +func TestManual(t *testing.T) { + filenames := flag.Args() + if len(filenames) == 0 { + return + } testenv.MustHaveGoBuild(t) - - // Declare builtins for testing. DefPredeclaredTestFuncs() + testPkg(t, filenames, *goVersion, true) +} - // If explicit test files are specified, only check those. - if files := *testFiles; files != "" { - checkFiles(t, strings.Split(files, " ")) - return - } +func TestLongConstants(t *testing.T) { + format := "package longconst\n\nconst _ = %s\nconst _ = %s // ERROR excessively long constant" + src := fmt.Sprintf(format, strings.Repeat("1", 9999), strings.Repeat("1", 10001)) + checkFiles(t, nil, "", []string{"longconst.go"}, [][]byte{[]byte(src)}, false, nil) +} + +// TestIndexRepresentability tests that constant index operands must +// be representable as int even if they already have a type that can +// represent larger values. +func TestIndexRepresentability(t *testing.T) { + const src = "package index\n\nvar s []byte\nvar _ = s[int64 /* ERROR \"int64\\(1\\) << 40 \\(.*\\) overflows int\" */ (1) << 40]" + checkFiles(t, &StdSizes{4, 4}, "", []string{"index.go"}, [][]byte{[]byte(src)}, false, nil) +} - // Otherwise, run all the tests. - for _, files := range tests { - checkFiles(t, files) +func TestIssue46453(t *testing.T) { + if typeparams.Enabled { + t.Skip("type params are enabled") } + const src = "package p\ntype _ comparable // ERROR \"undeclared name: comparable\"" + checkFiles(t, nil, "", []string{"issue46453.go"}, [][]byte{[]byte(src)}, false, nil) } -func TestFixedBugs(t *testing.T) { testDir(t, "fixedbugs") } +func TestIssue47243_TypedRHS(t *testing.T) { + // The RHS of the shift expression below overflows uint on 32bit platforms, + // but this is OK as it is explicitly typed. + const src = "package issue47243\n\nvar a uint64; var _ = a << uint64(4294967296)" // uint64(1<<32) + checkFiles(t, &StdSizes{4, 4}, "", []string{"p.go"}, [][]byte{[]byte(src)}, false, nil) +} + +func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDir(t, "check") } +func TestExamples(t *testing.T) { testDir(t, "examples") } +func TestFixedbugs(t *testing.T) { testDir(t, "fixedbugs") } func testDir(t *testing.T, dir string) { testenv.MustHaveGoBuild(t) - dirs, err := os.ReadDir(dir) + dir = filepath.Join("testdata", dir) + fis, err := os.ReadDir(dir) if err != nil { - t.Fatal(err) + t.Error(err) + return } - for _, d := range dirs { - testname := filepath.Base(d.Name()) - testname = strings.TrimSuffix(testname, filepath.Ext(testname)) - t.Run(testname, func(t *testing.T) { - filename := filepath.Join(dir, d.Name()) - if d.IsDir() { - t.Errorf("skipped directory %q", filename) - return + for _, fi := range fis { + path := filepath.Join(dir, fi.Name()) + + // if fi is a directory, its files make up a single package + var filenames []string + if fi.IsDir() { + fis, err := os.ReadDir(path) + if err != nil { + t.Error(err) + continue } - checkFiles(t, []string{filename}) + for _, fi := range fis { + filenames = append(filenames, filepath.Join(path, fi.Name())) + } + } else { + filenames = []string{path} + } + t.Run(filepath.Base(path), func(t *testing.T) { + testPkg(t, filenames, "", false) }) } } + +// TODO(rFindley) reconcile the different test setup in go/types with types2. +func testPkg(t *testing.T, filenames []string, goVersion string, manual bool) { + srcs := make([][]byte, len(filenames)) + for i, filename := range filenames { + src, err := os.ReadFile(filename) + if err != nil { + t.Fatalf("could not read %s: %v", filename, err) + } + srcs[i] = src + } + checkFiles(t, nil, goVersion, filenames, srcs, manual, nil) +} diff --git a/libgo/go/go/types/conversions.go b/libgo/go/go/types/conversions.go index 1cab1cc..ad6d3ee 100644 --- a/libgo/go/go/types/conversions.go +++ b/libgo/go/go/types/conversions.go @@ -17,10 +17,11 @@ func (check *Checker) conversion(x *operand, T Type) { constArg := x.mode == constant_ var ok bool + var reason string switch { case constArg && isConstType(T): // constant conversion - switch t := T.Underlying().(*Basic); { + switch t := asBasic(T); { case representableConst(x.val, check, t, &x.val): ok = true case isInteger(x.typ) && isString(t): @@ -31,14 +32,18 @@ func (check *Checker) conversion(x *operand, T Type) { x.val = constant.MakeString(string(codepoint)) ok = true } - case x.convertibleTo(check, T): + case x.convertibleTo(check, T, &reason): // non-constant conversion x.mode = value ok = true } if !ok { - check.errorf(x, _InvalidConversion, "cannot convert %s to %s", x, T) + if reason != "" { + check.errorf(x, _InvalidConversion, "cannot convert %s to %s (%s)", x, T, reason) + } else { + check.errorf(x, _InvalidConversion, "cannot convert %s to %s", x, T) + } x.mode = invalid return } @@ -55,8 +60,8 @@ func (check *Checker) conversion(x *operand, T Type) { // - Keep untyped nil for untyped nil arguments. // - For integer to string conversions, keep the argument type. // (See also the TODO below.) - if IsInterface(T) || constArg && !isConstType(T) { - final = Default(x.typ) + if IsInterface(T) || constArg && !isConstType(T) || x.isNil() { + final = Default(x.typ) // default type of untyped nil is untyped nil } else if isInteger(x.typ) && isString(T) { final = x.typ } @@ -79,7 +84,7 @@ func (check *Checker) conversion(x *operand, T Type) { // convertibleTo reports whether T(x) is valid. // The check parameter may be nil if convertibleTo is invoked through an // exported API call, i.e., when all methods have been type-checked. -func (x *operand) convertibleTo(check *Checker, T Type) bool { +func (x *operand) convertibleTo(check *Checker, T Type, reason *string) bool { // "x is assignable to T" if ok, _ := x.assignableTo(check, T, nil); ok { return true @@ -87,8 +92,8 @@ func (x *operand) convertibleTo(check *Checker, T Type) bool { // "x's type and T have identical underlying types if tags are ignored" V := x.typ - Vu := V.Underlying() - Tu := T.Underlying() + Vu := under(V) + Tu := under(T) if check.identicalIgnoreTags(Vu, Tu) { return true } @@ -97,14 +102,14 @@ func (x *operand) convertibleTo(check *Checker, T Type) bool { // have identical underlying types if tags are ignored" if V, ok := V.(*Pointer); ok { if T, ok := T.(*Pointer); ok { - if check.identicalIgnoreTags(V.base.Underlying(), T.base.Underlying()) { + if check.identicalIgnoreTags(under(V.base), under(T.base)) { return true } } } // "x's type and T are both integer or floating point types" - if (isInteger(V) || isFloat(V)) && (isInteger(T) || isFloat(T)) { + if isIntegerOrFloat(V) && isIntegerOrFloat(T) { return true } @@ -133,31 +138,48 @@ func (x *operand) convertibleTo(check *Checker, T Type) bool { return true } + // "x is a slice, T is a pointer-to-array type, + // and the slice and array types have identical element types." + if s := asSlice(V); s != nil { + if p := asPointer(T); p != nil { + if a := asArray(p.Elem()); a != nil { + if check.identical(s.Elem(), a.Elem()) { + if check == nil || check.allowVersion(check.pkg, 1, 17) { + return true + } + if reason != nil { + *reason = "conversion of slices to array pointers requires go1.17 or later" + } + } + } + } + } + return false } func isUintptr(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.kind == Uintptr + t := asBasic(typ) + return t != nil && t.kind == Uintptr } func isUnsafePointer(typ Type) bool { - // TODO(gri): Is this (typ.Underlying() instead of just typ) correct? + // TODO(gri): Is this asBasic(typ) instead of typ.(*Basic) correct? + // (The former calls under(), while the latter doesn't.) // The spec does not say so, but gc claims it is. See also // issue 6326. - t, ok := typ.Underlying().(*Basic) - return ok && t.kind == UnsafePointer + t := asBasic(typ) + return t != nil && t.kind == UnsafePointer } func isPointer(typ Type) bool { - _, ok := typ.Underlying().(*Pointer) - return ok + return asPointer(typ) != nil } func isBytesOrRunes(typ Type) bool { - if s, ok := typ.(*Slice); ok { - t, ok := s.elem.Underlying().(*Basic) - return ok && (t.kind == Byte || t.kind == Rune) + if s := asSlice(typ); s != nil { + t := asBasic(s.elem) + return t != nil && (t.kind == Byte || t.kind == Rune) } return false } diff --git a/libgo/go/go/types/decl.go b/libgo/go/go/types/decl.go index 1f0bc35..9211feb 100644 --- a/libgo/go/go/types/decl.go +++ b/libgo/go/go/types/decl.go @@ -5,8 +5,10 @@ package types import ( + "fmt" "go/ast" "go/constant" + "go/internal/typeparams" "go/token" ) @@ -52,7 +54,10 @@ func pathString(path []Object) string { // objDecl type-checks the declaration of obj in its respective (file) context. // For the meaning of def, see Checker.definedType, in typexpr.go. func (check *Checker) objDecl(obj Object, def *Named) { - if trace { + if trace && obj.Type() == nil { + if check.indent == 0 { + fmt.Println() // empty line between top-level objects for readability + } check.trace(obj.Pos(), "-- checking %s (%s, objPath = %s)", obj, obj.color(), pathString(check.objPath)) check.indent++ defer func() { @@ -183,13 +188,14 @@ func (check *Checker) objDecl(obj Object, def *Named) { switch obj := obj.(type) { case *Const: check.decl = d // new package-level const decl - check.constDecl(obj, d.typ, d.init, d.inherited) + check.constDecl(obj, d.vtyp, d.init, d.inherited) case *Var: check.decl = d // new package-level var decl - check.varDecl(obj, d.lhs, d.typ, d.init) + check.varDecl(obj, d.lhs, d.vtyp, d.init) case *TypeName: // invalid recursive types are detected via path - check.typeDecl(obj, d.typ, def, d.alias) + check.typeDecl(obj, d.tdecl, def) + check.collectMethods(obj) // methods can only be added to top-level types case *Func: // functions may be recursive - no need to track dependencies check.funcDecl(obj, d) @@ -234,7 +240,7 @@ func (check *Checker) cycle(obj Object) (isCycle bool) { // this information explicitly in the object. var alias bool if d := check.objMap[obj]; d != nil { - alias = d.alias // package-level object + alias = d.tdecl.Assign.IsValid() // package-level object } else { alias = obj.IsAlias() // function local object } @@ -318,7 +324,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { } // don't report a 2nd error if we already know the type is invalid - // (e.g., if a cycle was detected earlier, via Checker.underlying). + // (e.g., if a cycle was detected earlier, via under). if t.underlying == Typ[Invalid] { t.info = invalid return invalid @@ -337,13 +343,15 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo { if tn == t.obj { check.cycleError(path[i:]) t.info = invalid - t.underlying = Typ[Invalid] return t.info } } panic("internal error: cycle start not found") } return t.info + + case *instance: + return check.validType(t.expand(), path) } return valid @@ -475,7 +483,7 @@ func (check *Checker) constDecl(obj *Const, typ, init ast.Expr, inherited bool) if !isConstType(t) { // don't report an error if the type is an invalid C (defined) type // (issue #22090) - if t.Underlying() != Typ[Invalid] { + if under(t) != Typ[Invalid] { check.errorf(typ, _InvalidConstType, "invalid constant type %s", t) } obj.typ = Typ[Invalid] @@ -506,7 +514,7 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) { // determine type, if any if typ != nil { - obj.typ = check.typ(typ) + obj.typ = check.varType(typ) // We cannot spread the type to all lhs variables if there // are more than one since that would mark them as checked // (see Checker.objDecl) and the assignment of init exprs, @@ -561,36 +569,66 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) { check.initVars(lhs, []ast.Expr{init}, token.NoPos) } -// underlying returns the underlying type of typ; possibly by following -// forward chains of named types. Such chains only exist while named types -// are incomplete. If an underlying type is found, resolve the chain by -// setting the underlying type for each defined type in the chain before -// returning it. -// -// If no underlying type is found, a cycle error is reported and Typ[Invalid] -// is used as underlying type for each defined type in the chain and returned -// as result. -func (check *Checker) underlying(typ Type) Type { - // If typ is not a defined type, its underlying type is itself. - n0, _ := typ.(*Named) - if n0 == nil { - return typ // nothing to do +// under returns the expanded underlying type of n0; possibly by following +// forward chains of named types. If an underlying type is found, resolve +// the chain by setting the underlying type for each defined type in the +// chain before returning it. If no underlying type is found or a cycle +// is detected, the result is Typ[Invalid]. If a cycle is detected and +// n0.check != nil, the cycle is reported. +func (n0 *Named) under() Type { + u := n0.underlying + + if u == Typ[Invalid] { + return u } // If the underlying type of a defined type is not a defined - // type, then that is the desired underlying type. - typ = n0.underlying - n, _ := typ.(*Named) + // (incl. instance) type, then that is the desired underlying + // type. + switch u.(type) { + case nil: + return Typ[Invalid] + default: + // common case + return u + case *Named, *instance: + // handled below + } + + if n0.check == nil { + panic("internal error: Named.check == nil but type is incomplete") + } + + // Invariant: after this point n0 as well as any named types in its + // underlying chain should be set up when this function exits. + check := n0.check + + // If we can't expand u at this point, it is invalid. + n := asNamed(u) if n == nil { - return typ // common case + n0.underlying = Typ[Invalid] + return n0.underlying } // Otherwise, follow the forward chain. seen := map[*Named]int{n0: 0} path := []Object{n0.obj} for { - typ = n.underlying - n1, _ := typ.(*Named) + u = n.underlying + if u == nil { + u = Typ[Invalid] + break + } + var n1 *Named + switch u1 := u.(type) { + case *Named: + n1 = u1 + case *instance: + n1, _ = u1.expand().(*Named) + if n1 == nil { + u = Typ[Invalid] + } + } if n1 == nil { break // end of chain } @@ -602,7 +640,7 @@ func (check *Checker) underlying(typ Type) Type { if i, ok := seen[n]; ok { // cycle check.cycleError(path[i:]) - typ = Typ[Invalid] + u = Typ[Invalid] break } } @@ -611,13 +649,14 @@ func (check *Checker) underlying(typ Type) Type { // We should never have to update the underlying type of an imported type; // those underlying types should have been resolved during the import. // Also, doing so would lead to a race condition (was issue #31749). + // Do this check always, not just in debug mode (it's cheap). if n.obj.pkg != check.pkg { panic("internal error: imported type with unresolved underlying type") } - n.underlying = typ + n.underlying = u } - return typ + return u } func (n *Named) setUnderlying(typ Type) { @@ -626,26 +665,45 @@ func (n *Named) setUnderlying(typ Type) { } } -func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, alias bool) { +func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) { assert(obj.typ == nil) check.later(func() { check.validType(obj.typ, nil) }) + alias := tdecl.Assign.IsValid() + if alias && typeparams.Get(tdecl) != nil { + // The parser will ensure this but we may still get an invalid AST. + // Complain and continue as regular type definition. + check.error(atPos(tdecl.Assign), 0, "generic type cannot be alias") + alias = false + } + if alias { + // type alias declaration + if !check.allowVersion(check.pkg, 1, 9) { + check.errorf(atPos(tdecl.Assign), _BadDecl, "type aliases requires go1.9 or later") + } obj.typ = Typ[Invalid] - obj.typ = check.typ(typ) + obj.typ = check.anyType(tdecl.Type) } else { + // defined type declaration - named := &Named{obj: obj} + named := check.newNamed(obj, nil, nil) def.setUnderlying(named) obj.typ = named // make sure recursive type declarations terminate + if tparams := typeparams.Get(tdecl); tparams != nil { + check.openScope(tdecl, "type parameters") + defer check.closeScope() + named.tparams = check.collectTypeParams(tparams) + } + // determine underlying type of named - named.orig = check.definedType(typ, named) + named.orig = check.definedType(tdecl.Type, named) // The underlying type of named may be itself a named type that is // incomplete: @@ -660,14 +718,85 @@ func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, alias bo // and which has as its underlying type the named type B. // Determine the (final, unnamed) underlying type by resolving // any forward chain. - named.underlying = check.underlying(named) + // TODO(gri) Investigate if we can just use named.origin here + // and rely on lazy computation of the underlying type. + named.underlying = under(named) + } + +} +func (check *Checker) collectTypeParams(list *ast.FieldList) (tparams []*TypeName) { + // Type parameter lists should not be empty. The parser will + // complain but we still may get an incorrect AST: ignore it. + if list.NumFields() == 0 { + return + } + + // Declare type parameters up-front, with empty interface as type bound. + // The scope of type parameters starts at the beginning of the type parameter + // list (so we can have mutually recursive parameterized interfaces). + for _, f := range list.List { + tparams = check.declareTypeParams(tparams, f.Names) + } + + setBoundAt := func(at int, bound Type) { + assert(IsInterface(bound)) + tparams[at].typ.(*_TypeParam).bound = bound + } + + index := 0 + var bound Type + for _, f := range list.List { + if f.Type == nil { + goto next + } + + // The predeclared identifier "any" is visible only as a constraint + // in a type parameter list. Look for it before general constraint + // resolution. + if tident, _ := unparen(f.Type).(*ast.Ident); tident != nil && tident.Name == "any" && check.lookup("any") == nil { + bound = universeAny + } else { + bound = check.typ(f.Type) + } + + // type bound must be an interface + // TODO(gri) We should delay the interface check because + // we may not have a complete interface yet: + // type C(type T C) interface {} + // (issue #39724). + if _, ok := under(bound).(*Interface); ok { + // Otherwise, set the bound for each type parameter. + for i := range f.Names { + setBoundAt(index+i, bound) + } + } else if bound != Typ[Invalid] { + check.errorf(f.Type, _Todo, "%s is not an interface", bound) + } + + next: + index += len(f.Names) } - check.addMethodDecls(obj) + return } -func (check *Checker) addMethodDecls(obj *TypeName) { +func (check *Checker) declareTypeParams(tparams []*TypeName, names []*ast.Ident) []*TypeName { + for _, name := range names { + tpar := NewTypeName(name.Pos(), check.pkg, name.Name, nil) + check.newTypeParam(tpar, len(tparams), &emptyInterface) // assigns type to tpar as a side-effect + check.declare(check.scope, name, tpar, check.scope.pos) // TODO(gri) check scope position + tparams = append(tparams, tpar) + } + + if trace && len(names) > 0 { + check.trace(names[0].Pos(), "type params = %v", tparams[len(tparams)-len(names):]) + } + + return tparams +} + +func (check *Checker) collectMethods(obj *TypeName) { // get associated methods // (Checker.collectObjects only collects methods with non-blank names; // Checker.resolveBaseTypeName ensures that obj is not an alias name @@ -677,14 +806,14 @@ func (check *Checker) addMethodDecls(obj *TypeName) { return } delete(check.methods, obj) - assert(!check.objMap[obj].alias) // don't use TypeName.IsAlias (requires fully set up object) + assert(!check.objMap[obj].tdecl.Assign.IsValid()) // don't use TypeName.IsAlias (requires fully set up object) // use an objset to check for name conflicts var mset objset // spec: "If the base type is a struct type, the non-blank method // and field names must be distinct." - base, _ := obj.typ.(*Named) // shouldn't fail but be conservative + base := asNamed(obj.typ) // shouldn't fail but be conservative if base != nil { if t, _ := base.underlying.(*Struct); t != nil { for _, fld := range t.fields { @@ -735,12 +864,18 @@ func (check *Checker) funcDecl(obj *Func, decl *declInfo) { sig := new(Signature) obj.typ = sig // guard against cycles + + // Avoid cycle error when referring to method while type-checking the signature. + // This avoids a nuisance in the best case (non-parameterized receiver type) and + // since the method is not a type, we get an error. If we have a parameterized + // receiver type, instantiating the receiver type leads to the instantiation of + // its methods, and we don't want a cycle error in that case. + // TODO(gri) review if this is correct and/or whether we still need this? + saved := obj.color_ + obj.color_ = black fdecl := decl.fdecl check.funcType(sig, fdecl.Recv, fdecl.Type) - if sig.recv == nil && obj.name == "init" && (sig.params.Len() > 0 || sig.results.Len() > 0) { - check.errorf(fdecl, _InvalidInitSig, "func init must have no arguments and no return values") - // ok to continue - } + obj.color_ = saved // function body must be type-checked after global declarations // (functions implemented elsewhere have no body) @@ -846,7 +981,7 @@ func (check *Checker) declStmt(d ast.Decl) { check.declare(check.scope, d.spec.Name, obj, scopePos) // mark and unmark type before calling typeDecl; its type is still nil (see Checker.objDecl) obj.setColor(grey + color(check.push(obj))) - check.typeDecl(obj, d.spec.Type, nil, d.spec.Assign.IsValid()) + check.typeDecl(obj, d.spec, nil) check.pop().setColor(black) default: check.invalidAST(d.node(), "unknown ast.Decl node %T", d.node()) diff --git a/libgo/go/go/types/errorcodes.go b/libgo/go/go/types/errorcodes.go index c01a12c..3d24da7 100644 --- a/libgo/go/go/types/errorcodes.go +++ b/libgo/go/go/types/errorcodes.go @@ -10,6 +10,8 @@ type errorCode int // Collectively, these codes provide an identifier that may be used to // implement special handling for certain types of errors. // +// Error code values should not be changed: add new codes at the end. +// // Error codes should be fine-grained enough that the exact nature of the error // can be easily determined, but coarse enough that they are not an // implementation detail of the type checking algorithm. As a rule-of-thumb, @@ -34,8 +36,6 @@ const ( // _Test is reserved for errors that only apply while in self-test mode. _Test - /* package names */ - // _BlankPkgName occurs when a package name is the blank identifier "_". // // Per the spec: @@ -55,8 +55,6 @@ const ( // var _ = fmt _InvalidPkgUse - /* imports */ - // _BadImportPath occurs when an import path is not valid. _BadImportPath @@ -81,8 +79,6 @@ const ( // func main() {} _UnusedImport - /* initialization */ - // _InvalidInitCycle occurs when an invalid cycle is detected within the // initialization graph. // @@ -92,8 +88,6 @@ const ( // func f() int { return x } _InvalidInitCycle - /* decls */ - // _DuplicateDecl occurs when an identifier is declared multiple times. // // Example: @@ -122,8 +116,6 @@ const ( // type T [unsafe.Sizeof(T{})]int _InvalidTypeCycle - /* decls > const */ - // _InvalidConstInit occurs when a const declaration has a non-constant // initializer. // @@ -149,8 +141,6 @@ const ( // const c *int = 4 _InvalidConstType - /* decls > var (+ other variable assignment codes) */ - // _UntypedNil occurs when the predeclared (untyped) value nil is used to // initialize a variable declared without an explicit type. // @@ -159,7 +149,7 @@ const ( _UntypedNil // _WrongAssignCount occurs when the number of values on the right-hand side - // of an assignment or or initialization expression does not match the number + // of an assignment or initialization expression does not match the number // of variables on the left-hand side. // // Example: @@ -249,8 +239,6 @@ const ( // } _UnaddressableFieldAssign - /* decls > type (+ other type expression codes) */ - // _NotAType occurs when the identifier used as the underlying type in a type // declaration or the right-hand side of a type alias does not denote a type. // @@ -320,8 +308,6 @@ const ( // } _InvalidPtrEmbed - /* decls > func and method */ - // _BadRecv occurs when a method declaration does not have exactly one // receiver parameter. // @@ -358,8 +344,6 @@ const ( // func (T) m(i int) int { return i } _DuplicateMethod - /* decls > special */ - // _InvalidBlank occurs when a blank identifier is used as a value or type. // // Per the spec: @@ -386,8 +370,8 @@ const ( // _InvalidInitSig occurs when an init function declares parameters or // results. // - // Example: - // func init() int { return 1 } + // Deprecated: no longer emitted by the type checker. _InvalidInitDecl is + // used instead. _InvalidInitSig // _InvalidInitDecl occurs when init is declared as anything other than a @@ -395,14 +379,15 @@ const ( // // Example: // var init = 1 + // + // Example: + // func init() int { return 1 } _InvalidInitDecl // _InvalidMainDecl occurs when main is declared as anything other than a // function, in a main package. _InvalidMainDecl - /* exprs */ - // _TooManyValues occurs when a function returns too many values for the // expression context in which it is used. // @@ -425,8 +410,6 @@ const ( // } _NotAnExpr - /* exprs > const */ - // _TruncatedFloat occurs when a float constant is truncated to an integer // value. // @@ -440,8 +423,6 @@ const ( // var x int8 = 1000 _NumericOverflow - /* exprs > operation */ - // _UndefinedOp occurs when an operator is not defined for the type(s) used // in an operation. // @@ -476,8 +457,6 @@ const ( // } _NonNumericIncDec - /* exprs > ptr */ - // _UnaddressableOperand occurs when the & operator is applied to an // unaddressable expression. // @@ -493,8 +472,6 @@ const ( // var y = *x _InvalidIndirection - /* exprs > [] */ - // _NonIndexableOperand occurs when an index operation is applied to a value // that cannot be indexed. // @@ -527,8 +504,6 @@ const ( // var _ = []int{1,2,3}[2:1] _SwappedSliceIndices - /* operators > slice */ - // _NonSliceableOperand occurs when a slice operation is applied to a value // whose type is not sliceable, or is unaddressable. // @@ -548,8 +523,6 @@ const ( // var x = s[1:2:3] _InvalidSliceExpr - /* exprs > shift */ - // _InvalidShiftCount occurs when the right-hand side of a shift operation is // either non-integer, negative, or too large. // @@ -567,8 +540,6 @@ const ( // var x = s << 2 _InvalidShiftOperand - /* exprs > chan */ - // _InvalidReceive occurs when there is a channel receive from a value that // is either not a channel, or is a send-only channel. // @@ -589,8 +560,6 @@ const ( // } _InvalidSend - /* exprs > literal */ - // _DuplicateLitKey occurs when an index is duplicated in a slice, array, or // map literal. // @@ -680,8 +649,6 @@ const ( // var _ = P {} _InvalidLit - /* exprs > selector */ - // _AmbiguousSelector occurs when a selector is ambiguous. // // Example: @@ -727,8 +694,6 @@ const ( // var x = T{}.f _MissingFieldOrMethod - /* exprs > ... */ - // _BadDotDotDotSyntax occurs when a "..." occurs in a context where it is // not valid. // @@ -753,51 +718,13 @@ const ( _NonVariadicDotDotDot // _MisplacedDotDotDot occurs when a "..." is used somewhere other than the - // final argument to a function call. + // final argument in a function declaration. // // Example: - // func printArgs(args ...int) { - // for _, a := range args { - // println(a) - // } - // } - // - // func f() { - // a := []int{1,2,3} - // printArgs(0, a...) - // } + // func f(...int, int) _MisplacedDotDotDot - // _InvalidDotDotDotOperand occurs when a "..." operator is applied to a - // single-valued operand. - // - // Example: - // func printArgs(args ...int) { - // for _, a := range args { - // println(a) - // } - // } - // - // func f() { - // a := 1 - // printArgs(a...) - // } - // - // Example: - // func args() (int, int) { - // return 1, 2 - // } - // - // func printArgs(args ...int) { - // for _, a := range args { - // println(a) - // } - // } - // - // func g() { - // printArgs(args()...) - // } - _InvalidDotDotDotOperand + _ // _InvalidDotDotDotOperand was removed. // _InvalidDotDotDot occurs when a "..." is used in a non-variadic built-in // function. @@ -807,8 +734,6 @@ const ( // var l = len(s...) _InvalidDotDotDot - /* exprs > built-in */ - // _UncalledBuiltin occurs when a built-in function is used as a // function-valued expression, instead of being called. // @@ -920,8 +845,6 @@ const ( // var _ = real(int(1)) _InvalidReal - /* exprs > assertion */ - // _InvalidAssert occurs when a type assertion is applied to a // value that is not of interface type. // @@ -945,8 +868,6 @@ const ( // var _ = x.(T) _ImpossibleAssert - /* exprs > conversion */ - // _InvalidConversion occurs when the argument type cannot be converted to the // target. // @@ -966,8 +887,6 @@ const ( // var _ = 1 + "" _InvalidUntypedConversion - /* offsetof */ - // _BadOffsetofSyntax occurs when unsafe.Offsetof is called with an argument // that is not a selector expression. // @@ -1006,8 +925,6 @@ const ( // var _ = unsafe.Offsetof(s.m) _InvalidOffsetof - /* control flow > scope */ - // _UnusedExpr occurs when a side-effect free expression is used as a // statement. Such a statement has no effect. // @@ -1055,8 +972,6 @@ const ( // } _OutOfScopeResult - /* control flow > if */ - // _InvalidCond occurs when an if condition is not a boolean expression. // // Example: @@ -1067,8 +982,6 @@ const ( // } _InvalidCond - /* control flow > for */ - // _InvalidPostDecl occurs when there is a declaration in a for-loop post // statement. // @@ -1078,17 +991,7 @@ const ( // } _InvalidPostDecl - // _InvalidChanRange occurs when a send-only channel used in a range - // expression. - // - // Example: - // func sum(c chan<- int) { - // s := 0 - // for i := range c { - // s += i - // } - // } - _InvalidChanRange + _ // _InvalidChanRange was removed. // _InvalidIterVar occurs when two iteration variables are used while ranging // over a channel. @@ -1112,8 +1015,6 @@ const ( // } _InvalidRangeExpr - /* control flow > switch */ - // _MisplacedBreak occurs when a break statement is not within a for, switch, // or select statement of the innermost function definition. // @@ -1217,8 +1118,6 @@ const ( // } _InvalidExprSwitch - /* control flow > select */ - // _InvalidSelectCase occurs when a select case is not a channel send or // receive. // @@ -1233,8 +1132,6 @@ const ( // } _InvalidSelectCase - /* control flow > labels and jumps */ - // _UndeclaredLabel occurs when an undeclared label is jumped to. // // Example: @@ -1302,8 +1199,6 @@ const ( // } _JumpIntoBlock - /* control flow > calls */ - // _InvalidMethodExpr occurs when a pointer method is called but the argument // is not addressable. // @@ -1331,8 +1226,6 @@ const ( // var y = x() _InvalidCall - /* control flow > suspended */ - // _UnusedResults occurs when a restricted expression-only built-in function // is suspended via go or defer. Such a suspension discards the results of // these side-effect free built-in functions, and therefore is ineffectual. @@ -1363,4 +1256,61 @@ const ( // return i // } _InvalidGo + + // All codes below were added in Go 1.17. + + // _BadDecl occurs when a declaration has invalid syntax. + _BadDecl + + // _RepeatedDecl occurs when an identifier occurs more than once on the left + // hand side of a short variable declaration. + // + // Example: + // func _() { + // x, y, y := 1, 2, 3 + // } + _RepeatedDecl + + // _InvalidUnsafeAdd occurs when unsafe.Add is called with a + // length argument that is not of integer type. + // + // Example: + // import "unsafe" + // + // var p unsafe.Pointer + // var _ = unsafe.Add(p, float64(1)) + _InvalidUnsafeAdd + + // _InvalidUnsafeSlice occurs when unsafe.Slice is called with a + // pointer argument that is not of pointer type or a length argument + // that is not of integer type, negative, or out of bounds. + // + // Example: + // import "unsafe" + // + // var x int + // var _ = unsafe.Slice(x, 1) + // + // Example: + // import "unsafe" + // + // var x int + // var _ = unsafe.Slice(&x, float64(1)) + // + // Example: + // import "unsafe" + // + // var x int + // var _ = unsafe.Slice(&x, -1) + // + // Example: + // import "unsafe" + // + // var x int + // var _ = unsafe.Slice(&x, uint64(1) << 63) + _InvalidUnsafeSlice + + // _Todo is a placeholder for error codes that have not been decided. + // TODO(rFindley) remove this error code after deciding on errors for generics code. + _Todo ) diff --git a/libgo/go/go/types/errors.go b/libgo/go/go/types/errors.go index a219501..2263106 100644 --- a/libgo/go/go/types/errors.go +++ b/libgo/go/go/types/errors.go @@ -28,8 +28,13 @@ func unreachable() { func (check *Checker) qualifier(pkg *Package) string { // Qualify the package unless it's the package being type-checked. if pkg != check.pkg { + if check.pkgPathMap == nil { + check.pkgPathMap = make(map[string]map[string]bool) + check.seenPkgMap = make(map[*Package]bool) + check.markImports(check.pkg) + } // If the same package name was used by multiple packages, display the full path. - if check.pkgCnt[pkg.name] > 1 { + if len(check.pkgPathMap[pkg.name]) > 1 { return strconv.Quote(pkg.path) } return pkg.name @@ -37,6 +42,26 @@ func (check *Checker) qualifier(pkg *Package) string { return "" } +// markImports recursively walks pkg and its imports, to record unique import +// paths in pkgPathMap. +func (check *Checker) markImports(pkg *Package) { + if check.seenPkgMap[pkg] { + return + } + check.seenPkgMap[pkg] = true + + forName, ok := check.pkgPathMap[pkg.name] + if !ok { + forName = make(map[string]bool) + check.pkgPathMap[pkg.name] = forName + } + forName[pkg.path] = true + + for _, imp := range pkg.imports { + check.markImports(imp) + } +} + func (check *Checker) sprintf(format string, args ...interface{}) string { for i, arg := range args { switch a := arg.(type) { @@ -89,15 +114,18 @@ func (check *Checker) err(err error) { return } - if check.errpos != nil && isInternal { - // If we have an internal error and the errpos override is set, use it to - // augment our error positioning. - // TODO(rFindley) we may also want to augment the error message and refer - // to the position (pos) in the original expression. - span := spanOf(check.errpos) - e.Pos = span.pos - e.go116start = span.start - e.go116end = span.end + if isInternal { + e.Msg = stripAnnotations(e.Msg) + if check.errpos != nil { + // If we have an internal error and the errpos override is set, use it to + // augment our error positioning. + // TODO(rFindley) we may also want to augment the error message and refer + // to the position (pos) in the original expression. + span := spanOf(check.errpos) + e.Pos = span.pos + e.go116start = span.start + e.go116end = span.end + } err = e } @@ -225,3 +253,18 @@ func spanOf(at positioner) posSpan { return posSpan{pos, pos, pos} } } + +// stripAnnotations removes internal (type) annotations from s. +func stripAnnotations(s string) string { + var b strings.Builder + for _, r := range s { + // strip #'s and subscript digits + if r != instanceMarker && !('₀' <= r && r < '₀'+10) { // '₀' == U+2080 + b.WriteRune(r) + } + } + if b.Len() < len(s) { + return b.String() + } + return s +} diff --git a/libgo/go/go/types/errors_test.go b/libgo/go/go/types/errors_test.go new file mode 100644 index 0000000..fdbe07c --- /dev/null +++ b/libgo/go/go/types/errors_test.go @@ -0,0 +1,25 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import "testing" + +func TestStripAnnotations(t *testing.T) { + for _, test := range []struct { + in, want string + }{ + {"", ""}, + {" ", " "}, + {"foo", "foo"}, + {"foo₀", "foo"}, + {"foo(T₀)", "foo(T)"}, + {"#foo(T₀)", "foo(T)"}, + } { + got := stripAnnotations(test.in) + if got != test.want { + t.Errorf("%q: got %q; want %q", test.in, got, test.want) + } + } +} diff --git a/libgo/go/go/types/eval_test.go b/libgo/go/go/types/eval_test.go index d940bf0..41d3a61 100644 --- a/libgo/go/go/types/eval_test.go +++ b/libgo/go/go/types/eval_test.go @@ -76,7 +76,7 @@ func TestEvalArith(t *testing.T) { `false == false`, `12345678 + 87654321 == 99999999`, `10 * 20 == 200`, - `(1<<1000)*2 >> 100 == 2<<900`, + `(1<<500)*2 >> 100 == 2<<400`, `"foo" + "bar" == "foobar"`, `"abc" <= "bcd"`, `len([10]struct{}{}) == 2*5`, @@ -155,9 +155,9 @@ func TestEvalPos(t *testing.T) { import "io" type R = io.Reader func _() { - /* interface{R}.Read => , func(interface{io.Reader}, p []byte) (n int, err error) */ + /* interface{R}.Read => , func(_ interface{io.Reader}, p []byte) (n int, err error) */ _ = func() { - /* interface{io.Writer}.Write => , func(interface{io.Writer}, p []byte) (n int, err error) */ + /* interface{io.Writer}.Write => , func(_ interface{io.Writer}, p []byte) (n int, err error) */ type io interface {} // must not shadow io in line above } type R interface {} // must not shadow R in first line of this function body diff --git a/libgo/go/go/types/example_test.go b/libgo/go/go/types/example_test.go index 95bb270..ffbb5c0 100644 --- a/libgo/go/go/types/example_test.go +++ b/libgo/go/go/types/example_test.go @@ -5,6 +5,7 @@ // Only run where builders (build.golang.org) have // access to compiled packages for import. // +//go:build !arm && !arm64 // +build !arm,!arm64 package types_test diff --git a/libgo/go/go/types/expr.go b/libgo/go/go/types/expr.go index eb20561..58962e7 100644 --- a/libgo/go/go/types/expr.go +++ b/libgo/go/go/types/expr.go @@ -10,6 +10,7 @@ import ( "fmt" "go/ast" "go/constant" + "go/internal/typeparams" "go/token" "math" ) @@ -58,11 +59,16 @@ the type (and constant value, if any) is recorded via Info.Types, if present. type opPredicates map[token.Token]func(Type) bool -var unaryOpPredicates = opPredicates{ - token.ADD: isNumeric, - token.SUB: isNumeric, - token.XOR: isInteger, - token.NOT: isBoolean, +var unaryOpPredicates opPredicates + +func init() { + // Setting unaryOpPredicates in init avoids declaration cycles. + unaryOpPredicates = opPredicates{ + token.ADD: isNumeric, + token.SUB: isNumeric, + token.XOR: isInteger, + token.NOT: isBoolean, + } } func (check *Checker) op(m opPredicates, x *operand, op token.Token) bool { @@ -78,13 +84,77 @@ func (check *Checker) op(m opPredicates, x *operand, op token.Token) bool { return true } +// overflow checks that the constant x is representable by its type. +// For untyped constants, it checks that the value doesn't become +// arbitrarily large. +func (check *Checker) overflow(x *operand, op token.Token, opPos token.Pos) { + assert(x.mode == constant_) + + if x.val.Kind() == constant.Unknown { + // TODO(gri) We should report exactly what went wrong. At the + // moment we don't have the (go/constant) API for that. + // See also TODO in go/constant/value.go. + check.errorf(atPos(opPos), _InvalidConstVal, "constant result is not representable") + return + } + + // Typed constants must be representable in + // their type after each constant operation. + if isTyped(x.typ) { + check.representable(x, asBasic(x.typ)) + return + } + + // Untyped integer values must not grow arbitrarily. + const prec = 512 // 512 is the constant precision + if x.val.Kind() == constant.Int && constant.BitLen(x.val) > prec { + check.errorf(atPos(opPos), _InvalidConstVal, "constant %s overflow", opName(x.expr)) + x.val = constant.MakeUnknown() + } +} + +// opName returns the name of an operation, or the empty string. +// For now, only operations that might overflow are handled. +// TODO(gri) Expand this to a general mechanism giving names to +// nodes? +func opName(e ast.Expr) string { + switch e := e.(type) { + case *ast.BinaryExpr: + if int(e.Op) < len(op2str2) { + return op2str2[e.Op] + } + case *ast.UnaryExpr: + if int(e.Op) < len(op2str1) { + return op2str1[e.Op] + } + } + return "" +} + +var op2str1 = [...]string{ + token.XOR: "bitwise complement", +} + +// This is only used for operations that may cause overflow. +var op2str2 = [...]string{ + token.ADD: "addition", + token.SUB: "subtraction", + token.XOR: "bitwise XOR", + token.MUL: "multiplication", + token.SHL: "shift", +} + // The unary expression e may be nil. It's passed in for better error messages only. -func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) { - switch op { +func (check *Checker) unary(x *operand, e *ast.UnaryExpr) { + check.expr(x, e.X) + if x.mode == invalid { + return + } + switch e.Op { case token.AND: // spec: "As an exception to the addressability // requirement x may also be a composite literal." - if _, ok := unparen(x.expr).(*ast.CompositeLit); !ok && x.mode != variable { + if _, ok := unparen(e.X).(*ast.CompositeLit); !ok && x.mode != variable { check.invalidOp(x, _UnaddressableOperand, "cannot take address of %s", x) x.mode = invalid return @@ -94,8 +164,8 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) { return case token.ARROW: - typ, ok := x.typ.Underlying().(*Chan) - if !ok { + typ := asChan(x.typ) + if typ == nil { check.invalidOp(x, _InvalidReceive, "cannot receive from non-channel %s", x) x.mode = invalid return @@ -111,26 +181,23 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) { return } - if !check.op(unaryOpPredicates, x, op) { + if !check.op(unaryOpPredicates, x, e.Op) { x.mode = invalid return } if x.mode == constant_ { - typ := x.typ.Underlying().(*Basic) - var prec uint - if isUnsigned(typ) { - prec = uint(check.conf.sizeof(typ) * 8) + if x.val.Kind() == constant.Unknown { + // nothing to do (and don't cause an error below in the overflow check) + return } - x.val = constant.UnaryOp(op, x.val, prec) - // Typed constants must be representable in - // their type after each constant operation. - if isTyped(typ) { - if e != nil { - x.expr = e // for better error message - } - check.representable(x, typ) + var prec uint + if isUnsigned(x.typ) { + prec = uint(check.conf.sizeof(x.typ) * 8) } + x.val = constant.UnaryOp(e.Op, x.val, prec) + x.expr = e + check.overflow(x, e.Op, x.Pos()) return } @@ -332,17 +399,24 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c // representable checks that a constant operand is representable in the given // basic type. func (check *Checker) representable(x *operand, typ *Basic) { - if err := check.isRepresentable(x, typ); err != nil { + v, code := check.representation(x, typ) + if code != 0 { + check.invalidConversion(code, x, typ) x.mode = invalid - check.err(err) + return } + assert(v != nil) + x.val = v } -func (check *Checker) isRepresentable(x *operand, typ *Basic) error { +// representation returns the representation of the constant operand x as the +// basic type typ. +// +// If no such representation is possible, it returns a non-zero error code. +func (check *Checker) representation(x *operand, typ *Basic) (constant.Value, errorCode) { assert(x.mode == constant_) - if !representableConst(x.val, check, typ, &x.val) { - var msg string - var code errorCode + v := x.val + if !representableConst(x.val, check, typ, &v) { if isNumeric(x.typ) && isNumeric(typ) { // numeric conversion : error msg // @@ -352,19 +426,25 @@ func (check *Checker) isRepresentable(x *operand, typ *Basic) error { // float -> float : overflows // if !isInteger(x.typ) && isInteger(typ) { - msg = "%s truncated to %s" - code = _TruncatedFloat + return nil, _TruncatedFloat } else { - msg = "%s overflows %s" - code = _NumericOverflow + return nil, _NumericOverflow } - } else { - msg = "cannot convert %s to %s" - code = _InvalidConstVal } - return check.newErrorf(x, code, false, msg, x, typ) + return nil, _InvalidConstVal } - return nil + return v, 0 +} + +func (check *Checker) invalidConversion(code errorCode, x *operand, target Type) { + msg := "cannot convert %s to %s" + switch code { + case _TruncatedFloat: + msg = "%s truncated to %s" + case _NumericOverflow: + msg = "%s overflows %s" + } + check.errorf(x, code, msg, x, target) } // updateExprType updates the type of x to typ and invokes itself @@ -456,7 +536,7 @@ func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) { // If the new type is not final and still untyped, just // update the recorded type. if !final && isUntyped(typ) { - old.typ = typ.Underlying().(*Basic) + old.typ = asBasic(typ) check.untyped[x] = old return } @@ -500,15 +580,32 @@ func (check *Checker) updateExprVal(x ast.Expr, val constant.Value) { // convertUntyped attempts to set the type of an untyped value to the target type. func (check *Checker) convertUntyped(x *operand, target Type) { - if err := check.canConvertUntyped(x, target); err != nil { + newType, val, code := check.implicitTypeAndValue(x, target) + if code != 0 { + check.invalidConversion(code, x, target.Underlying()) x.mode = invalid - check.err(err) + return + } + if val != nil { + x.val = val + check.updateExprVal(x.expr, val) + } + if newType != x.typ { + x.typ = newType + check.updateExprType(x.expr, newType, false) } } -func (check *Checker) canConvertUntyped(x *operand, target Type) error { +// implicitTypeAndValue returns the implicit type of x when used in a context +// where the target type is expected. If no such implicit conversion is +// possible, it returns a nil Type and non-zero error code. +// +// If x is a constant operand, the returned constant.Value will be the +// representation of x in this context. +func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, constant.Value, errorCode) { + target = expand(target) if x.mode == invalid || isTyped(x.typ) || target == Typ[Invalid] { - return nil + return x.typ, nil, 0 } if isUntyped(target) { @@ -517,43 +614,23 @@ func (check *Checker) canConvertUntyped(x *operand, target Type) error { tkind := target.(*Basic).kind if isNumeric(x.typ) && isNumeric(target) { if xkind < tkind { - x.typ = target - check.updateExprType(x.expr, target, false) + return target, nil, 0 } } else if xkind != tkind { - return check.newErrorf(x, _InvalidUntypedConversion, false, "cannot convert %s to %s", x, target) - } - return nil - } - - if t, ok := target.Underlying().(*Basic); ok && x.mode == constant_ { - if err := check.isRepresentable(x, t); err != nil { - return err + return nil, nil, _InvalidUntypedConversion } - // Expression value may have been rounded - update if needed. - check.updateExprVal(x.expr, x.val) - } else { - newTarget := check.implicitType(x, target) - if newTarget == nil { - return check.newErrorf(x, _InvalidUntypedConversion, false, "cannot convert %s to %s", x, target) - } - target = newTarget + return x.typ, nil, 0 } - x.typ = target - // Even though implicitType can return UntypedNil, this value is final: the - // predeclared identifier nil has no type. - check.updateExprType(x.expr, target, true) - return nil -} -// implicitType returns the implicit type of x when used in a context where the -// target type is expected. If no such implicit conversion is possible, it -// returns nil. -func (check *Checker) implicitType(x *operand, target Type) Type { - assert(isUntyped(x.typ)) - switch t := target.Underlying().(type) { + switch t := optype(target).(type) { case *Basic: - assert(x.mode != constant_) + if x.mode == constant_ { + v, code := check.representation(x, t) + if code != 0 { + return nil, nil, code + } + return target, v, code + } // Non-constant untyped values may appear as the // result of comparisons (untyped bool), intermediate // (delayed-checked) rhs operands of shifts, and as @@ -561,26 +638,40 @@ func (check *Checker) implicitType(x *operand, target Type) Type { switch x.typ.(*Basic).kind { case UntypedBool: if !isBoolean(target) { - return nil + return nil, nil, _InvalidUntypedConversion } case UntypedInt, UntypedRune, UntypedFloat, UntypedComplex: if !isNumeric(target) { - return nil + return nil, nil, _InvalidUntypedConversion } case UntypedString: // Non-constant untyped string values are not permitted by the spec and // should not occur during normal typechecking passes, but this path is // reachable via the AssignableTo API. if !isString(target) { - return nil + return nil, nil, _InvalidUntypedConversion } case UntypedNil: // Unsafe.Pointer is a basic type that includes nil. if !hasNil(target) { - return nil + return nil, nil, _InvalidUntypedConversion } + // Preserve the type of nil as UntypedNil: see #13061. + return Typ[UntypedNil], nil, 0 default: - return nil + return nil, nil, _InvalidUntypedConversion + } + case *_Sum: + ok := t.is(func(t Type) bool { + target, _, _ := check.implicitTypeAndValue(x, t) + return target != nil + }) + if !ok { + return nil, nil, _InvalidUntypedConversion + } + // keep nil untyped (was bug #39755) + if x.isNil() { + return Typ[UntypedNil], nil, 0 } case *Interface: // Values must have concrete dynamic types. If the value is nil, @@ -588,24 +679,24 @@ func (check *Checker) implicitType(x *operand, target Type) Type { // need the dynamic type for argument checking of say, print // functions) if x.isNil() { - return Typ[UntypedNil] + return Typ[UntypedNil], nil, 0 } // cannot assign untyped values to non-empty interfaces - check.completeInterface(t) + check.completeInterface(token.NoPos, t) if !t.Empty() { - return nil + return nil, nil, _InvalidUntypedConversion } - return Default(x.typ) + return Default(x.typ), nil, 0 case *Pointer, *Signature, *Slice, *Map, *Chan: if !x.isNil() { - return nil + return nil, nil, _InvalidUntypedConversion } // Keep nil untyped - see comment for interfaces, above. - return Typ[UntypedNil] + return Typ[UntypedNil], nil, 0 default: - return nil + return nil, nil, _InvalidUntypedConversion } - return target + return target, nil, 0 } func (check *Checker) comparison(x, y *operand, op token.Token) { @@ -665,15 +756,16 @@ func (check *Checker) comparison(x, y *operand, op token.Token) { x.typ = Typ[UntypedBool] } -func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) { - untypedx := isUntyped(x.typ) +// If e != nil, it must be the shift expression; it may be nil for non-constant shifts. +func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { + // TODO(gri) This function seems overly complex. Revisit. var xval constant.Value if x.mode == constant_ { xval = constant.ToInt(x.val) } - if isInteger(x.typ) || untypedx && xval != nil && xval.Kind() == constant.Int { + if isInteger(x.typ) || isUntyped(x.typ) && xval != nil && xval.Kind() == constant.Int { // The lhs is of integer type or an untyped constant representable // as an integer. Nothing to do. } else { @@ -685,10 +777,40 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) { // spec: "The right operand in a shift expression must have integer type // or be an untyped constant representable by a value of type uint." + + // Check that constants are representable by uint, but do not convert them + // (see also issue #47243). + if y.mode == constant_ { + // Provide a good error message for negative shift counts. + yval := constant.ToInt(y.val) // consider -1, 1.0, but not -1.1 + if yval.Kind() == constant.Int && constant.Sign(yval) < 0 { + check.invalidOp(y, _InvalidShiftCount, "negative shift count %s", y) + x.mode = invalid + return + } + + if isUntyped(y.typ) { + // Caution: Check for representability here, rather than in the switch + // below, because isInteger includes untyped integers (was bug #43697). + check.representable(y, Typ[Uint]) + if y.mode == invalid { + x.mode = invalid + return + } + } + } + + // Check that RHS is otherwise at least of integer type. switch { case isInteger(y.typ): - // nothing to do + if !isUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) { + check.invalidOp(y, _InvalidShiftCount, "signed shift count %s requires go1.13 or later", y) + x.mode = invalid + return + } case isUntyped(y.typ): + // This is incorrect, but preserves pre-existing behavior. + // See also bug #47410. check.convertUntyped(y, Typ[Uint]) if y.mode == invalid { x.mode = invalid @@ -700,25 +822,20 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) { return } - var yval constant.Value - if y.mode == constant_ { - // rhs must be an integer value - // (Either it was of an integer type already, or it was - // untyped and successfully converted to a uint above.) - yval = constant.ToInt(y.val) - assert(yval.Kind() == constant.Int) - if constant.Sign(yval) < 0 { - check.invalidOp(y, _InvalidShiftCount, "negative shift count %s", y) - x.mode = invalid - return - } - } - if x.mode == constant_ { if y.mode == constant_ { + // if either x or y has an unknown value, the result is unknown + if x.val.Kind() == constant.Unknown || y.val.Kind() == constant.Unknown { + x.val = constant.MakeUnknown() + // ensure the correct type - see comment below + if !isInteger(x.typ) { + x.typ = Typ[UntypedInt] + } + return + } // rhs must be within reasonable bounds in constant shifts - const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64 - s, ok := constant.Uint64Val(yval) + const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64 (see issue #44057) + s, ok := constant.Uint64Val(y.val) if !ok || s > shiftBound { check.invalidOp(y, _InvalidShiftCount, "invalid shift count %s", y) x.mode = invalid @@ -733,19 +850,17 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) { } // x is a constant so xval != nil and it must be of Int kind. x.val = constant.Shift(xval, op, uint(s)) - // Typed constants must be representable in - // their type after each constant operation. - if isTyped(x.typ) { - if e != nil { - x.expr = e // for better error message - } - check.representable(x, x.typ.Underlying().(*Basic)) + x.expr = e + opPos := x.Pos() + if b, _ := e.(*ast.BinaryExpr); b != nil { + opPos = b.OpPos } + check.overflow(x, op, opPos) return } // non-constant shift with constant lhs - if untypedx { + if isUntyped(x.typ) { // spec: "If the left operand of a non-constant shift // expression is an untyped constant, the type of the // constant is what it would be if the shift expression @@ -785,24 +900,30 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) { x.mode = value } -var binaryOpPredicates = opPredicates{ - token.ADD: func(typ Type) bool { return isNumeric(typ) || isString(typ) }, - token.SUB: isNumeric, - token.MUL: isNumeric, - token.QUO: isNumeric, - token.REM: isInteger, +var binaryOpPredicates opPredicates - token.AND: isInteger, - token.OR: isInteger, - token.XOR: isInteger, - token.AND_NOT: isInteger, +func init() { + // Setting binaryOpPredicates in init avoids declaration cycles. + binaryOpPredicates = opPredicates{ + token.ADD: isNumericOrString, + token.SUB: isNumeric, + token.MUL: isNumeric, + token.QUO: isNumeric, + token.REM: isInteger, - token.LAND: isBoolean, - token.LOR: isBoolean, + token.AND: isInteger, + token.OR: isInteger, + token.XOR: isInteger, + token.AND_NOT: isInteger, + + token.LAND: isBoolean, + token.LOR: isBoolean, + } } -// The binary expression e may be nil. It's passed in for better error messages only. -func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, op token.Token, opPos token.Pos) { +// If e != nil, it must be the binary expression; it may be nil for non-constant expressions +// (when invoked for an assignment operation where the binary expression is implicit). +func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token.Token, opPos token.Pos) { var y operand check.expr(x, lhs) @@ -877,30 +998,19 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o } if x.mode == constant_ && y.mode == constant_ { - xval := x.val - yval := y.val - typ := x.typ.Underlying().(*Basic) + // if either x or y has an unknown value, the result is unknown + if x.val.Kind() == constant.Unknown || y.val.Kind() == constant.Unknown { + x.val = constant.MakeUnknown() + // x.typ is unchanged + return + } // force integer division of integer operands - if op == token.QUO && isInteger(typ) { + if op == token.QUO && isInteger(x.typ) { op = token.QUO_ASSIGN } - x.val = constant.BinaryOp(xval, op, yval) - // report error if valid operands lead to an invalid result - if xval.Kind() != constant.Unknown && yval.Kind() != constant.Unknown && x.val.Kind() == constant.Unknown { - // TODO(gri) We should report exactly what went wrong. At the - // moment we don't have the (go/constant) API for that. - // See also TODO in go/constant/value.go. - check.errorf(atPos(opPos), _InvalidConstVal, "constant result is not representable") - // TODO(gri) Should we mark operands with unknown values as invalid? - } - // Typed constants must be representable in - // their type after each constant operation. - if isTyped(typ) { - if e != nil { - x.expr = e // for better error message - } - check.representable(x, typ) - } + x.val = constant.BinaryOp(x.val, op, y.val) + x.expr = e + check.overflow(x, op, opPos) return } @@ -908,100 +1018,6 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o // x.typ is unchanged } -// index checks an index expression for validity. -// If max >= 0, it is the upper bound for index. -// If the result typ is != Typ[Invalid], index is valid and typ is its (possibly named) integer type. -// If the result val >= 0, index is valid and val is its constant int value. -func (check *Checker) index(index ast.Expr, max int64) (typ Type, val int64) { - typ = Typ[Invalid] - val = -1 - - var x operand - check.expr(&x, index) - if x.mode == invalid { - return - } - - // an untyped constant must be representable as Int - check.convertUntyped(&x, Typ[Int]) - if x.mode == invalid { - return - } - - // the index must be of integer type - if !isInteger(x.typ) { - check.invalidArg(&x, _InvalidIndex, "index %s must be integer", &x) - return - } - - if x.mode != constant_ { - return x.typ, -1 - } - - // a constant index i must be in bounds - if constant.Sign(x.val) < 0 { - check.invalidArg(&x, _InvalidIndex, "index %s must not be negative", &x) - return - } - - v, valid := constant.Int64Val(constant.ToInt(x.val)) - if !valid || max >= 0 && v >= max { - check.errorf(&x, _InvalidIndex, "index %s is out of bounds", &x) - return - } - - // 0 <= v [ && v < max ] - return Typ[Int], v -} - -// indexElts checks the elements (elts) of an array or slice composite literal -// against the literal's element type (typ), and the element indices against -// the literal length if known (length >= 0). It returns the length of the -// literal (maximum index value + 1). -// -func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64 { - visited := make(map[int64]bool, len(elts)) - var index, max int64 - for _, e := range elts { - // determine and check index - validIndex := false - eval := e - if kv, _ := e.(*ast.KeyValueExpr); kv != nil { - if typ, i := check.index(kv.Key, length); typ != Typ[Invalid] { - if i >= 0 { - index = i - validIndex = true - } else { - check.errorf(e, _InvalidLitIndex, "index %s must be integer constant", kv.Key) - } - } - eval = kv.Value - } else if length >= 0 && index >= length { - check.errorf(e, _OversizeArrayLit, "index %d is out of bounds (>= %d)", index, length) - } else { - validIndex = true - } - - // if we have a valid index, check for duplicate entries - if validIndex { - if visited[index] { - check.errorf(e, _DuplicateLitKey, "duplicate index %d in array or slice literal", index) - } - visited[index] = true - } - index++ - if index > max { - max = index - } - - // check element against composite literal element type - var x operand - check.exprWithHint(&x, eval, typ) - check.assignment(&x, typ, "array or slice literal") - } - return max -} - // exprKind describes the kind of an expression; the kind // determines if an expression is valid in 'statement context'. type exprKind int @@ -1018,7 +1034,7 @@ const ( // func (check *Checker) rawExpr(x *operand, e ast.Expr, hint Type) exprKind { if trace { - check.trace(e.Pos(), "%s", e) + check.trace(e.Pos(), "expr %s", e) check.indent++ defer func() { check.indent-- @@ -1027,31 +1043,7 @@ func (check *Checker) rawExpr(x *operand, e ast.Expr, hint Type) exprKind { } kind := check.exprInternal(x, e, hint) - - // convert x into a user-friendly set of values - // TODO(gri) this code can be simplified - var typ Type - var val constant.Value - switch x.mode { - case invalid: - typ = Typ[Invalid] - case novalue: - typ = (*Tuple)(nil) - case constant_: - typ = x.typ - val = x.val - default: - typ = x.typ - } - assert(x.expr != nil && typ != nil) - - if isUntyped(typ) { - // delay type and value recording until we know the type - // or until the end of type checking - check.rememberUntyped(x.expr, false, x.mode, typ.(*Basic), val) - } else { - check.recordTypeAndValue(e, x.mode, typ, val) - } + check.record(x) return kind } @@ -1079,6 +1071,24 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { goto Error case *ast.BasicLit: + switch e.Kind { + case token.INT, token.FLOAT, token.IMAG: + check.langCompat(e) + // The max. mantissa precision for untyped numeric values + // is 512 bits, or 4048 bits for each of the two integer + // parts of a fraction for floating-point numbers that are + // represented accurately in the go/constant package. + // Constant literals that are longer than this many bits + // are not meaningful; and excessively long constants may + // consume a lot of space and time for a useless conversion. + // Cap constant length with a generous upper limit that also + // allows for separators between all digits. + const limit = 10000 + if len(e.Value) > limit { + check.errorf(e, _InvalidConstVal, "excessively long constant: %s... (%d chars)", e.Value[:10], len(e.Value)) + goto Error + } + } x.setConst(e.Kind, e.Value) if x.mode == invalid { // The parser already establishes syntactic correctness. @@ -1091,18 +1101,20 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { case *ast.FuncLit: if sig, ok := check.typ(e.Type).(*Signature); ok { - // Anonymous functions are considered part of the - // init expression/func declaration which contains - // them: use existing package-level declaration info. - decl := check.decl // capture for use in closure below - iota := check.iota // capture for use in closure below (#22345) - // Don't type-check right away because the function may - // be part of a type definition to which the function - // body refers. Instead, type-check as soon as possible, - // but before the enclosing scope contents changes (#22992). - check.later(func() { - check.funcBody(decl, "<function literal>", sig, e.Body, iota) - }) + if !check.conf.IgnoreFuncBodies && e.Body != nil { + // Anonymous functions are considered part of the + // init expression/func declaration which contains + // them: use existing package-level declaration info. + decl := check.decl // capture for use in closure below + iota := check.iota // capture for use in closure below (#22345) + // Don't type-check right away because the function may + // be part of a type definition to which the function + // body refers. Instead, type-check as soon as possible, + // but before the enclosing scope contents changes (#22992). + check.later(func() { + check.funcBody(decl, "<function literal>", sig, e.Body, iota) + }) + } x.mode = value x.typ = sig } else { @@ -1123,7 +1135,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { // We have an "open" [...]T array type. // Create a new ArrayType with unknown length (-1) // and finish setting it up after analyzing the literal. - typ = &Array{len: -1, elem: check.typ(atyp.Elt)} + typ = &Array{len: -1, elem: check.varType(atyp.Elt)} base = typ break } @@ -1134,7 +1146,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { case hint != nil: // no composite literal type present - use hint (element type of enclosing type) typ = hint - base, _ = deref(typ.Underlying()) // *T implies &T{} + base, _ = deref(under(typ)) // *T implies &T{} default: // TODO(gri) provide better error messages depending on context @@ -1142,7 +1154,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { goto Error } - switch utyp := base.Underlying().(type) { + switch utyp := optype(base).(type) { case *Struct: if len(e.Elts) == 0 { break @@ -1270,7 +1282,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { duplicate := false // if the key is of interface type, the type is also significant when checking for duplicates xkey := keyVal(x.val) - if _, ok := utyp.key.Underlying().(*Interface); ok { + if asInterface(utyp.key) != nil { for _, vtyp := range visited[xkey] { if check.identical(vtyp, x.typ) { duplicate = true @@ -1322,184 +1334,30 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { check.selector(x, e) case *ast.IndexExpr: - check.expr(x, e.X) - if x.mode == invalid { - check.use(e.Index) - goto Error + if check.indexExpr(x, e) { + check.funcInst(x, e) } - - valid := false - length := int64(-1) // valid if >= 0 - switch typ := x.typ.Underlying().(type) { - case *Basic: - if isString(typ) { - valid = true - if x.mode == constant_ { - length = int64(len(constant.StringVal(x.val))) - } - // an indexed string always yields a byte value - // (not a constant) even if the string and the - // index are constant - x.mode = value - x.typ = universeByte // use 'byte' name - } - - case *Array: - valid = true - length = typ.len - if x.mode != variable { - x.mode = value - } - x.typ = typ.elem - - case *Pointer: - if typ, _ := typ.base.Underlying().(*Array); typ != nil { - valid = true - length = typ.len - x.mode = variable - x.typ = typ.elem - } - - case *Slice: - valid = true - x.mode = variable - x.typ = typ.elem - - case *Map: - var key operand - check.expr(&key, e.Index) - check.assignment(&key, typ.key, "map index") - // ok to continue even if indexing failed - map element type is known - x.mode = mapindex - x.typ = typ.elem - x.expr = e - return expression - } - - if !valid { - check.invalidOp(x, _NonIndexableOperand, "cannot index %s", x) - goto Error - } - - if e.Index == nil { - check.invalidAST(e, "missing index for %s", x) + if x.mode == invalid { goto Error } - check.index(e.Index, length) - // ok to continue - case *ast.SliceExpr: - check.expr(x, e.X) + check.sliceExpr(x, e) if x.mode == invalid { - check.use(e.Low, e.High, e.Max) - goto Error - } - - valid := false - length := int64(-1) // valid if >= 0 - switch typ := x.typ.Underlying().(type) { - case *Basic: - if isString(typ) { - if e.Slice3 { - check.invalidOp(x, _InvalidSliceExpr, "3-index slice of string") - goto Error - } - valid = true - if x.mode == constant_ { - length = int64(len(constant.StringVal(x.val))) - } - // spec: "For untyped string operands the result - // is a non-constant value of type string." - if typ.kind == UntypedString { - x.typ = Typ[String] - } - } - - case *Array: - valid = true - length = typ.len - if x.mode != variable { - check.invalidOp(x, _NonSliceableOperand, "cannot slice %s (value not addressable)", x) - goto Error - } - x.typ = &Slice{elem: typ.elem} - - case *Pointer: - if typ, _ := typ.base.Underlying().(*Array); typ != nil { - valid = true - length = typ.len - x.typ = &Slice{elem: typ.elem} - } - - case *Slice: - valid = true - // x.typ doesn't change - } - - if !valid { - check.invalidOp(x, _NonSliceableOperand, "cannot slice %s", x) - goto Error - } - - x.mode = value - - // spec: "Only the first index may be omitted; it defaults to 0." - if e.Slice3 && (e.High == nil || e.Max == nil) { - check.invalidAST(inNode(e, e.Rbrack), "2nd and 3rd index required in 3-index slice") goto Error } - // check indices - var ind [3]int64 - for i, expr := range []ast.Expr{e.Low, e.High, e.Max} { - x := int64(-1) - switch { - case expr != nil: - // The "capacity" is only known statically for strings, arrays, - // and pointers to arrays, and it is the same as the length for - // those types. - max := int64(-1) - if length >= 0 { - max = length + 1 - } - if _, v := check.index(expr, max); v >= 0 { - x = v - } - case i == 0: - // default is 0 for the first index - x = 0 - case length >= 0: - // default is length (== capacity) otherwise - x = length - } - ind[i] = x - } - - // constant indices must be in range - // (check.index already checks that existing indices >= 0) - L: - for i, x := range ind[:len(ind)-1] { - if x > 0 { - for _, y := range ind[i+1:] { - if y >= 0 && x > y { - check.errorf(inNode(e, e.Rbrack), _SwappedSliceIndices, "swapped slice indices: %d > %d", x, y) - break L // only report one error, ok to continue - } - } - } - } - case *ast.TypeAssertExpr: check.expr(x, e.X) if x.mode == invalid { goto Error } - xtyp, _ := x.typ.Underlying().(*Interface) + xtyp, _ := under(x.typ).(*Interface) if xtyp == nil { check.invalidOp(x, _InvalidAssert, "%s is not an interface", x) goto Error } + check.ordinaryType(x, xtyp) // x.(type) expressions are handled explicitly in type switches if e.Type == nil { // Don't use invalidAST because this can occur in the AST produced by @@ -1507,7 +1365,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { check.error(e, _BadTypeKeyword, "use of .(type) outside type switch") goto Error } - T := check.typ(e.Type) + T := check.varType(e.Type) if T == Typ[Invalid] { goto Error } @@ -1516,7 +1374,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { x.typ = T case *ast.CallExpr: - return check.call(x, e) + return check.callExpr(x, e) case *ast.StarExpr: check.exprOrType(x, e.X) @@ -1526,7 +1384,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { case typexpr: x.typ = &Pointer{base: x.typ} default: - if typ, ok := x.typ.Underlying().(*Pointer); ok { + if typ := asPointer(x.typ); typ != nil { x.mode = variable x.typ = typ.base } else { @@ -1536,11 +1394,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { } case *ast.UnaryExpr: - check.expr(x, e.X) - if x.mode == invalid { - goto Error - } - check.unary(x, e, e.Op) + check.unary(x, e) if x.mode == invalid { goto Error } @@ -1571,7 +1425,12 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { // types, which are comparatively rare. default: - panic(fmt.Sprintf("%s: unknown expression type %T", check.fset.Position(e.Pos()), e)) + if typeparams.IsListExpr(e) { + // catch-all for unexpected expression lists + check.errorf(e, _Todo, "unexpected list of expressions") + } else { + panic(fmt.Sprintf("%s: unknown expression type %T", check.fset.Position(e.Pos()), e)) + } } // everything went well @@ -1627,46 +1486,20 @@ func (check *Checker) typeAssertion(at positioner, x *operand, xtyp *Interface, check.errorf(at, _ImpossibleAssert, "%s cannot have dynamic type %s (%s)", x, T, msg) } -func (check *Checker) singleValue(x *operand) { - if x.mode == value { - // tuple types are never named - no need for underlying type below - if t, ok := x.typ.(*Tuple); ok { - assert(t.Len() != 1) - check.errorf(x, _TooManyValues, "%d-valued %s where single value is expected", t.Len(), x) - x.mode = invalid - } - } -} - // expr typechecks expression e and initializes x with the expression value. // The result must be a single value. // If an error occurred, x.mode is set to invalid. // func (check *Checker) expr(x *operand, e ast.Expr) { - check.multiExpr(x, e) + check.rawExpr(x, e, nil) + check.exclude(x, 1<<novalue|1<<builtin|1<<typexpr) check.singleValue(x) } -// multiExpr is like expr but the result may be a multi-value. +// multiExpr is like expr but the result may also be a multi-value. func (check *Checker) multiExpr(x *operand, e ast.Expr) { check.rawExpr(x, e, nil) - var msg string - var code errorCode - switch x.mode { - default: - return - case novalue: - msg = "%s used as value" - code = _TooManyValues - case builtin: - msg = "%s must be called" - code = _UncalledBuiltin - case typexpr: - msg = "%s is not an expression" - code = _NotAnExpr - } - check.errorf(x, code, msg, x) - x.mode = invalid + check.exclude(x, 1<<novalue|1<<builtin|1<<typexpr) } // exprWithHint typechecks expression e and initializes x with the expression value; @@ -1676,24 +1509,8 @@ func (check *Checker) multiExpr(x *operand, e ast.Expr) { func (check *Checker) exprWithHint(x *operand, e ast.Expr, hint Type) { assert(hint != nil) check.rawExpr(x, e, hint) + check.exclude(x, 1<<novalue|1<<builtin|1<<typexpr) check.singleValue(x) - var msg string - var code errorCode - switch x.mode { - default: - return - case novalue: - msg = "%s used as value" - code = _TooManyValues - case builtin: - msg = "%s must be called" - code = _UncalledBuiltin - case typexpr: - msg = "%s is not an expression" - code = _NotAnExpr - } - check.errorf(x, code, msg, x) - x.mode = invalid } // exprOrType typechecks expression or type e and initializes x with the expression value or type. @@ -1701,9 +1518,46 @@ func (check *Checker) exprWithHint(x *operand, e ast.Expr, hint Type) { // func (check *Checker) exprOrType(x *operand, e ast.Expr) { check.rawExpr(x, e, nil) + check.exclude(x, 1<<novalue) check.singleValue(x) - if x.mode == novalue { - check.errorf(x, _NotAnExpr, "%s used as value or type", x) +} + +// exclude reports an error if x.mode is in modeset and sets x.mode to invalid. +// The modeset may contain any of 1<<novalue, 1<<builtin, 1<<typexpr. +func (check *Checker) exclude(x *operand, modeset uint) { + if modeset&(1<<x.mode) != 0 { + var msg string + var code errorCode + switch x.mode { + case novalue: + if modeset&(1<<typexpr) != 0 { + msg = "%s used as value" + } else { + msg = "%s used as value or type" + } + code = _TooManyValues + case builtin: + msg = "%s must be called" + code = _UncalledBuiltin + case typexpr: + msg = "%s is not an expression" + code = _NotAnExpr + default: + unreachable() + } + check.errorf(x, code, msg, x) x.mode = invalid } } + +// singleValue reports an error if x describes a tuple and sets x.mode to invalid. +func (check *Checker) singleValue(x *operand) { + if x.mode == value { + // tuple types are never named - no need for underlying type below + if t, ok := x.typ.(*Tuple); ok { + assert(t.Len() != 1) + check.errorf(x, _TooManyValues, "%d-valued %s where single value is expected", t.Len(), x) + x.mode = invalid + } + } +} diff --git a/libgo/go/go/types/exprstring.go b/libgo/go/go/types/exprstring.go index 28d605f..f05e642 100644 --- a/libgo/go/go/types/exprstring.go +++ b/libgo/go/go/types/exprstring.go @@ -8,7 +8,9 @@ package types import ( "bytes" + "fmt" "go/ast" + "go/internal/typeparams" ) // ExprString returns the (possibly shortened) string representation for x. @@ -31,7 +33,7 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) { switch x := x.(type) { default: - buf.WriteString("(bad expr)") // nil, ast.BadExpr, ast.KeyValueExpr + buf.WriteString(fmt.Sprintf("(ast: %T)", x)) // nil, ast.BadExpr, ast.KeyValueExpr case *ast.Ident: buf.WriteString(x.Name) @@ -68,7 +70,13 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) { case *ast.IndexExpr: WriteExpr(buf, x.X) buf.WriteByte('[') - WriteExpr(buf, x.Index) + exprs := typeparams.UnpackExpr(x.Index) + for i, e := range exprs { + if i > 0 { + buf.WriteString(", ") + } + WriteExpr(buf, e) + } buf.WriteByte(']') case *ast.SliceExpr: @@ -98,12 +106,7 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) { case *ast.CallExpr: WriteExpr(buf, x.Fun) buf.WriteByte('(') - for i, arg := range x.Args { - if i > 0 { - buf.WriteString(", ") - } - WriteExpr(buf, arg) - } + writeExprList(buf, x.Args) if x.Ellipsis.IsValid() { buf.WriteString("...") } @@ -134,7 +137,7 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) { case *ast.StructType: buf.WriteString("struct{") - writeFieldList(buf, x.Fields, "; ", false) + writeFieldList(buf, x.Fields.List, "; ", false) buf.WriteByte('}') case *ast.FuncType: @@ -142,8 +145,29 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) { writeSigExpr(buf, x) case *ast.InterfaceType: + // separate type list types from method list + // TODO(gri) we can get rid of this extra code if writeExprList does the separation + var types []ast.Expr + var methods []*ast.Field + for _, f := range x.Methods.List { + if len(f.Names) > 1 && f.Names[0].Name == "type" { + // type list type + types = append(types, f.Type) + } else { + // method or embedded interface + methods = append(methods, f) + } + } + buf.WriteString("interface{") - writeFieldList(buf, x.Methods, "; ", true) + writeFieldList(buf, methods, "; ", true) + if len(types) > 0 { + if len(methods) > 0 { + buf.WriteString("; ") + } + buf.WriteString("type ") + writeExprList(buf, types) + } buf.WriteByte('}') case *ast.MapType: @@ -169,7 +193,7 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) { func writeSigExpr(buf *bytes.Buffer, sig *ast.FuncType) { buf.WriteByte('(') - writeFieldList(buf, sig.Params, ", ", false) + writeFieldList(buf, sig.Params.List, ", ", false) buf.WriteByte(')') res := sig.Results @@ -188,23 +212,18 @@ func writeSigExpr(buf *bytes.Buffer, sig *ast.FuncType) { // multiple or named result(s) buf.WriteByte('(') - writeFieldList(buf, res, ", ", false) + writeFieldList(buf, res.List, ", ", false) buf.WriteByte(')') } -func writeFieldList(buf *bytes.Buffer, fields *ast.FieldList, sep string, iface bool) { - for i, f := range fields.List { +func writeFieldList(buf *bytes.Buffer, list []*ast.Field, sep string, iface bool) { + for i, f := range list { if i > 0 { buf.WriteString(sep) } // field list names - for i, name := range f.Names { - if i > 0 { - buf.WriteString(", ") - } - buf.WriteString(name.Name) - } + writeIdentList(buf, f.Names) // types of interface methods consist of signatures only if sig, _ := f.Type.(*ast.FuncType); sig != nil && iface { @@ -222,3 +241,21 @@ func writeFieldList(buf *bytes.Buffer, fields *ast.FieldList, sep string, iface // ignore tag } } + +func writeIdentList(buf *bytes.Buffer, list []*ast.Ident) { + for i, x := range list { + if i > 0 { + buf.WriteString(", ") + } + buf.WriteString(x.Name) + } +} + +func writeExprList(buf *bytes.Buffer, list []ast.Expr) { + for i, x := range list { + if i > 0 { + buf.WriteString(", ") + } + WriteExpr(buf, x) + } +} diff --git a/libgo/go/go/types/gotype.go b/libgo/go/go/types/gotype.go index 52709df..ca1d42c 100644 --- a/libgo/go/go/types/gotype.go +++ b/libgo/go/go/types/gotype.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // Build this command explicitly: go build gotype.go diff --git a/libgo/go/go/types/index.go b/libgo/go/go/types/index.go new file mode 100644 index 0000000..2ba3475 --- /dev/null +++ b/libgo/go/go/types/index.go @@ -0,0 +1,446 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file implements typechecking of index/slice expressions. + +package types + +import ( + "go/ast" + "go/constant" + "go/internal/typeparams" +) + +// If e is a valid function instantiation, indexExpr returns true. +// In that case x represents the uninstantiated function value and +// it is the caller's responsibility to instantiate the function. +func (check *Checker) indexExpr(x *operand, e *ast.IndexExpr) (isFuncInst bool) { + check.exprOrType(x, e.X) + + switch x.mode { + case invalid: + check.use(typeparams.UnpackExpr(e.Index)...) + return false + + case typexpr: + // type instantiation + x.mode = invalid + x.typ = check.varType(e) + if x.typ != Typ[Invalid] { + x.mode = typexpr + } + return false + + case value: + if sig := asSignature(x.typ); sig != nil && len(sig.tparams) > 0 { + // function instantiation + return true + } + } + + valid := false + length := int64(-1) // valid if >= 0 + switch typ := optype(x.typ).(type) { + case *Basic: + if isString(typ) { + valid = true + if x.mode == constant_ { + length = int64(len(constant.StringVal(x.val))) + } + // an indexed string always yields a byte value + // (not a constant) even if the string and the + // index are constant + x.mode = value + x.typ = universeByte // use 'byte' name + } + + case *Array: + valid = true + length = typ.len + if x.mode != variable { + x.mode = value + } + x.typ = typ.elem + + case *Pointer: + if typ := asArray(typ.base); typ != nil { + valid = true + length = typ.len + x.mode = variable + x.typ = typ.elem + } + + case *Slice: + valid = true + x.mode = variable + x.typ = typ.elem + + case *Map: + index := check.singleIndex(e) + if index == nil { + x.mode = invalid + return + } + var key operand + check.expr(&key, index) + check.assignment(&key, typ.key, "map index") + // ok to continue even if indexing failed - map element type is known + x.mode = mapindex + x.typ = typ.elem + x.expr = e + return + + case *_Sum: + // A sum type can be indexed if all of the sum's types + // support indexing and have the same index and element + // type. Special rules apply for maps in the sum type. + var tkey, telem Type // key is for map types only + nmaps := 0 // number of map types in sum type + if typ.is(func(t Type) bool { + var e Type + switch t := under(t).(type) { + case *Basic: + if isString(t) { + e = universeByte + } + case *Array: + e = t.elem + case *Pointer: + if t := asArray(t.base); t != nil { + e = t.elem + } + case *Slice: + e = t.elem + case *Map: + // If there are multiple maps in the sum type, + // they must have identical key types. + // TODO(gri) We may be able to relax this rule + // but it becomes complicated very quickly. + if tkey != nil && !Identical(t.key, tkey) { + return false + } + tkey = t.key + e = t.elem + nmaps++ + case *_TypeParam: + check.errorf(x, 0, "type of %s contains a type parameter - cannot index (implementation restriction)", x) + case *instance: + panic("unimplemented") + } + if e == nil || telem != nil && !Identical(e, telem) { + return false + } + telem = e + return true + }) { + // If there are maps, the index expression must be assignable + // to the map key type (as for simple map index expressions). + if nmaps > 0 { + index := check.singleIndex(e) + if index == nil { + x.mode = invalid + return + } + var key operand + check.expr(&key, index) + check.assignment(&key, tkey, "map index") + // ok to continue even if indexing failed - map element type is known + + // If there are only maps, we are done. + if nmaps == len(typ.types) { + x.mode = mapindex + x.typ = telem + x.expr = e + return + } + + // Otherwise we have mix of maps and other types. For + // now we require that the map key be an integer type. + // TODO(gri) This is probably not good enough. + valid = isInteger(tkey) + // avoid 2nd indexing error if indexing failed above + if !valid && key.mode == invalid { + x.mode = invalid + return + } + x.mode = value // map index expressions are not addressable + } else { + // no maps + valid = true + x.mode = variable + } + x.typ = telem + } + } + + if !valid { + check.invalidOp(x, _NonIndexableOperand, "cannot index %s", x) + x.mode = invalid + return + } + + index := check.singleIndex(e) + if index == nil { + x.mode = invalid + return + } + + // In pathological (invalid) cases (e.g.: type T1 [][[]T1{}[0][0]]T0) + // the element type may be accessed before it's set. Make sure we have + // a valid type. + if x.typ == nil { + x.typ = Typ[Invalid] + } + + check.index(index, length) + return false +} + +func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { + check.expr(x, e.X) + if x.mode == invalid { + check.use(e.Low, e.High, e.Max) + return + } + + valid := false + length := int64(-1) // valid if >= 0 + switch typ := optype(x.typ).(type) { + case *Basic: + if isString(typ) { + if e.Slice3 { + check.invalidOp(x, _InvalidSliceExpr, "3-index slice of string") + x.mode = invalid + return + } + valid = true + if x.mode == constant_ { + length = int64(len(constant.StringVal(x.val))) + } + // spec: "For untyped string operands the result + // is a non-constant value of type string." + if typ.kind == UntypedString { + x.typ = Typ[String] + } + } + + case *Array: + valid = true + length = typ.len + if x.mode != variable { + check.invalidOp(x, _NonSliceableOperand, "cannot slice %s (value not addressable)", x) + x.mode = invalid + return + } + x.typ = &Slice{elem: typ.elem} + + case *Pointer: + if typ := asArray(typ.base); typ != nil { + valid = true + length = typ.len + x.typ = &Slice{elem: typ.elem} + } + + case *Slice: + valid = true + // x.typ doesn't change + + case *_Sum, *_TypeParam: + check.errorf(x, 0, "generic slice expressions not yet implemented") + x.mode = invalid + return + } + + if !valid { + check.invalidOp(x, _NonSliceableOperand, "cannot slice %s", x) + x.mode = invalid + return + } + + x.mode = value + + // spec: "Only the first index may be omitted; it defaults to 0." + if e.Slice3 && (e.High == nil || e.Max == nil) { + check.invalidAST(inNode(e, e.Rbrack), "2nd and 3rd index required in 3-index slice") + x.mode = invalid + return + } + + // check indices + var ind [3]int64 + for i, expr := range []ast.Expr{e.Low, e.High, e.Max} { + x := int64(-1) + switch { + case expr != nil: + // The "capacity" is only known statically for strings, arrays, + // and pointers to arrays, and it is the same as the length for + // those types. + max := int64(-1) + if length >= 0 { + max = length + 1 + } + if _, v := check.index(expr, max); v >= 0 { + x = v + } + case i == 0: + // default is 0 for the first index + x = 0 + case length >= 0: + // default is length (== capacity) otherwise + x = length + } + ind[i] = x + } + + // constant indices must be in range + // (check.index already checks that existing indices >= 0) +L: + for i, x := range ind[:len(ind)-1] { + if x > 0 { + for _, y := range ind[i+1:] { + if y >= 0 && x > y { + check.errorf(inNode(e, e.Rbrack), _SwappedSliceIndices, "swapped slice indices: %d > %d", x, y) + break L // only report one error, ok to continue + } + } + } + } +} + +// singleIndex returns the (single) index from the index expression e. +// If the index is missing, or if there are multiple indices, an error +// is reported and the result is nil. +func (check *Checker) singleIndex(e *ast.IndexExpr) ast.Expr { + index := e.Index + if index == nil { + check.invalidAST(e, "missing index for %s", e) + return nil + } + + indexes := typeparams.UnpackExpr(index) + if len(indexes) == 0 { + check.invalidAST(index, "index expression %v with 0 indices", index) + return nil + } + if len(indexes) > 1 { + // TODO(rFindley) should this get a distinct error code? + check.invalidOp(indexes[1], _InvalidIndex, "more than one index") + } + return indexes[0] +} + +// index checks an index expression for validity. +// If max >= 0, it is the upper bound for index. +// If the result typ is != Typ[Invalid], index is valid and typ is its (possibly named) integer type. +// If the result val >= 0, index is valid and val is its constant int value. +func (check *Checker) index(index ast.Expr, max int64) (typ Type, val int64) { + typ = Typ[Invalid] + val = -1 + + var x operand + check.expr(&x, index) + if !check.isValidIndex(&x, _InvalidIndex, "index", false) { + return + } + + if x.mode != constant_ { + return x.typ, -1 + } + + if x.val.Kind() == constant.Unknown { + return + } + + v, ok := constant.Int64Val(x.val) + assert(ok) + if max >= 0 && v >= max { + check.invalidArg(&x, _InvalidIndex, "index %s is out of bounds", &x) + return + } + + // 0 <= v [ && v < max ] + return x.typ, v +} + +func (check *Checker) isValidIndex(x *operand, code errorCode, what string, allowNegative bool) bool { + if x.mode == invalid { + return false + } + + // spec: "a constant index that is untyped is given type int" + check.convertUntyped(x, Typ[Int]) + if x.mode == invalid { + return false + } + + // spec: "the index x must be of integer type or an untyped constant" + if !isInteger(x.typ) { + check.invalidArg(x, code, "%s %s must be integer", what, x) + return false + } + + if x.mode == constant_ { + // spec: "a constant index must be non-negative ..." + if !allowNegative && constant.Sign(x.val) < 0 { + check.invalidArg(x, code, "%s %s must not be negative", what, x) + return false + } + + // spec: "... and representable by a value of type int" + if !representableConst(x.val, check, Typ[Int], &x.val) { + check.invalidArg(x, code, "%s %s overflows int", what, x) + return false + } + } + + return true +} + +// indexElts checks the elements (elts) of an array or slice composite literal +// against the literal's element type (typ), and the element indices against +// the literal length if known (length >= 0). It returns the length of the +// literal (maximum index value + 1). +// +func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64 { + visited := make(map[int64]bool, len(elts)) + var index, max int64 + for _, e := range elts { + // determine and check index + validIndex := false + eval := e + if kv, _ := e.(*ast.KeyValueExpr); kv != nil { + if typ, i := check.index(kv.Key, length); typ != Typ[Invalid] { + if i >= 0 { + index = i + validIndex = true + } else { + check.errorf(e, _InvalidLitIndex, "index %s must be integer constant", kv.Key) + } + } + eval = kv.Value + } else if length >= 0 && index >= length { + check.errorf(e, _OversizeArrayLit, "index %d is out of bounds (>= %d)", index, length) + } else { + validIndex = true + } + + // if we have a valid index, check for duplicate entries + if validIndex { + if visited[index] { + check.errorf(e, _DuplicateLitKey, "duplicate index %d in array or slice literal", index) + } + visited[index] = true + } + index++ + if index > max { + max = index + } + + // check element against composite literal element type + var x operand + check.exprWithHint(&x, eval, typ) + check.assignment(&x, typ, "array or slice literal") + } + return max +} diff --git a/libgo/go/go/types/infer.go b/libgo/go/go/types/infer.go new file mode 100644 index 0000000..5d49351 --- /dev/null +++ b/libgo/go/go/types/infer.go @@ -0,0 +1,482 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file implements type parameter inference given +// a list of concrete arguments and a parameter list. + +package types + +import ( + "go/token" + "strings" +) + +// infer attempts to infer the complete set of type arguments for generic function instantiation/call +// based on the given type parameters tparams, type arguments targs, function parameters params, and +// function arguments args, if any. There must be at least one type parameter, no more type arguments +// than type parameters, and params and args must match in number (incl. zero). +// If successful, infer returns the complete list of type arguments, one for each type parameter. +// Otherwise the result is nil and appropriate errors will be reported unless report is set to false. +// +// Inference proceeds in 3 steps: +// +// 1) Start with given type arguments. +// 2) Infer type arguments from typed function arguments. +// 3) Infer type arguments from untyped function arguments. +// +// Constraint type inference is used after each step to expand the set of type arguments. +// +func (check *Checker) infer(posn positioner, tparams []*TypeName, targs []Type, params *Tuple, args []*operand, report bool) (result []Type) { + if debug { + defer func() { + assert(result == nil || len(result) == len(tparams)) + for _, targ := range result { + assert(targ != nil) + } + //check.dump("### inferred targs = %s", result) + }() + } + + // There must be at least one type parameter, and no more type arguments than type parameters. + n := len(tparams) + assert(n > 0 && len(targs) <= n) + + // Function parameters and arguments must match in number. + assert(params.Len() == len(args)) + + // --- 0 --- + // If we already have all type arguments, we're done. + if len(targs) == n { + return targs + } + // len(targs) < n + + // --- 1 --- + // Explicitly provided type arguments take precedence over any inferred types; + // and types inferred via constraint type inference take precedence over types + // inferred from function arguments. + // If we have type arguments, see how far we get with constraint type inference. + if len(targs) > 0 { + var index int + targs, index = check.inferB(tparams, targs, report) + if targs == nil || index < 0 { + return targs + } + } + + // Continue with the type arguments we have now. Avoid matching generic + // parameters that already have type arguments against function arguments: + // It may fail because matching uses type identity while parameter passing + // uses assignment rules. Instantiate the parameter list with the type + // arguments we have, and continue with that parameter list. + + // First, make sure we have a "full" list of type arguments, so of which + // may be nil (unknown). + if len(targs) < n { + targs2 := make([]Type, n) + copy(targs2, targs) + targs = targs2 + } + // len(targs) == n + + // Substitute type arguments for their respective type parameters in params, + // if any. Note that nil targs entries are ignored by check.subst. + // TODO(gri) Can we avoid this (we're setting known type argumemts below, + // but that doesn't impact the isParameterized check for now). + if params.Len() > 0 { + smap := makeSubstMap(tparams, targs) + params = check.subst(token.NoPos, params, smap).(*Tuple) + } + + // --- 2 --- + // Unify parameter and argument types for generic parameters with typed arguments + // and collect the indices of generic parameters with untyped arguments. + // Terminology: generic parameter = function parameter with a type-parameterized type + u := newUnifier(check, false) + u.x.init(tparams) + + // Set the type arguments which we know already. + for i, targ := range targs { + if targ != nil { + u.x.set(i, targ) + } + } + + errorf := func(kind string, tpar, targ Type, arg *operand) { + if !report { + return + } + // provide a better error message if we can + targs, index := u.x.types() + if index == 0 { + // The first type parameter couldn't be inferred. + // If none of them could be inferred, don't try + // to provide the inferred type in the error msg. + allFailed := true + for _, targ := range targs { + if targ != nil { + allFailed = false + break + } + } + if allFailed { + check.errorf(arg, _Todo, "%s %s of %s does not match %s (cannot infer %s)", kind, targ, arg.expr, tpar, typeNamesString(tparams)) + return + } + } + smap := makeSubstMap(tparams, targs) + // TODO(rFindley): pass a positioner here, rather than arg.Pos(). + inferred := check.subst(arg.Pos(), tpar, smap) + if inferred != tpar { + check.errorf(arg, _Todo, "%s %s of %s does not match inferred type %s for %s", kind, targ, arg.expr, inferred, tpar) + } else { + check.errorf(arg, 0, "%s %s of %s does not match %s", kind, targ, arg.expr, tpar) + } + } + + // indices of the generic parameters with untyped arguments - save for later + var indices []int + for i, arg := range args { + par := params.At(i) + // If we permit bidirectional unification, this conditional code needs to be + // executed even if par.typ is not parameterized since the argument may be a + // generic function (for which we want to infer its type arguments). + if isParameterized(tparams, par.typ) { + if arg.mode == invalid { + // An error was reported earlier. Ignore this targ + // and continue, we may still be able to infer all + // targs resulting in fewer follon-on errors. + continue + } + if targ := arg.typ; isTyped(targ) { + // If we permit bidirectional unification, and targ is + // a generic function, we need to initialize u.y with + // the respective type parameters of targ. + if !u.unify(par.typ, targ) { + errorf("type", par.typ, targ, arg) + return nil + } + } else { + indices = append(indices, i) + } + } + } + + // If we've got all type arguments, we're done. + var index int + targs, index = u.x.types() + if index < 0 { + return targs + } + + // See how far we get with constraint type inference. + // Note that even if we don't have any type arguments, constraint type inference + // may produce results for constraints that explicitly specify a type. + targs, index = check.inferB(tparams, targs, report) + if targs == nil || index < 0 { + return targs + } + + // --- 3 --- + // Use any untyped arguments to infer additional type arguments. + // Some generic parameters with untyped arguments may have been given + // a type by now, we can ignore them. + for _, i := range indices { + par := params.At(i) + // Since untyped types are all basic (i.e., non-composite) types, an + // untyped argument will never match a composite parameter type; the + // only parameter type it can possibly match against is a *TypeParam. + // Thus, only consider untyped arguments for generic parameters that + // are not of composite types and which don't have a type inferred yet. + if tpar, _ := par.typ.(*_TypeParam); tpar != nil && targs[tpar.index] == nil { + arg := args[i] + targ := Default(arg.typ) + // The default type for an untyped nil is untyped nil. We must not + // infer an untyped nil type as type parameter type. Ignore untyped + // nil by making sure all default argument types are typed. + if isTyped(targ) && !u.unify(par.typ, targ) { + errorf("default type", par.typ, targ, arg) + return nil + } + } + } + + // If we've got all type arguments, we're done. + targs, index = u.x.types() + if index < 0 { + return targs + } + + // Again, follow up with constraint type inference. + targs, index = check.inferB(tparams, targs, report) + if targs == nil || index < 0 { + return targs + } + + // At least one type argument couldn't be inferred. + assert(index >= 0 && targs[index] == nil) + tpar := tparams[index] + if report { + check.errorf(posn, _Todo, "cannot infer %s (%v) (%v)", tpar.name, tpar.pos, targs) + } + return nil +} + +// typeNamesString produces a string containing all the +// type names in list suitable for human consumption. +func typeNamesString(list []*TypeName) string { + // common cases + n := len(list) + switch n { + case 0: + return "" + case 1: + return list[0].name + case 2: + return list[0].name + " and " + list[1].name + } + + // general case (n > 2) + var b strings.Builder + for i, tname := range list[:n-1] { + if i > 0 { + b.WriteString(", ") + } + b.WriteString(tname.name) + } + b.WriteString(", and ") + b.WriteString(list[n-1].name) + return b.String() +} + +// IsParameterized reports whether typ contains any of the type parameters of tparams. +func isParameterized(tparams []*TypeName, typ Type) bool { + w := tpWalker{ + seen: make(map[Type]bool), + tparams: tparams, + } + return w.isParameterized(typ) +} + +type tpWalker struct { + seen map[Type]bool + tparams []*TypeName +} + +func (w *tpWalker) isParameterized(typ Type) (res bool) { + // detect cycles + if x, ok := w.seen[typ]; ok { + return x + } + w.seen[typ] = false + defer func() { + w.seen[typ] = res + }() + + switch t := typ.(type) { + case nil, *Basic: // TODO(gri) should nil be handled here? + break + + case *Array: + return w.isParameterized(t.elem) + + case *Slice: + return w.isParameterized(t.elem) + + case *Struct: + for _, fld := range t.fields { + if w.isParameterized(fld.typ) { + return true + } + } + + case *Pointer: + return w.isParameterized(t.base) + + case *Tuple: + n := t.Len() + for i := 0; i < n; i++ { + if w.isParameterized(t.At(i).typ) { + return true + } + } + + case *_Sum: + return w.isParameterizedList(t.types) + + case *Signature: + // t.tparams may not be nil if we are looking at a signature + // of a generic function type (or an interface method) that is + // part of the type we're testing. We don't care about these type + // parameters. + // Similarly, the receiver of a method may declare (rather then + // use) type parameters, we don't care about those either. + // Thus, we only need to look at the input and result parameters. + return w.isParameterized(t.params) || w.isParameterized(t.results) + + case *Interface: + if t.allMethods != nil { + // TODO(rFindley) at some point we should enforce completeness here + for _, m := range t.allMethods { + if w.isParameterized(m.typ) { + return true + } + } + return w.isParameterizedList(unpackType(t.allTypes)) + } + + return t.iterate(func(t *Interface) bool { + for _, m := range t.methods { + if w.isParameterized(m.typ) { + return true + } + } + return w.isParameterizedList(unpackType(t.types)) + }, nil) + + case *Map: + return w.isParameterized(t.key) || w.isParameterized(t.elem) + + case *Chan: + return w.isParameterized(t.elem) + + case *Named: + return w.isParameterizedList(t.targs) + + case *_TypeParam: + // t must be one of w.tparams + return t.index < len(w.tparams) && w.tparams[t.index].typ == t + + case *instance: + return w.isParameterizedList(t.targs) + + default: + unreachable() + } + + return false +} + +func (w *tpWalker) isParameterizedList(list []Type) bool { + for _, t := range list { + if w.isParameterized(t) { + return true + } + } + return false +} + +// inferB returns the list of actual type arguments inferred from the type parameters' +// bounds and an initial set of type arguments. If type inference is impossible because +// unification fails, an error is reported if report is set to true, the resulting types +// list is nil, and index is 0. +// Otherwise, types is the list of inferred type arguments, and index is the index of the +// first type argument in that list that couldn't be inferred (and thus is nil). If all +// type arguments were inferred successfully, index is < 0. The number of type arguments +// provided may be less than the number of type parameters, but there must be at least one. +func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (types []Type, index int) { + assert(len(tparams) >= len(targs) && len(targs) > 0) + + // Setup bidirectional unification between those structural bounds + // and the corresponding type arguments (which may be nil!). + u := newUnifier(check, false) + u.x.init(tparams) + u.y = u.x // type parameters between LHS and RHS of unification are identical + + // Set the type arguments which we know already. + for i, targ := range targs { + if targ != nil { + u.x.set(i, targ) + } + } + + // Unify type parameters with their structural constraints, if any. + for _, tpar := range tparams { + typ := tpar.typ.(*_TypeParam) + sbound := check.structuralType(typ.bound) + if sbound != nil { + if !u.unify(typ, sbound) { + if report { + check.errorf(tpar, _Todo, "%s does not match %s", tpar, sbound) + } + return nil, 0 + } + } + } + + // u.x.types() now contains the incoming type arguments plus any additional type + // arguments for which there were structural constraints. The newly inferred non- + // nil entries may still contain references to other type parameters. For instance, + // for [A any, B interface{type []C}, C interface{type *A}], if A == int + // was given, unification produced the type list [int, []C, *A]. We eliminate the + // remaining type parameters by substituting the type parameters in this type list + // until nothing changes anymore. + types, _ = u.x.types() + if debug { + for i, targ := range targs { + assert(targ == nil || types[i] == targ) + } + } + + // dirty tracks the indices of all types that may still contain type parameters. + // We know that nil type entries and entries corresponding to provided (non-nil) + // type arguments are clean, so exclude them from the start. + var dirty []int + for i, typ := range types { + if typ != nil && (i >= len(targs) || targs[i] == nil) { + dirty = append(dirty, i) + } + } + + for len(dirty) > 0 { + // TODO(gri) Instead of creating a new substMap for each iteration, + // provide an update operation for substMaps and only change when + // needed. Optimization. + smap := makeSubstMap(tparams, types) + n := 0 + for _, index := range dirty { + t0 := types[index] + if t1 := check.subst(token.NoPos, t0, smap); t1 != t0 { + types[index] = t1 + dirty[n] = index + n++ + } + } + dirty = dirty[:n] + } + + // Once nothing changes anymore, we may still have type parameters left; + // e.g., a structural constraint *P may match a type parameter Q but we + // don't have any type arguments to fill in for *P or Q (issue #45548). + // Don't let such inferences escape, instead nil them out. + for i, typ := range types { + if typ != nil && isParameterized(tparams, typ) { + types[i] = nil + } + } + + // update index + index = -1 + for i, typ := range types { + if typ == nil { + index = i + break + } + } + + return +} + +// structuralType returns the structural type of a constraint, if any. +func (check *Checker) structuralType(constraint Type) Type { + if iface, _ := under(constraint).(*Interface); iface != nil { + check.completeInterface(token.NoPos, iface) + types := unpackType(iface.allTypes) + if len(types) == 1 { + return types[0] + } + return nil + } + return constraint +} diff --git a/libgo/go/go/types/issues_test.go b/libgo/go/go/types/issues_test.go index 34850eb..6d08f88 100644 --- a/libgo/go/go/types/issues_test.go +++ b/libgo/go/go/types/issues_test.go @@ -385,9 +385,9 @@ func TestIssue28005(t *testing.T) { } } if obj == nil { - t.Fatal("interface not found") + t.Fatal("object X not found") } - iface := obj.Type().Underlying().(*Interface) // I must be an interface + iface := obj.Type().Underlying().(*Interface) // object X must be an interface // Each iface method m is embedded; and m's receiver base type name // must match the method's name per the choice in the source file. @@ -477,7 +477,7 @@ func TestIssue34151(t *testing.T) { } bast := mustParse(t, bsrc) - conf := Config{Importer: importHelper{a}} + conf := Config{Importer: importHelper{pkg: a}} b, err := conf.Check(bast.Name.Name, fset, []*ast.File{bast}, nil) if err != nil { t.Errorf("package %s failed to typecheck: %v", b.Name(), err) @@ -485,14 +485,18 @@ func TestIssue34151(t *testing.T) { } type importHelper struct { - pkg *Package + pkg *Package + fallback Importer } func (h importHelper) Import(path string) (*Package, error) { - if path != h.pkg.Path() { + if path == h.pkg.Path() { + return h.pkg, nil + } + if h.fallback == nil { return nil, fmt.Errorf("got package path %q; want %q", path, h.pkg.Path()) } - return h.pkg, nil + return h.fallback.Import(path) } // TestIssue34921 verifies that we don't update an imported type's underlying @@ -516,7 +520,7 @@ func TestIssue34921(t *testing.T) { var pkg *Package for _, src := range sources { f := mustParse(t, src) - conf := Config{Importer: importHelper{pkg}} + conf := Config{Importer: importHelper{pkg: pkg}} res, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil) if err != nil { t.Errorf("%q failed to typecheck: %v", src, err) @@ -549,3 +553,90 @@ func TestIssue43088(t *testing.T) { Comparable(T1) Comparable(T2) } + +func TestIssue44515(t *testing.T) { + typ := Unsafe.Scope().Lookup("Pointer").Type() + + got := TypeString(typ, nil) + want := "unsafe.Pointer" + if got != want { + t.Errorf("got %q; want %q", got, want) + } + + qf := func(pkg *Package) string { + if pkg == Unsafe { + return "foo" + } + return "" + } + got = TypeString(typ, qf) + want = "foo.Pointer" + if got != want { + t.Errorf("got %q; want %q", got, want) + } +} + +func TestIssue43124(t *testing.T) { + t.Skip("skipping for gccgo--no importer") + + // TODO(rFindley) move this to testdata by enhancing support for importing. + + // All involved packages have the same name (template). Error messages should + // disambiguate between text/template and html/template by printing the full + // path. + const ( + asrc = `package a; import "text/template"; func F(template.Template) {}; func G(int) {}` + bsrc = ` +package b + +import ( + "a" + "html/template" +) + +func _() { + // Packages should be fully qualified when there is ambiguity within the + // error string itself. + a.F(template /* ERROR cannot use.*html/template.* as .*text/template */ .Template{}) +} +` + csrc = ` +package c + +import ( + "a" + "fmt" + "html/template" +) + +// Issue #46905: make sure template is not the first package qualified. +var _ fmt.Stringer = 1 // ERROR cannot use 1.*as fmt\.Stringer + +// Packages should be fully qualified when there is ambiguity in reachable +// packages. In this case both a (and for that matter html/template) import +// text/template. +func _() { a.G(template /* ERROR cannot use .*html/template.*Template */ .Template{}) } +` + + tsrc = ` +package template + +import "text/template" + +type T int + +// Verify that the current package name also causes disambiguation. +var _ T = template /* ERROR cannot use.*text/template.* as T value */.Template{} +` + ) + + a, err := pkgFor("a", asrc, nil) + if err != nil { + t.Fatalf("package a failed to typecheck: %v", err) + } + imp := importHelper{pkg: a, fallback: importer.Default()} + + checkFiles(t, nil, "", []string{"b.go"}, [][]byte{[]byte(bsrc)}, false, imp) + checkFiles(t, nil, "", []string{"c.go"}, [][]byte{[]byte(csrc)}, false, imp) + checkFiles(t, nil, "", []string{"t.go"}, [][]byte{[]byte(tsrc)}, false, imp) +} diff --git a/libgo/go/go/types/lookup.go b/libgo/go/go/types/lookup.go index 3c9ff18..9c7bfd4 100644 --- a/libgo/go/go/types/lookup.go +++ b/libgo/go/go/types/lookup.go @@ -6,6 +6,8 @@ package types +import "go/token" + // LookupFieldOrMethod looks up a field or method with given package and name // in T and returns the corresponding *Var or *Func, an index sequence, and a // bool indicating if there were any pointer indirections on the path to the @@ -53,7 +55,7 @@ func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package // Thus, if we have a named pointer type, proceed with the underlying // pointer type but discard the result if it is a method since we would // not have found it for T (see also issue 8590). - if t, _ := T.(*Named); t != nil { + if t := asNamed(T); t != nil { if p, _ := t.underlying.(*Pointer); p != nil { obj, index, indirect = check.rawLookupFieldOrMethod(p, false, pkg, name) if _, ok := obj.(*Func); ok { @@ -83,7 +85,8 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack typ, isPtr := deref(T) // *typ where typ is an interface has no methods. - if isPtr && IsInterface(typ) { + // Be cautious: typ may be nil (issue 39634, crash #3). + if typ == nil || isPtr && IsInterface(typ) { return } @@ -104,12 +107,13 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack var next []embeddedType // embedded types found at current depth // look for (pkg, name) in all types at current depth + var tpar *_TypeParam // set if obj receiver is a type parameter for _, e := range current { typ := e.typ // If we have a named type, we may have associated methods. // Look for those first. - if named, _ := typ.(*Named); named != nil { + if named := asNamed(typ); named != nil { if seen[named] { // We have seen this type before, at a more shallow depth // (note that multiples of this type at the current depth @@ -136,10 +140,17 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack continue // we can't have a matching field or interface method } - // continue with underlying type - typ = named.underlying + // continue with underlying type, but only if it's not a type parameter + // TODO(gri) is this what we want to do for type parameters? (spec question) + // TODO(#45639) the error message produced as a result of skipping an + // underlying type parameter should be improved. + typ = named.under() + if asTypeParam(typ) != nil { + continue + } } + tpar = nil switch t := typ.(type) { case *Struct: // look for a matching field and collect embedded types @@ -175,7 +186,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack case *Interface: // look for a matching method // TODO(gri) t.allMethods is sorted - use binary search - check.completeInterface(t) + check.completeInterface(token.NoPos, t) if i, m := lookupMethod(t.allMethods, pkg, name); m != nil { assert(m.typ != nil) index = concat(e.index, i) @@ -185,6 +196,20 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack obj = m indirect = e.indirect } + + case *_TypeParam: + // only consider explicit methods in the type parameter bound, not + // methods that may be common to all types in the type list. + if i, m := lookupMethod(t.Bound().allMethods, pkg, name); m != nil { + assert(m.typ != nil) + index = concat(e.index, i) + if obj != nil || e.multiples { + return nil, index, false // collision + } + tpar = t + obj = m + indirect = e.indirect + } } } @@ -194,8 +219,12 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack // contains m and the argument list can be assigned to the parameter // list of m. If x is addressable and &x's method set contains m, x.m() // is shorthand for (&x).m()". - if f, _ := obj.(*Func); f != nil && ptrRecv(f) && !indirect && !addressable { - return nil, nil, true // pointer/addressable receiver required + if f, _ := obj.(*Func); f != nil { + // determine if method has a pointer receiver + hasPtrRecv := tpar == nil && ptrRecv(f) + if hasPtrRecv && !indirect && !addressable { + return nil, nil, true // pointer/addressable receiver required + } } return } @@ -267,7 +296,8 @@ func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType b return m, typ != nil } -// missingMethod is like MissingMethod but accepts a receiver. +// missingMethod is like MissingMethod but accepts a *Checker as +// receiver and an addressable flag. // The receiver may be nil if missingMethod is invoked through // an exported API call (such as MissingMethod), i.e., when all // methods have been type-checked. @@ -276,32 +306,53 @@ func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType b // To improve error messages, also report the wrong signature // when the method exists on *V instead of V. func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, wrongType *Func) { - check.completeInterface(T) + check.completeInterface(token.NoPos, T) // fast path for common case if T.Empty() { return } - if ityp, _ := V.Underlying().(*Interface); ityp != nil { - check.completeInterface(ityp) + if ityp := asInterface(V); ityp != nil { + check.completeInterface(token.NoPos, ityp) // TODO(gri) allMethods is sorted - can do this more efficiently for _, m := range T.allMethods { - _, obj := lookupMethod(ityp.allMethods, m.pkg, m.name) - switch { - case obj == nil: - if static { - return m, nil + _, f := lookupMethod(ityp.allMethods, m.pkg, m.name) + + if f == nil { + // if m is the magic method == we're ok (interfaces are comparable) + if m.name == "==" || !static { + continue } - case !check.identical(obj.Type(), m.typ): - return m, obj + return m, f + } + + ftyp := f.typ.(*Signature) + mtyp := m.typ.(*Signature) + if len(ftyp.tparams) != len(mtyp.tparams) { + return m, f + } + + // If the methods have type parameters we don't care whether they + // are the same or not, as long as they match up. Use unification + // to see if they can be made to match. + // TODO(gri) is this always correct? what about type bounds? + // (Alternative is to rename/subst type parameters and compare.) + u := newUnifier(check, true) + u.x.init(ftyp.tparams) + if !u.unify(ftyp, mtyp) { + return m, f } } + return } // A concrete type implements T if it implements all methods of T. + Vd, _ := deref(V) + Vn := asNamed(Vd) for _, m := range T.allMethods { + // TODO(gri) should this be calling lookupFieldOrMethod instead (and why not)? obj, _, _ := check.rawLookupFieldOrMethod(V, false, m.pkg, m.name) // Check if *V implements this method of T. @@ -316,6 +367,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // we must have a method (not a field of matching function type) f, _ := obj.(*Func) if f == nil { + // if m is the magic method == and V is comparable, we're ok + if m.name == "==" && Comparable(V) { + continue + } return m, nil } @@ -324,7 +379,41 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, check.objDecl(f, nil) } - if !check.identical(f.typ, m.typ) { + // both methods must have the same number of type parameters + ftyp := f.typ.(*Signature) + mtyp := m.typ.(*Signature) + if len(ftyp.tparams) != len(mtyp.tparams) { + return m, f + } + + // If V is a (instantiated) generic type, its methods are still + // parameterized using the original (declaration) receiver type + // parameters (subst simply copies the existing method list, it + // does not instantiate the methods). + // In order to compare the signatures, substitute the receiver + // type parameters of ftyp with V's instantiation type arguments. + // This lazily instantiates the signature of method f. + if Vn != nil && len(Vn.tparams) > 0 { + // Be careful: The number of type arguments may not match + // the number of receiver parameters. If so, an error was + // reported earlier but the length discrepancy is still + // here. Exit early in this case to prevent an assertion + // failure in makeSubstMap. + // TODO(gri) Can we avoid this check by fixing the lengths? + if len(ftyp.rparams) != len(Vn.targs) { + return + } + ftyp = check.subst(token.NoPos, ftyp, makeSubstMap(ftyp.rparams, Vn.targs)).(*Signature) + } + + // If the methods have type parameters we don't care whether they + // are the same or not, as long as they match up. Use unification + // to see if they can be made to match. + // TODO(gri) is this always correct? what about type bounds? + // (Alternative is to rename/subst type parameters and compare.) + u := newUnifier(check, true) + u.x.init(ftyp.tparams) + if !u.unify(ftyp, mtyp) { return m, f } } @@ -337,11 +426,13 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method, // method required by V and whether it is missing or just has the wrong type. // The receiver may be nil if assertableTo is invoked through an exported API call // (such as AssertableTo), i.e., when all methods have been type-checked. +// If the global constant forceStrict is set, assertions that are known to fail +// are not permitted. func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Func) { // no static check is required if T is an interface // spec: "If T is an interface type, x.(T) asserts that the // dynamic type of x implements the interface T." - if _, ok := T.Underlying().(*Interface); ok && !strict { + if asInterface(T) != nil && !forceStrict { return } return check.missingMethod(T, V, false) @@ -359,8 +450,8 @@ func deref(typ Type) (Type, bool) { // derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a // (named or unnamed) struct and returns its base. Otherwise it returns typ. func derefStructPtr(typ Type) Type { - if p, _ := typ.Underlying().(*Pointer); p != nil { - if _, ok := p.base.Underlying().(*Struct); ok { + if p := asPointer(typ); p != nil { + if asStruct(p.base) != nil { return p.base } } diff --git a/libgo/go/go/types/methodset.go b/libgo/go/go/types/methodset.go index c34d732..ae8011a 100644 --- a/libgo/go/go/types/methodset.go +++ b/libgo/go/go/types/methodset.go @@ -63,7 +63,7 @@ func (s *MethodSet) Lookup(pkg *Package, name string) *Selection { var emptyMethodSet MethodSet // Note: NewMethodSet is intended for external use only as it -// requires interfaces to be complete. If may be used +// requires interfaces to be complete. It may be used // internally if LookupFieldOrMethod completed the same // interfaces beforehand. @@ -73,6 +73,9 @@ func NewMethodSet(T Type) *MethodSet { // WARNING: The code in this function is extremely subtle - do not modify casually! // This function and lookupFieldOrMethod should be kept in sync. + // TODO(rfindley) confirm that this code is in sync with lookupFieldOrMethod + // with respect to type params. + // method set up to the current depth, allocated lazily var base methodSet @@ -108,7 +111,7 @@ func NewMethodSet(T Type) *MethodSet { // If we have a named type, we may have associated methods. // Look for those first. - if named, _ := typ.(*Named); named != nil { + if named := asNamed(typ); named != nil { if seen[named] { // We have seen this type before, at a more shallow depth // (note that multiples of this type at the current depth @@ -124,8 +127,12 @@ func NewMethodSet(T Type) *MethodSet { mset = mset.add(named.methods, e.index, e.indirect, e.multiples) - // continue with underlying type + // continue with underlying type, but only if it's not a type parameter + // TODO(rFindley): should this use named.under()? Can there be a difference? typ = named.underlying + if _, ok := typ.(*_TypeParam); ok { + continue + } } switch t := typ.(type) { @@ -151,6 +158,9 @@ func NewMethodSet(T Type) *MethodSet { case *Interface: mset = mset.add(t.allMethods, e.index, true, e.multiples) + + case *_TypeParam: + mset = mset.add(t.Bound().allMethods, e.index, true, e.multiples) } } diff --git a/libgo/go/go/types/methodset_test.go b/libgo/go/go/types/methodset_test.go new file mode 100644 index 0000000..4a373fa --- /dev/null +++ b/libgo/go/go/types/methodset_test.go @@ -0,0 +1,109 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types_test + +import ( + "testing" + + "go/internal/typeparams" + . "go/types" +) + +func TestNewMethodSet(t *testing.T) { + type method struct { + name string + index []int + indirect bool + } + + // Tests are expressed src -> methods, for simplifying the composite literal. + // Should be kept in sync with TestLookupFieldOrMethod. + tests := map[string][]method{ + // Named types + "var a T; type T struct{}; func (T) f() {}": {{"f", []int{0}, false}}, + "var a *T; type T struct{}; func (T) f() {}": {{"f", []int{0}, true}}, + "var a T; type T struct{}; func (*T) f() {}": {}, + "var a *T; type T struct{}; func (*T) f() {}": {{"f", []int{0}, true}}, + + // Interfaces + "var a T; type T interface{ f() }": {{"f", []int{0}, true}}, + "var a T1; type ( T1 T2; T2 interface{ f() } )": {{"f", []int{0}, true}}, + "var a T1; type ( T1 interface{ T2 }; T2 interface{ f() } )": {{"f", []int{0}, true}}, + + // Embedding + "var a struct{ E }; type E interface{ f() }": {{"f", []int{0, 0}, true}}, + "var a *struct{ E }; type E interface{ f() }": {{"f", []int{0, 0}, true}}, + "var a struct{ E }; type E struct{}; func (E) f() {}": {{"f", []int{0, 0}, false}}, + "var a struct{ *E }; type E struct{}; func (E) f() {}": {{"f", []int{0, 0}, true}}, + "var a struct{ E }; type E struct{}; func (*E) f() {}": {}, + "var a struct{ *E }; type E struct{}; func (*E) f() {}": {{"f", []int{0, 0}, true}}, + + // collisions + "var a struct{ E1; *E2 }; type ( E1 interface{ f() }; E2 struct{ f int })": {}, + "var a struct{ E1; *E2 }; type ( E1 struct{ f int }; E2 struct{} ); func (E2) f() {}": {}, + } + + genericTests := map[string][]method{ + // By convention, look up a in the scope of "g" + "type C interface{ f() }; func g[T C](a T){}": {{"f", []int{0}, true}}, + "type C interface{ f() }; func g[T C]() { var a T; _ = a }": {{"f", []int{0}, true}}, + "type C interface{ f() }; func g[T C]() { var a struct{T}; _ = a }": {{"f", []int{0, 0}, true}}, + + // Issue #45639. + "type C interface{ f() }; func g[T C]() { type Y T; var a Y; _ = a }": {}, + } + + check := func(src string, methods []method, generic bool) { + pkgName := "p" + if generic { + // The generic_ prefix causes pkgFor to allow generic code. + pkgName = "generic_p" + } + pkg, err := pkgFor("test", "package "+pkgName+";"+src, nil) + if err != nil { + t.Errorf("%s: incorrect test case: %s", src, err) + return + } + + scope := pkg.Scope() + if generic { + fn := pkg.Scope().Lookup("g").(*Func) + scope = fn.Scope() + } + obj := scope.Lookup("a") + if obj == nil { + t.Errorf("%s: incorrect test case - no object a", src) + return + } + + ms := NewMethodSet(obj.Type()) + if got, want := ms.Len(), len(methods); got != want { + t.Errorf("%s: got %d methods, want %d", src, got, want) + return + } + for i, m := range methods { + sel := ms.At(i) + if got, want := sel.Obj().Name(), m.name; got != want { + t.Errorf("%s [method %d]: got name = %q at, want %q", src, i, got, want) + } + if got, want := sel.Index(), m.index; !sameSlice(got, want) { + t.Errorf("%s [method %d]: got index = %v, want %v", src, i, got, want) + } + if got, want := sel.Indirect(), m.indirect; got != want { + t.Errorf("%s [method %d]: got indirect = %v, want %v", src, i, got, want) + } + } + } + + for src, methods := range tests { + check(src, methods, false) + } + + if typeparams.Enabled { + for src, methods := range genericTests { + check(src, methods, true) + } + } +} diff --git a/libgo/go/go/types/object.go b/libgo/go/go/types/object.go index 374b24d..50346ec 100644 --- a/libgo/go/go/types/object.go +++ b/libgo/go/go/types/object.go @@ -36,6 +36,9 @@ type Object interface { // color returns the object's color. color() color + // setType sets the type of the object. + setType(Type) + // setOrder sets the order number of the object. It must be > 0. setOrder(uint32) @@ -149,6 +152,7 @@ func (obj *object) color() color { return obj.color_ } func (obj *object) scopePos() token.Pos { return obj.scopePos_ } func (obj *object) setParent(parent *Scope) { obj.parent = parent } +func (obj *object) setType(typ Type) { obj.typ = typ } func (obj *object) setOrder(order uint32) { assert(order > 0); obj.order_ = order } func (obj *object) setColor(color color) { assert(color != white); obj.color_ = color } func (obj *object) setScopePos(pos token.Pos) { obj.scopePos_ = pos } @@ -299,7 +303,7 @@ type Func struct { // NewFunc returns a new function with the given signature, representing // the function's type. func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func { - // don't store a nil signature + // don't store a (typed) nil signature var typ Type if sig != nil { typ = sig @@ -420,7 +424,7 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) { if tname.IsAlias() { buf.WriteString(" =") } else { - typ = typ.Underlying() + typ = under(typ) } } diff --git a/libgo/go/go/types/operand.go b/libgo/go/go/types/operand.go index 3e1ac31..6463728 100644 --- a/libgo/go/go/types/operand.go +++ b/libgo/go/go/types/operand.go @@ -158,7 +158,16 @@ func operandString(x *operand, qf Qualifier) string { // <typ> if hasType { if x.typ != Typ[Invalid] { - buf.WriteString(" of type ") + var intro string + switch { + case isGeneric(x.typ): + intro = " of generic type " + case asTypeParam(x.typ) != nil: + intro = " of type parameter type " + default: + intro = " of type " + } + buf.WriteString(intro) WriteType(&buf, x.typ, qf) } else { buf.WriteString(" with invalid type") @@ -213,9 +222,10 @@ func (x *operand) isNil() bool { // assignableTo reports whether x is assignable to a variable of type T. If the // result is false and a non-nil reason is provided, it may be set to a more -// detailed explanation of the failure (result != ""). The check parameter may -// be nil if assignableTo is invoked through an exported API call, i.e., when -// all methods have been type-checked. +// detailed explanation of the failure (result != ""). The returned error code +// is only valid if the (first) result is false. The check parameter may be nil +// if assignableTo is invoked through an exported API call, i.e., when all +// methods have been type-checked. func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, errorCode) { if x.mode == invalid || T == Typ[Invalid] { return true, 0 // avoid spurious errors @@ -228,20 +238,25 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er return true, 0 } - Vu := V.Underlying() - Tu := T.Underlying() + Vu := optype(V) + Tu := optype(T) // x is an untyped value representable by a value of type T. if isUntyped(Vu) { - if t, ok := Tu.(*Basic); ok && x.mode == constant_ { - return representableConst(x.val, check, t, nil), _IncompatibleAssign + if t, ok := Tu.(*_Sum); ok { + return t.is(func(t Type) bool { + // TODO(gri) this could probably be more efficient + ok, _ := x.assignableTo(check, t, reason) + return ok + }), _IncompatibleAssign } - return check.implicitType(x, Tu) != nil, _IncompatibleAssign + newType, _, _ := check.implicitTypeAndValue(x, Tu) + return newType != nil, _IncompatibleAssign } // Vu is typed - // x's type V and T have identical underlying types and at least one of V or - // T is not a named type. + // x's type V and T have identical underlying types + // and at least one of V or T is not a named type if check.identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) { return true, 0 } @@ -271,11 +286,7 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er // and at least one of V or T is not a named type if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv { if Tc, ok := Tu.(*Chan); ok && check.identical(Vc.elem, Tc.elem) { - if !isNamed(V) || !isNamed(T) { - return true, 0 - } else { - return false, _InvalidChanAssign - } + return !isNamed(V) || !isNamed(T), _InvalidChanAssign } } diff --git a/libgo/go/go/types/predicates.go b/libgo/go/go/types/predicates.go index 148edbf..7bb0264 100644 --- a/libgo/go/go/types/predicates.go +++ b/libgo/go/go/types/predicates.go @@ -6,75 +6,84 @@ package types -import "sort" +import ( + "go/token" +) +// isNamed reports whether typ has a name. +// isNamed may be called with types that are not fully set up. func isNamed(typ Type) bool { - if _, ok := typ.(*Basic); ok { - return ok + switch typ.(type) { + case *Basic, *Named, *_TypeParam, *instance: + return true } - _, ok := typ.(*Named) - return ok -} - -func isBoolean(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsBoolean != 0 -} - -func isInteger(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsInteger != 0 -} - -func isUnsigned(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsUnsigned != 0 -} - -func isFloat(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsFloat != 0 -} - -func isComplex(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsComplex != 0 + return false } -func isNumeric(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsNumeric != 0 +// isGeneric reports whether a type is a generic, uninstantiated type (generic +// signatures are not included). +func isGeneric(typ Type) bool { + // A parameterized type is only instantiated if it doesn't have an instantiation already. + named, _ := typ.(*Named) + return named != nil && named.obj != nil && named.tparams != nil && named.targs == nil } -func isString(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsString != 0 +func is(typ Type, what BasicInfo) bool { + switch t := optype(typ).(type) { + case *Basic: + return t.info&what != 0 + case *_Sum: + return t.is(func(typ Type) bool { return is(typ, what) }) + } + return false } +func isBoolean(typ Type) bool { return is(typ, IsBoolean) } +func isInteger(typ Type) bool { return is(typ, IsInteger) } +func isUnsigned(typ Type) bool { return is(typ, IsUnsigned) } +func isFloat(typ Type) bool { return is(typ, IsFloat) } +func isComplex(typ Type) bool { return is(typ, IsComplex) } +func isNumeric(typ Type) bool { return is(typ, IsNumeric) } +func isString(typ Type) bool { return is(typ, IsString) } + +// Note that if typ is a type parameter, isInteger(typ) || isFloat(typ) does not +// produce the expected result because a type list that contains both an integer +// and a floating-point type is neither (all) integers, nor (all) floats. +// Use isIntegerOrFloat instead. +func isIntegerOrFloat(typ Type) bool { return is(typ, IsInteger|IsFloat) } + +// isNumericOrString is the equivalent of isIntegerOrFloat for isNumeric(typ) || isString(typ). +func isNumericOrString(typ Type) bool { return is(typ, IsNumeric|IsString) } + +// isTyped reports whether typ is typed; i.e., not an untyped +// constant or boolean. isTyped may be called with types that +// are not fully set up. func isTyped(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return !ok || t.info&IsUntyped == 0 + // isTyped is called with types that are not fully + // set up. Must not call asBasic()! + // A *Named or *instance type is always typed, so + // we only need to check if we have a true *Basic + // type. + t, _ := typ.(*Basic) + return t == nil || t.info&IsUntyped == 0 } +// isUntyped(typ) is the same as !isTyped(typ). func isUntyped(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsUntyped != 0 + return !isTyped(typ) } -func isOrdered(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsOrdered != 0 -} +func isOrdered(typ Type) bool { return is(typ, IsOrdered) } func isConstType(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsConstType != 0 + // Type parameters are never const types. + t, _ := under(typ).(*Basic) + return t != nil && t.info&IsConstType != 0 } // IsInterface reports whether typ is an interface type. func IsInterface(typ Type) bool { - _, ok := typ.Underlying().(*Interface) - return ok + return asInterface(typ) != nil } // Comparable reports whether values of type T are comparable. @@ -91,7 +100,19 @@ func comparable(T Type, seen map[Type]bool) bool { } seen[T] = true - switch t := T.Underlying().(type) { + // If T is a type parameter not constrained by any type + // list (i.e., it's underlying type is the top type), + // T is comparable if it has the == method. Otherwise, + // the underlying type "wins". For instance + // + // interface{ comparable; type []byte } + // + // is not comparable because []byte is not comparable. + if t := asTypeParam(T); t != nil && optype(t) == theTop { + return t.Bound()._IsComparable() + } + + switch t := optype(T).(type) { case *Basic: // assume invalid types to be comparable // to avoid follow-up errors @@ -107,17 +128,26 @@ func comparable(T Type, seen map[Type]bool) bool { return true case *Array: return comparable(t.elem, seen) + case *_Sum: + pred := func(t Type) bool { + return comparable(t, seen) + } + return t.is(pred) + case *_TypeParam: + return t.Bound()._IsComparable() } return false } // hasNil reports whether a type includes the nil value. func hasNil(typ Type) bool { - switch t := typ.Underlying().(type) { + switch t := optype(typ).(type) { case *Basic: return t.kind == UnsafePointer case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan: return true + case *_Sum: + return t.is(hasNil) } return false } @@ -144,7 +174,12 @@ func (p *ifacePair) identical(q *ifacePair) bool { return p.x == q.x && p.y == q.y || p.x == q.y && p.y == q.x } +// For changes to this code the corresponding changes should be made to unifier.nify. func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { + // types must be expanded for comparison + x = expandf(x) + y = expandf(y) + if x == y { return true } @@ -221,12 +256,38 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { // and result values, corresponding parameter and result types are identical, // and either both functions are variadic or neither is. Parameter and result // names are not required to match. + // Generic functions must also have matching type parameter lists, but for the + // parameter names. if y, ok := y.(*Signature); ok { return x.variadic == y.variadic && + check.identicalTParams(x.tparams, y.tparams, cmpTags, p) && check.identical0(x.params, y.params, cmpTags, p) && check.identical0(x.results, y.results, cmpTags, p) } + case *_Sum: + // Two sum types are identical if they contain the same types. + // (Sum types always consist of at least two types. Also, the + // the set (list) of types in a sum type consists of unique + // types - each type appears exactly once. Thus, two sum types + // must contain the same number of types to have chance of + // being equal. + if y, ok := y.(*_Sum); ok && len(x.types) == len(y.types) { + // Every type in x.types must be in y.types. + // Quadratic algorithm, but probably good enough for now. + // TODO(gri) we need a fast quick type ID/hash for all types. + L: + for _, x := range x.types { + for _, y := range y.types { + if Identical(x, y) { + continue L // x is in y.types + } + } + return false // x is not in y.types + } + return true + } + case *Interface: // Two interface types are identical if they have the same set of methods with // the same names and identical function types. Lower-case method names from @@ -237,8 +298,8 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { // that case, interfaces are expected to be complete and lazy completion // here is not needed. if check != nil { - check.completeInterface(x) - check.completeInterface(y) + check.completeInterface(token.NoPos, x) + check.completeInterface(token.NoPos, y) } a := x.allMethods b := y.allMethods @@ -273,8 +334,8 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { p = p.prev } if debug { - assert(sort.IsSorted(byUniqueMethodName(a))) - assert(sort.IsSorted(byUniqueMethodName(b))) + assertSortedMethods(a) + assertSortedMethods(b) } for i, f := range a { g := b[i] @@ -303,10 +364,25 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { // Two named types are identical if their type names originate // in the same type declaration. if y, ok := y.(*Named); ok { + // TODO(gri) Why is x == y not sufficient? And if it is, + // we can just return false here because x == y + // is caught in the very beginning of this function. return x.obj == y.obj } + case *_TypeParam: + // nothing to do (x and y being equal is caught in the very beginning of this function) + + // case *instance: + // unreachable since types are expanded + + case *bottom, *top: + // Either both types are theBottom, or both are theTop in which + // case the initial x == y check will have caught them. Otherwise + // they are not identical. + case nil: + // avoid a crash in case of nil type default: unreachable() @@ -315,6 +391,19 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool { return false } +func (check *Checker) identicalTParams(x, y []*TypeName, cmpTags bool, p *ifacePair) bool { + if len(x) != len(y) { + return false + } + for i, x := range x { + y := y[i] + if !check.identical0(x.typ.(*_TypeParam).bound, y.typ.(*_TypeParam).bound, cmpTags, p) { + return false + } + } + return true +} + // Default returns the default "typed" type for an "untyped" type; // it returns the incoming type for all other types. The default type // for untyped nil is untyped nil. diff --git a/libgo/go/go/types/resolver.go b/libgo/go/go/types/resolver.go index b637f8b..114647a 100644 --- a/libgo/go/go/types/resolver.go +++ b/libgo/go/go/types/resolver.go @@ -8,6 +8,7 @@ import ( "fmt" "go/ast" "go/constant" + "go/internal/typeparams" "go/token" "sort" "strconv" @@ -19,11 +20,11 @@ import ( type declInfo struct { file *Scope // scope of file containing this declaration lhs []*Var // lhs of n:1 variable declarations, or nil - typ ast.Expr // type, or nil - init ast.Expr // init/orig expression, or nil + vtyp ast.Expr // type, or nil (for const and var declarations only) + init ast.Expr // init/orig expression, or nil (for const and var declarations only) inherited bool // if set, the init expression is inherited from a previous constant declaration + tdecl *ast.TypeSpec // type declaration, or nil fdecl *ast.FuncDecl // func declaration, or nil - alias bool // type alias declaration // The deps field tracks initialization expression dependencies. deps map[Object]bool // lazily initialized @@ -130,7 +131,7 @@ func (check *Checker) filename(fileNo int) string { return fmt.Sprintf("file[%d]", fileNo) } -func (check *Checker) importPackage(pos token.Pos, path, dir string) *Package { +func (check *Checker) importPackage(at positioner, path, dir string) *Package { // If we already have a package for the given (path, dir) // pair, use it instead of doing a full import. // Checker.impMap only caches packages that are marked Complete @@ -170,7 +171,7 @@ func (check *Checker) importPackage(pos token.Pos, path, dir string) *Package { imp = nil // create fake package below } if err != nil { - check.errorf(atPos(pos), _BrokenImport, "could not import %s (%s)", path, err) + check.errorf(at, _BrokenImport, "could not import %s (%s)", path, err) if imp == nil { // create a new fake package // come up with a sensible package name (heuristic) @@ -191,7 +192,11 @@ func (check *Checker) importPackage(pos token.Pos, path, dir string) *Package { // package should be complete or marked fake, but be cautious if imp.complete || imp.fake { check.impMap[key] = imp - check.pkgCnt[imp.name]++ + // Once we've formatted an error message once, keep the pkgPathMap + // up-to-date on subsequent imports. + if check.pkgPathMap != nil { + check.markImports(imp) + } return imp } @@ -216,7 +221,13 @@ func (check *Checker) collectObjects() { pkgImports[imp] = true } - var methods []*Func // list of methods with non-blank _ names + type methodInfo struct { + obj *Func // method + ptr bool // true if pointer receiver + recv *ast.Ident // receiver type name + } + var methods []methodInfo // collected methods with valid receivers and non-blank _ names + var fileScopes []*Scope for fileNo, file := range check.files { // The package identifier denotes the current package, // but there is no corresponding package object. @@ -230,6 +241,7 @@ func (check *Checker) collectObjects() { pos, end = token.Pos(f.Base()), token.Pos(f.Base()+f.Size()) } fileScope := NewScope(check.pkg.scope, pos, end, check.filename(fileNo)) + fileScopes = append(fileScopes, fileScope) check.recordScope(file, fileScope) // determine file directory, necessary to resolve imports @@ -247,19 +259,11 @@ func (check *Checker) collectObjects() { return } - imp := check.importPackage(d.spec.Path.Pos(), path, fileDir) + imp := check.importPackage(d.spec.Path, path, fileDir) if imp == nil { return } - // add package to list of explicit imports - // (this functionality is provided as a convenience - // for clients; it is not needed for type-checking) - if !pkgImports[imp] { - pkgImports[imp] = true - pkg.imports = append(pkg.imports, imp) - } - // local name overrides imported package name name := imp.name if d.spec.Name != nil { @@ -269,27 +273,41 @@ func (check *Checker) collectObjects() { check.errorf(d.spec.Name, _ImportCRenamed, `cannot rename import "C"`) return } - if name == "init" { - check.errorf(d.spec.Name, _InvalidInitDecl, "cannot declare init - must be func") - return - } } - obj := NewPkgName(d.spec.Pos(), pkg, name, imp) + if name == "init" { + check.errorf(d.spec.Name, _InvalidInitDecl, "cannot import package as init - init must be a func") + return + } + + // add package to list of explicit imports + // (this functionality is provided as a convenience + // for clients; it is not needed for type-checking) + if !pkgImports[imp] { + pkgImports[imp] = true + pkg.imports = append(pkg.imports, imp) + } + + pkgName := NewPkgName(d.spec.Pos(), pkg, name, imp) if d.spec.Name != nil { // in a dot-import, the dot represents the package - check.recordDef(d.spec.Name, obj) + check.recordDef(d.spec.Name, pkgName) } else { - check.recordImplicit(d.spec, obj) + check.recordImplicit(d.spec, pkgName) } if path == "C" { // match cmd/compile (not prescribed by spec) - obj.used = true + pkgName.used = true } // add import to file scope + check.imports = append(check.imports, pkgName) if name == "." { + // dot-import + if check.dotImportMap == nil { + check.dotImportMap = make(map[dotImportKey]*PkgName) + } // merge imported scope with file scope for _, obj := range imp.scope.elems { // A package scope may contain non-exported objects, @@ -303,16 +321,15 @@ func (check *Checker) collectObjects() { if alt := fileScope.Insert(obj); alt != nil { check.errorf(d.spec.Name, _DuplicateDecl, "%s redeclared in this block", obj.Name()) check.reportAltDecl(alt) + } else { + check.dotImportMap[dotImportKey{fileScope, obj}] = pkgName } } } - // add position to set of dot-import positions for this file - // (this is only needed for "imported but not used" errors) - check.addUnusedDotImport(fileScope, imp, d.spec) } else { // declare imported package object in file scope // (no need to provide s.Name since we called check.recordDef earlier) - check.declare(fileScope, nil, obj, token.NoPos) + check.declare(fileScope, nil, pkgName, token.NoPos) } case constDecl: // declare all constants @@ -324,7 +341,7 @@ func (check *Checker) collectObjects() { init = d.init[i] } - d := &declInfo{file: fileScope, typ: d.typ, init: init, inherited: d.inherited} + d := &declInfo{file: fileScope, vtyp: d.typ, init: init, inherited: d.inherited} check.declarePkgObj(name, obj, d) } @@ -339,7 +356,7 @@ func (check *Checker) collectObjects() { // The lhs elements are only set up after the for loop below, // but that's ok because declareVar only collects the declInfo // for a later phase. - d1 = &declInfo{file: fileScope, lhs: lhs, typ: d.spec.Type, init: d.spec.Values[0]} + d1 = &declInfo{file: fileScope, lhs: lhs, vtyp: d.spec.Type, init: d.spec.Values[0]} } // declare all variables @@ -354,26 +371,44 @@ func (check *Checker) collectObjects() { if i < len(d.spec.Values) { init = d.spec.Values[i] } - di = &declInfo{file: fileScope, typ: d.spec.Type, init: init} + di = &declInfo{file: fileScope, vtyp: d.spec.Type, init: init} } check.declarePkgObj(name, obj, di) } case typeDecl: obj := NewTypeName(d.spec.Name.Pos(), pkg, d.spec.Name.Name, nil) - check.declarePkgObj(d.spec.Name, obj, &declInfo{file: fileScope, typ: d.spec.Type, alias: d.spec.Assign.IsValid()}) + check.declarePkgObj(d.spec.Name, obj, &declInfo{file: fileScope, tdecl: d.spec}) case funcDecl: info := &declInfo{file: fileScope, fdecl: d.decl} name := d.decl.Name.Name obj := NewFunc(d.decl.Name.Pos(), pkg, name, nil) - if d.decl.Recv == nil { + if d.decl.Recv.NumFields() == 0 { // regular function + if d.decl.Recv != nil { + check.error(d.decl.Recv, _BadRecv, "method is missing receiver") + // treat as function + } + if name == "init" || (name == "main" && check.pkg.name == "main") { + code := _InvalidInitDecl + if name == "main" { + code = _InvalidMainDecl + } + if tparams := typeparams.Get(d.decl.Type); tparams != nil { + check.softErrorf(tparams, code, "func %s must have no type parameters", name) + } + if t := d.decl.Type; t.Params.NumFields() != 0 || t.Results != nil { + // TODO(rFindley) Should this be a hard error? + check.softErrorf(d.decl, code, "func %s must have no arguments and no return values", name) + } + } if name == "init" { // don't declare init functions in the package scope - they are invisible obj.parent = pkg.scope check.recordDef(d.decl.Name, obj) // init functions must have a body if d.decl.Body == nil { + // TODO(gri) make this error message consistent with the others above check.softErrorf(obj, _MissingInitBody, "missing function body") } } else { @@ -381,11 +416,18 @@ func (check *Checker) collectObjects() { } } else { // method - // (Methods with blank _ names are never found; no need to collect - // them for later type association. They will still be type-checked - // with all the other functions.) - if name != "_" { - methods = append(methods, obj) + + // TODO(rFindley) earlier versions of this code checked that methods + // have no type parameters, but this is checked later + // when type checking the function type. Confirm that + // we don't need to check tparams here. + + ptr, recv, _ := check.unpackRecv(d.decl.Recv.List[0].Type, false) + // (Methods with invalid receiver cannot be associated to a type, and + // methods with blank _ names are never found; no need to collect any + // of them. They will still be type-checked with all the other functions.) + if recv != nil && name != "_" { + methods = append(methods, methodInfo{obj, ptr, recv}) } check.recordDef(d.decl.Name, obj) } @@ -400,7 +442,7 @@ func (check *Checker) collectObjects() { } // verify that objects in package and file scopes have different names - for _, scope := range check.pkg.scope.children /* file scopes */ { + for _, scope := range fileScopes { for _, obj := range scope.elems { if alt := pkg.scope.Lookup(obj.Name()); alt != nil { if pkg, ok := obj.(*PkgName); ok { @@ -423,31 +465,84 @@ func (check *Checker) collectObjects() { return // nothing to do } check.methods = make(map[*TypeName][]*Func) - for _, f := range methods { - fdecl := check.objMap[f].fdecl - if list := fdecl.Recv.List; len(list) > 0 { - // f is a method. - // Determine the receiver base type and associate f with it. - ptr, base := check.resolveBaseTypeName(list[0].Type) - if base != nil { - f.hasPtrRecv = ptr - check.methods[base] = append(check.methods[base], f) + for i := range methods { + m := &methods[i] + // Determine the receiver base type and associate m with it. + ptr, base := check.resolveBaseTypeName(m.ptr, m.recv) + if base != nil { + m.obj.hasPtrRecv = ptr + check.methods[base] = append(check.methods[base], m.obj) + } + } +} + +// unpackRecv unpacks a receiver type and returns its components: ptr indicates whether +// rtyp is a pointer receiver, rname is the receiver type name, and tparams are its +// type parameters, if any. The type parameters are only unpacked if unpackParams is +// set. If rname is nil, the receiver is unusable (i.e., the source has a bug which we +// cannot easily work around). +func (check *Checker) unpackRecv(rtyp ast.Expr, unpackParams bool) (ptr bool, rname *ast.Ident, tparams []*ast.Ident) { +L: // unpack receiver type + // This accepts invalid receivers such as ***T and does not + // work for other invalid receivers, but we don't care. The + // validity of receiver expressions is checked elsewhere. + for { + switch t := rtyp.(type) { + case *ast.ParenExpr: + rtyp = t.X + case *ast.StarExpr: + ptr = true + rtyp = t.X + default: + break L + } + } + + // unpack type parameters, if any + if ptyp, _ := rtyp.(*ast.IndexExpr); ptyp != nil { + rtyp = ptyp.X + if unpackParams { + for _, arg := range typeparams.UnpackExpr(ptyp.Index) { + var par *ast.Ident + switch arg := arg.(type) { + case *ast.Ident: + par = arg + case *ast.BadExpr: + // ignore - error already reported by parser + case nil: + check.invalidAST(ptyp, "parameterized receiver contains nil parameters") + default: + check.errorf(arg, _Todo, "receiver type parameter %s must be an identifier", arg) + } + if par == nil { + par = &ast.Ident{NamePos: arg.Pos(), Name: "_"} + } + tparams = append(tparams, par) } } } + + // unpack receiver name + if name, _ := rtyp.(*ast.Ident); name != nil { + rname = name + } + + return } // resolveBaseTypeName returns the non-alias base type name for typ, and whether // there was a pointer indirection to get to it. The base type name must be declared // in package scope, and there can be at most one pointer indirection. If no such type // name exists, the returned base is nil. -func (check *Checker) resolveBaseTypeName(typ ast.Expr) (ptr bool, base *TypeName) { +func (check *Checker) resolveBaseTypeName(seenPtr bool, name *ast.Ident) (ptr bool, base *TypeName) { // Algorithm: Starting from a type expression, which may be a name, // we follow that type through alias declarations until we reach a // non-alias type name. If we encounter anything but pointer types or // parentheses we're done. If we encounter more than one pointer type // we're done. + ptr = seenPtr var seen map[*TypeName]bool + var typ ast.Expr = name for { typ = unparen(typ) @@ -487,13 +582,13 @@ func (check *Checker) resolveBaseTypeName(typ ast.Expr) (ptr bool, base *TypeNam // we're done if tdecl defined tname as a new type // (rather than an alias) - tdecl := check.objMap[tname] // must exist for objects in package scope - if !tdecl.alias { + tdecl := check.objMap[tname].tdecl // must exist for objects in package scope + if !tdecl.Assign.IsValid() { return ptr, tname } // otherwise, continue resolving - typ = tdecl.typ + typ = tdecl.Type if seen == nil { seen = make(map[*TypeName]bool) } @@ -515,7 +610,7 @@ func (check *Checker) packageObjects() { // add new methods to already type-checked types (from a prior Checker.Files call) for _, obj := range objList { if obj, _ := obj.(*TypeName); obj != nil && obj.typ != nil { - check.addMethodDecls(obj) + check.collectMethods(obj) } } @@ -529,7 +624,7 @@ func (check *Checker) packageObjects() { // phase 1 for _, obj := range objList { // If we have a type alias, collect it for the 2nd phase. - if tname, _ := obj.(*TypeName); tname != nil && check.objMap[tname].alias { + if tname, _ := obj.(*TypeName); tname != nil && check.objMap[tname].tdecl.Assign.IsValid() { aliasList = append(aliasList, tname) continue } @@ -566,39 +661,30 @@ func (check *Checker) unusedImports() { // any of its exported identifiers. To import a package solely for its side-effects // (initialization), use the blank identifier as explicit package name." - // check use of regular imported packages - for _, scope := range check.pkg.scope.children /* file scopes */ { - for _, obj := range scope.elems { - if obj, ok := obj.(*PkgName); ok { - // Unused "blank imports" are automatically ignored - // since _ identifiers are not entered into scopes. - if !obj.used { - path := obj.imported.path - base := pkgName(path) - if obj.name == base { - check.softErrorf(obj, _UnusedImport, "%q imported but not used", path) - } else { - check.softErrorf(obj, _UnusedImport, "%q imported but not used as %s", path, obj.name) - } - } - } - } - } - - // check use of dot-imported packages - for _, unusedDotImports := range check.unusedDotImports { - for pkg, pos := range unusedDotImports { - check.softErrorf(pos, _UnusedImport, "%q imported but not used", pkg.path) + for _, obj := range check.imports { + if !obj.used && obj.name != "_" { + check.errorUnusedPkg(obj) } } } -// pkgName returns the package name (last element) of an import path. -func pkgName(path string) string { - if i := strings.LastIndex(path, "/"); i >= 0 { - path = path[i+1:] +func (check *Checker) errorUnusedPkg(obj *PkgName) { + // If the package was imported with a name other than the final + // import path element, show it explicitly in the error message. + // Note that this handles both renamed imports and imports of + // packages containing unconventional package declarations. + // Note that this uses / always, even on Windows, because Go import + // paths always use forward slashes. + path := obj.imported.path + elem := path + if i := strings.LastIndex(elem, "/"); i >= 0 { + elem = elem[i+1:] + } + if obj.name == "" || obj.name == "." || obj.name == elem { + check.softErrorf(obj, _UnusedImport, "%q imported but not used", path) + } else { + check.softErrorf(obj, _UnusedImport, "%q imported but not used as %s", path, obj.name) } - return path } // dir makes a good-faith attempt to return the directory diff --git a/libgo/go/go/types/sanitize.go b/libgo/go/go/types/sanitize.go new file mode 100644 index 0000000..727ec17 --- /dev/null +++ b/libgo/go/go/types/sanitize.go @@ -0,0 +1,206 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +// sanitizeInfo walks the types contained in info to ensure that all instances +// are expanded. +// +// This includes some objects that may be shared across concurrent +// type-checking passes (such as those in the universe scope), so we are +// careful here not to write types that are already sanitized. This avoids a +// data race as any shared types should already be sanitized. +func sanitizeInfo(info *Info) { + var s sanitizer = make(map[Type]Type) + + // Note: Some map entries are not references. + // If modified, they must be assigned back. + + for e, tv := range info.Types { + if typ := s.typ(tv.Type); typ != tv.Type { + tv.Type = typ + info.Types[e] = tv + } + } + + inferred := getInferred(info) + for e, inf := range inferred { + changed := false + for i, targ := range inf.Targs { + if typ := s.typ(targ); typ != targ { + inf.Targs[i] = typ + changed = true + } + } + if typ := s.typ(inf.Sig); typ != inf.Sig { + inf.Sig = typ.(*Signature) + changed = true + } + if changed { + inferred[e] = inf + } + } + + for _, obj := range info.Defs { + if obj != nil { + if typ := s.typ(obj.Type()); typ != obj.Type() { + obj.setType(typ) + } + } + } + + for _, obj := range info.Uses { + if obj != nil { + if typ := s.typ(obj.Type()); typ != obj.Type() { + obj.setType(typ) + } + } + } + + // TODO(gri) sanitize as needed + // - info.Implicits + // - info.Selections + // - info.Scopes + // - info.InitOrder +} + +type sanitizer map[Type]Type + +func (s sanitizer) typ(typ Type) Type { + if typ == nil { + return nil + } + + if t, found := s[typ]; found { + return t + } + s[typ] = typ + + switch t := typ.(type) { + case *Basic, *bottom, *top: + // nothing to do + + case *Array: + if elem := s.typ(t.elem); elem != t.elem { + t.elem = elem + } + + case *Slice: + if elem := s.typ(t.elem); elem != t.elem { + t.elem = elem + } + + case *Struct: + s.varList(t.fields) + + case *Pointer: + if base := s.typ(t.base); base != t.base { + t.base = base + } + + case *Tuple: + s.tuple(t) + + case *Signature: + s.var_(t.recv) + s.tuple(t.params) + s.tuple(t.results) + + case *_Sum: + s.typeList(t.types) + + case *Interface: + s.funcList(t.methods) + if types := s.typ(t.types); types != t.types { + t.types = types + } + s.typeList(t.embeddeds) + s.funcList(t.allMethods) + if allTypes := s.typ(t.allTypes); allTypes != t.allTypes { + t.allTypes = allTypes + } + + case *Map: + if key := s.typ(t.key); key != t.key { + t.key = key + } + if elem := s.typ(t.elem); elem != t.elem { + t.elem = elem + } + + case *Chan: + if elem := s.typ(t.elem); elem != t.elem { + t.elem = elem + } + + case *Named: + if debug && t.check != nil { + panic("internal error: Named.check != nil") + } + if orig := s.typ(t.orig); orig != t.orig { + t.orig = orig + } + if under := s.typ(t.underlying); under != t.underlying { + t.underlying = under + } + s.typeList(t.targs) + s.funcList(t.methods) + + case *_TypeParam: + if bound := s.typ(t.bound); bound != t.bound { + t.bound = bound + } + + case *instance: + typ = t.expand() + s[t] = typ + + default: + panic("unimplemented") + } + + return typ +} + +func (s sanitizer) var_(v *Var) { + if v != nil { + if typ := s.typ(v.typ); typ != v.typ { + v.typ = typ + } + } +} + +func (s sanitizer) varList(list []*Var) { + for _, v := range list { + s.var_(v) + } +} + +func (s sanitizer) tuple(t *Tuple) { + if t != nil { + s.varList(t.vars) + } +} + +func (s sanitizer) func_(f *Func) { + if f != nil { + if typ := s.typ(f.typ); typ != f.typ { + f.typ = typ + } + } +} + +func (s sanitizer) funcList(list []*Func) { + for _, f := range list { + s.func_(f) + } +} + +func (s sanitizer) typeList(list []Type) { + for i, t := range list { + if typ := s.typ(t); typ != t { + list[i] = typ + } + } +} diff --git a/libgo/go/go/types/scope.go b/libgo/go/go/types/scope.go index 8c9d9ab..26c28d1 100644 --- a/libgo/go/go/types/scope.go +++ b/libgo/go/go/types/scope.go @@ -108,6 +108,40 @@ func (s *Scope) Insert(obj Object) Object { return nil } +// squash merges s with its parent scope p by adding all +// objects of s to p, adding all children of s to the +// children of p, and removing s from p's children. +// The function f is called for each object obj in s which +// has an object alt in p. s should be discarded after +// having been squashed. +func (s *Scope) squash(err func(obj, alt Object)) { + p := s.parent + assert(p != nil) + for _, obj := range s.elems { + obj.setParent(nil) + if alt := p.Insert(obj); alt != nil { + err(obj, alt) + } + } + + j := -1 // index of s in p.children + for i, ch := range p.children { + if ch == s { + j = i + break + } + } + assert(j >= 0) + k := len(p.children) - 1 + p.children[j] = p.children[k] + p.children = p.children[:k] + + p.children = append(p.children, s.children...) + + s.children = nil + s.elems = nil +} + // Pos and End describe the scope's source code extent [pos, end). // The results are guaranteed to be valid only if the type-checked // AST has complete position information. The extent is undefined diff --git a/libgo/go/go/types/sizeof_test.go b/libgo/go/go/types/sizeof_test.go new file mode 100644 index 0000000..5a9d07c --- /dev/null +++ b/libgo/go/go/types/sizeof_test.go @@ -0,0 +1,63 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import ( + "reflect" + "testing" +) + +// Signal size changes of important structures. +func TestSizeof(t *testing.T) { + const _64bit = ^uint(0)>>32 != 0 + + var tests = []struct { + val interface{} // type as a value + _32bit uintptr // size on 32bit platforms + _64bit uintptr // size on 64bit platforms + }{ + // Types + {Basic{}, 16, 32}, + {Array{}, 16, 24}, + {Slice{}, 8, 16}, + {Struct{}, 24, 48}, + {Pointer{}, 8, 16}, + {Tuple{}, 12, 24}, + {Signature{}, 44, 88}, + {_Sum{}, 12, 24}, + {Interface{}, 60, 120}, + {Map{}, 16, 32}, + {Chan{}, 12, 24}, + {Named{}, 64, 128}, + {_TypeParam{}, 28, 48}, + {instance{}, 44, 88}, + {bottom{}, 0, 0}, + {top{}, 0, 0}, + + // Objects + {PkgName{}, 48, 88}, + {Const{}, 48, 88}, + {TypeName{}, 40, 72}, + {Var{}, 44, 80}, + {Func{}, 44, 80}, + {Label{}, 44, 80}, + {Builtin{}, 44, 80}, + {Nil{}, 40, 72}, + + // Misc + {Scope{}, 40, 80}, + {Package{}, 40, 80}, + } + for _, test := range tests { + got := reflect.TypeOf(test.val).Size() + want := test._32bit + if _64bit { + want = test._64bit + } + if got != want { + t.Errorf("unsafe.Sizeof(%T) = %d, want %d", test.val, got, want) + } + } +} diff --git a/libgo/go/go/types/sizes.go b/libgo/go/go/types/sizes.go index 4787b24..3b334ac 100644 --- a/libgo/go/go/types/sizes.go +++ b/libgo/go/go/types/sizes.go @@ -48,7 +48,7 @@ type StdSizes struct { func (s *StdSizes) Alignof(T Type) int64 { // For arrays and structs, alignment is defined in terms // of alignment of the elements and fields, respectively. - switch t := T.Underlying().(type) { + switch t := optype(T).(type) { case *Array: // spec: "For a variable x of array type: unsafe.Alignof(x) // is the same as unsafe.Alignof(x[0]), but at least 1." @@ -118,7 +118,7 @@ var basicSizes = [...]byte{ } func (s *StdSizes) Sizeof(T Type) int64 { - switch t := T.Underlying().(type) { + switch t := optype(T).(type) { case *Basic: assert(isTyped(T)) k := t.kind @@ -148,6 +148,8 @@ func (s *StdSizes) Sizeof(T Type) int64 { } offsets := s.Offsetsof(t.fields) return offsets[n-1] + s.Sizeof(t.fields[n-1].typ) + case *_Sum: + panic("Sizeof unimplemented for type sum") case *Interface: return s.WordSize * 2 } @@ -241,7 +243,7 @@ func (conf *Config) offsetsof(T *Struct) []int64 { func (conf *Config) offsetof(typ Type, index []int) int64 { var o int64 for _, i := range index { - s := typ.Underlying().(*Struct) + s := asStruct(typ) o += conf.offsetsof(s)[i] typ = s.fields[i].typ } diff --git a/libgo/go/go/types/stdlib_test.go b/libgo/go/go/types/stdlib_test.go index 208311e..de30bdb 100644 --- a/libgo/go/go/types/stdlib_test.go +++ b/libgo/go/go/types/stdlib_test.go @@ -26,9 +26,15 @@ import ( . "go/types" ) +// The cmd/*/internal packages may have been deleted as part of a binary +// release. Import from source instead. +// +// (See https://golang.org/issue/43232 and +// https://github.com/golang/build/blob/df58bbac082bc87c4a3cdfe336d1ffe60bbaa916/cmd/release/release.go#L533-L545.) +// // Use the same importer for all std lib tests to // avoid repeated importing of the same packages. -var stdLibImporter = importer.Default() +var stdLibImporter = importer.ForCompiler(token.NewFileSet(), "source", nil) func TestStdlib(t *testing.T) { testenv.MustHaveGoBuild(t) @@ -108,6 +114,7 @@ func testTestDir(t *testing.T, path string, ignore ...string) { // get per-file instructions expectErrors := false filename := filepath.Join(path, f.Name()) + goVersion := "" if comment := firstComment(filename); comment != "" { fields := strings.Fields(comment) switch fields[0] { @@ -117,13 +124,17 @@ func testTestDir(t *testing.T, path string, ignore ...string) { expectErrors = true for _, arg := range fields[1:] { if arg == "-0" || arg == "-+" || arg == "-std" { - // Marked explicitly as not expected errors (-0), + // Marked explicitly as not expecting errors (-0), // or marked as compiling runtime/stdlib, which is only done // to trigger runtime/stdlib-only error output. // In both cases, the code should typecheck. expectErrors = false break } + const prefix = "-lang=" + if strings.HasPrefix(arg, prefix) { + goVersion = arg[len(prefix):] + } } } } @@ -132,6 +143,7 @@ func testTestDir(t *testing.T, path string, ignore ...string) { file, err := parser.ParseFile(fset, filename, nil, 0) if err == nil { conf := Config{Importer: stdLibImporter} + SetGoVersion(&conf, goVersion) _, err = conf.Check(filename, fset, []*ast.File{file}, nil) } @@ -159,6 +171,7 @@ func TestStdTest(t *testing.T) { "directive.go", // tests compiler rejection of bad directive placement - ignore "embedfunc.go", // tests //go:embed "embedvers.go", // tests //go:embed + "linkname2.go", // go/types doesn't check validity of //go:xxx directives ) } @@ -172,19 +185,15 @@ func TestStdFixed(t *testing.T) { testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"), "bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore "issue6889.go", // gc-specific test - "issue7746.go", // large constants - consumes too much memory "issue11362.go", // canonical import path check "issue16369.go", // go/types handles this correctly - not an issue "issue18459.go", // go/types doesn't check validity of //go:xxx directives "issue18882.go", // go/types doesn't check validity of //go:xxx directives - "issue20232.go", // go/types handles larger constants than gc "issue20529.go", // go/types does not have constraints on stack size "issue22200.go", // go/types does not have constraints on stack size "issue22200b.go", // go/types does not have constraints on stack size "issue25507.go", // go/types does not have constraints on stack size "issue20780.go", // go/types does not have constraints on stack size - "issue31747.go", // go/types does not have constraints on language level (-lang=go1.12) (see #31793) - "issue34329.go", // go/types does not have constraints on language level (-lang=go1.13) (see #31793) "bug251.go", // issue #34333 which was exposed with fix for #34151 "issue42058a.go", // go/types does not have constraints on channel element size "issue42058b.go", // go/types does not have constraints on channel element size @@ -200,6 +209,9 @@ func TestStdKen(t *testing.T) { // Package paths of excluded packages. var excluded = map[string]bool{ "builtin": true, + + // See #46027: some imports are missing for this submodule. + "crypto/ed25519/internal/edwards25519/field/_asm": true, } // typecheck typechecks the given package files. diff --git a/libgo/go/go/types/stmt.go b/libgo/go/go/types/stmt.go index d88e471..47f6dcf 100644 --- a/libgo/go/go/types/stmt.go +++ b/libgo/go/go/types/stmt.go @@ -14,6 +14,10 @@ import ( ) func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body *ast.BlockStmt, iota constant.Value) { + if check.conf.IgnoreFuncBodies { + panic("internal error: function body not ignored") + } + if trace { check.trace(body.Pos(), "--- %s: %s", name, sig) defer func() { @@ -49,6 +53,11 @@ func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body check.error(atPos(body.Rbrace), _MissingReturn, "missing return") } + // TODO(gri) Should we make it an error to declare generic functions + // where the type parameters are not used? + // 12/19/2018: Probably not - it can make sense to have an API with + // all functions uniformly sharing the same type parameters. + // spec: "Implementation restriction: A compiler may make it illegal to // declare a variable inside a function body if the variable is never used." check.usage(sig.scope) @@ -147,9 +156,9 @@ func (check *Checker) multipleDefaults(list []ast.Stmt) { } } -func (check *Checker) openScope(s ast.Stmt, comment string) { - scope := NewScope(check.scope, s.Pos(), s.End(), comment) - check.recordScope(s, scope) +func (check *Checker) openScope(node ast.Node, comment string) { + scope := NewScope(check.scope, node.Pos(), node.End(), comment) + check.recordScope(node, scope) check.scope = scope } @@ -269,10 +278,13 @@ L: func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[Type]ast.Expr) (T Type) { L: for _, e := range types { - T = check.typOrNil(e) + T = check.typeOrNil(e) if T == Typ[Invalid] { continue L } + if T != nil { + check.ordinaryType(e, T) + } // look for duplicate types // (quadratic algorithm, but type switches tend to be reasonably small) for t, other := range seen { @@ -355,8 +367,8 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { return } - tch, ok := ch.typ.Underlying().(*Chan) - if !ok { + tch := asChan(ch.typ) + if tch == nil { check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to non-chan type %s", ch.typ) return } @@ -609,7 +621,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { return } - // rhs must be of the form: expr.(type) and expr must be an interface + // rhs must be of the form: expr.(type) and expr must be an ordinary interface expr, _ := rhs.(*ast.TypeAssertExpr) if expr == nil || expr.Type != nil { check.invalidAST(s, "incorrect form of type switch guard") @@ -620,11 +632,12 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { if x.mode == invalid { return } - xtyp, _ := x.typ.Underlying().(*Interface) + xtyp, _ := under(x.typ).(*Interface) if xtyp == nil { check.errorf(&x, _InvalidTypeSwitch, "%s is not an interface", &x) return } + check.ordinaryType(&x, xtyp) check.multipleDefaults(s.Body.List) @@ -761,45 +774,24 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { // determine key/value types var key, val Type if x.mode != invalid { - switch typ := x.typ.Underlying().(type) { - case *Basic: - if isString(typ) { - key = Typ[Int] - val = universeRune // use 'rune' name - } - case *Array: - key = Typ[Int] - val = typ.elem - case *Slice: - key = Typ[Int] - val = typ.elem - case *Pointer: - if typ, _ := typ.base.Underlying().(*Array); typ != nil { - key = Typ[Int] - val = typ.elem - } - case *Map: - key = typ.key - val = typ.elem - case *Chan: - key = typ.elem - val = Typ[Invalid] - if typ.dir == SendOnly { - check.errorf(&x, _InvalidChanRange, "cannot range over send-only channel %s", &x) - // ok to continue - } - if s.Value != nil { - check.errorf(atPos(s.Value.Pos()), _InvalidIterVar, "iteration over %s permits only one iteration variable", &x) - // ok to continue + typ := optype(x.typ) + if _, ok := typ.(*Chan); ok && s.Value != nil { + // TODO(gri) this also needs to happen for channels in generic variables + check.softErrorf(atPos(s.Value.Pos()), _InvalidIterVar, "range over %s permits only one iteration variable", &x) + // ok to continue + } + var msg string + key, val, msg = rangeKeyVal(typ, isVarName(s.Key), isVarName(s.Value)) + if key == nil || msg != "" { + if msg != "" { + // TODO(rFindley) should this be parenthesized, to be consistent with other qualifiers? + msg = ": " + msg } + check.softErrorf(&x, _InvalidRangeExpr, "cannot range over %s%s", &x, msg) + // ok to continue } } - if key == nil { - check.errorf(&x, _InvalidRangeExpr, "cannot range over %s", &x) - // ok to continue - } - // check assignment to/declaration of iteration variables // (irregular assignment, cannot easily map to existing assignment checks) @@ -879,3 +871,72 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { check.invalidAST(s, "invalid statement") } } + +// isVarName reports whether x is a non-nil, non-blank (_) expression. +func isVarName(x ast.Expr) bool { + if x == nil { + return false + } + ident, _ := unparen(x).(*ast.Ident) + return ident == nil || ident.Name != "_" +} + +// rangeKeyVal returns the key and value type produced by a range clause +// over an expression of type typ, and possibly an error message. If the +// range clause is not permitted the returned key is nil or msg is not +// empty (in that case we still may have a non-nil key type which can be +// used to reduce the chance for follow-on errors). +// The wantKey, wantVal, and hasVal flags indicate which of the iteration +// variables are used or present; this matters if we range over a generic +// type where not all keys or values are of the same type. +func rangeKeyVal(typ Type, wantKey, wantVal bool) (Type, Type, string) { + switch typ := typ.(type) { + case *Basic: + if isString(typ) { + return Typ[Int], universeRune, "" // use 'rune' name + } + case *Array: + return Typ[Int], typ.elem, "" + case *Slice: + return Typ[Int], typ.elem, "" + case *Pointer: + if typ := asArray(typ.base); typ != nil { + return Typ[Int], typ.elem, "" + } + case *Map: + return typ.key, typ.elem, "" + case *Chan: + var msg string + if typ.dir == SendOnly { + msg = "send-only channel" + } + return typ.elem, Typ[Invalid], msg + case *_Sum: + first := true + var key, val Type + var msg string + typ.is(func(t Type) bool { + k, v, m := rangeKeyVal(under(t), wantKey, wantVal) + if k == nil || m != "" { + key, val, msg = k, v, m + return false + } + if first { + key, val, msg = k, v, m + first = false + return true + } + if wantKey && !Identical(key, k) { + key, val, msg = nil, nil, "all possible values must have the same key type" + return false + } + if wantVal && !Identical(val, v) { + key, val, msg = nil, nil, "all possible values must have the same element type" + return false + } + return true + }) + return key, val, msg + } + return nil, nil, "" +} diff --git a/libgo/go/go/types/subst.go b/libgo/go/go/types/subst.go new file mode 100644 index 0000000..931375f --- /dev/null +++ b/libgo/go/go/types/subst.go @@ -0,0 +1,543 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file implements instantiation of generic types +// through substitution of type parameters by actual +// types. + +package types + +import ( + "bytes" + "fmt" + "go/token" +) + +// TODO(rFindley) decide error codes for the errors in this file, and check +// if error spans can be improved + +type substMap struct { + // The targs field is currently needed for *Named type substitution. + // TODO(gri) rewrite that code, get rid of this field, and make this + // struct just the map (proj) + targs []Type + proj map[*_TypeParam]Type +} + +// makeSubstMap creates a new substitution map mapping tpars[i] to targs[i]. +// If targs[i] is nil, tpars[i] is not substituted. +func makeSubstMap(tpars []*TypeName, targs []Type) *substMap { + assert(len(tpars) == len(targs)) + proj := make(map[*_TypeParam]Type, len(tpars)) + for i, tpar := range tpars { + // We must expand type arguments otherwise *instance + // types end up as components in composite types. + // TODO(gri) explain why this causes problems, if it does + targ := expand(targs[i]) // possibly nil + targs[i] = targ + proj[tpar.typ.(*_TypeParam)] = targ + } + return &substMap{targs, proj} +} + +func (m *substMap) String() string { + return fmt.Sprintf("%s", m.proj) +} + +func (m *substMap) empty() bool { + return len(m.proj) == 0 +} + +func (m *substMap) lookup(tpar *_TypeParam) Type { + if t := m.proj[tpar]; t != nil { + return t + } + return tpar +} + +func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, poslist []token.Pos) (res Type) { + if trace { + check.trace(pos, "-- instantiating %s with %s", typ, typeListString(targs)) + check.indent++ + defer func() { + check.indent-- + var under Type + if res != nil { + // Calling under() here may lead to endless instantiations. + // Test case: type T[P any] T[P] + // TODO(gri) investigate if that's a bug or to be expected. + under = res.Underlying() + } + check.trace(pos, "=> %s (under = %s)", res, under) + }() + } + + assert(len(poslist) <= len(targs)) + + // TODO(gri) What is better here: work with TypeParams, or work with TypeNames? + var tparams []*TypeName + switch t := typ.(type) { + case *Named: + tparams = t.tparams + case *Signature: + tparams = t.tparams + defer func() { + // If we had an unexpected failure somewhere don't panic below when + // asserting res.(*Signature). Check for *Signature in case Typ[Invalid] + // is returned. + if _, ok := res.(*Signature); !ok { + return + } + // If the signature doesn't use its type parameters, subst + // will not make a copy. In that case, make a copy now (so + // we can set tparams to nil w/o causing side-effects). + if t == res { + copy := *t + res = © + } + // After instantiating a generic signature, it is not generic + // anymore; we need to set tparams to nil. + res.(*Signature).tparams = nil + }() + + default: + check.dump("%v: cannot instantiate %v", pos, typ) + unreachable() // only defined types and (defined) functions can be generic + } + + // the number of supplied types must match the number of type parameters + if len(targs) != len(tparams) { + // TODO(gri) provide better error message + check.errorf(atPos(pos), _Todo, "got %d arguments but %d type parameters", len(targs), len(tparams)) + return Typ[Invalid] + } + + if len(tparams) == 0 { + return typ // nothing to do (minor optimization) + } + + smap := makeSubstMap(tparams, targs) + + // check bounds + for i, tname := range tparams { + tpar := tname.typ.(*_TypeParam) + iface := tpar.Bound() + if iface.Empty() { + continue // no type bound + } + + targ := targs[i] + + // best position for error reporting + pos := pos + if i < len(poslist) { + pos = poslist[i] + } + + // The type parameter bound is parameterized with the same type parameters + // as the instantiated type; before we can use it for bounds checking we + // need to instantiate it with the type arguments with which we instantiate + // the parameterized type. + iface = check.subst(pos, iface, smap).(*Interface) + + // targ must implement iface (methods) + // - check only if we have methods + check.completeInterface(token.NoPos, iface) + if len(iface.allMethods) > 0 { + // If the type argument is a pointer to a type parameter, the type argument's + // method set is empty. + // TODO(gri) is this what we want? (spec question) + if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil { + check.errorf(atPos(pos), 0, "%s has no methods", targ) + break + } + if m, wrong := check.missingMethod(targ, iface, true); m != nil { + // TODO(gri) needs to print updated name to avoid major confusion in error message! + // (print warning for now) + // Old warning: + // check.softErrorf(pos, "%s does not satisfy %s (warning: name not updated) = %s (missing method %s)", targ, tpar.bound, iface, m) + if m.name == "==" { + // We don't want to report "missing method ==". + check.softErrorf(atPos(pos), 0, "%s does not satisfy comparable", targ) + } else if wrong != nil { + // TODO(gri) This can still report uninstantiated types which makes the error message + // more difficult to read then necessary. + // TODO(rFindley) should this use parentheses rather than ':' for qualification? + check.softErrorf(atPos(pos), _Todo, + "%s does not satisfy %s: wrong method signature\n\tgot %s\n\twant %s", + targ, tpar.bound, wrong, m, + ) + } else { + check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (missing method %s)", targ, tpar.bound, m.name) + } + break + } + } + + // targ's underlying type must also be one of the interface types listed, if any + if iface.allTypes == nil { + continue // nothing to do + } + + // If targ is itself a type parameter, each of its possible types, but at least one, must be in the + // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types). + if targ := asTypeParam(targ); targ != nil { + targBound := targ.Bound() + if targBound.allTypes == nil { + check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ) + break + } + for _, t := range unpackType(targBound.allTypes) { + if !iface.isSatisfiedBy(t) { + // TODO(gri) match this error message with the one below (or vice versa) + check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, t, iface.allTypes) + break + } + } + break + } + + // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any. + if !iface.isSatisfiedBy(targ) { + check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s or %s not found in %s)", targ, tpar.bound, targ, under(targ), iface.allTypes) + break + } + } + + return check.subst(pos, typ, smap) +} + +// subst returns the type typ with its type parameters tpars replaced by +// the corresponding type arguments targs, recursively. +// subst is functional in the sense that it doesn't modify the incoming +// type. If a substitution took place, the result type is different from +// from the incoming type. +func (check *Checker) subst(pos token.Pos, typ Type, smap *substMap) Type { + if smap.empty() { + return typ + } + + // common cases + switch t := typ.(type) { + case *Basic: + return typ // nothing to do + case *_TypeParam: + return smap.lookup(t) + } + + // general case + subst := subster{check, pos, make(map[Type]Type), smap} + return subst.typ(typ) +} + +type subster struct { + check *Checker + pos token.Pos + cache map[Type]Type + smap *substMap +} + +func (subst *subster) typ(typ Type) Type { + switch t := typ.(type) { + case nil: + // Call typOrNil if it's possible that typ is nil. + panic("nil typ") + + case *Basic, *bottom, *top: + // nothing to do + + case *Array: + elem := subst.typOrNil(t.elem) + if elem != t.elem { + return &Array{len: t.len, elem: elem} + } + + case *Slice: + elem := subst.typOrNil(t.elem) + if elem != t.elem { + return &Slice{elem: elem} + } + + case *Struct: + if fields, copied := subst.varList(t.fields); copied { + return &Struct{fields: fields, tags: t.tags} + } + + case *Pointer: + base := subst.typ(t.base) + if base != t.base { + return &Pointer{base: base} + } + + case *Tuple: + return subst.tuple(t) + + case *Signature: + // TODO(gri) rethink the recv situation with respect to methods on parameterized types + // recv := subst.var_(t.recv) // TODO(gri) this causes a stack overflow - explain + recv := t.recv + params := subst.tuple(t.params) + results := subst.tuple(t.results) + if recv != t.recv || params != t.params || results != t.results { + return &Signature{ + rparams: t.rparams, + // TODO(rFindley) why can't we nil out tparams here, rather than in + // instantiate above? + tparams: t.tparams, + scope: t.scope, + recv: recv, + params: params, + results: results, + variadic: t.variadic, + } + } + + case *_Sum: + types, copied := subst.typeList(t.types) + if copied { + // Don't do it manually, with a Sum literal: the new + // types list may not be unique and NewSum may remove + // duplicates. + return _NewSum(types) + } + + case *Interface: + methods, mcopied := subst.funcList(t.methods) + types := t.types + if t.types != nil { + types = subst.typ(t.types) + } + embeddeds, ecopied := subst.typeList(t.embeddeds) + if mcopied || types != t.types || ecopied { + iface := &Interface{methods: methods, types: types, embeddeds: embeddeds} + subst.check.posMap[iface] = subst.check.posMap[t] // satisfy completeInterface requirement + subst.check.completeInterface(token.NoPos, iface) + return iface + } + + case *Map: + key := subst.typ(t.key) + elem := subst.typ(t.elem) + if key != t.key || elem != t.elem { + return &Map{key: key, elem: elem} + } + + case *Chan: + elem := subst.typ(t.elem) + if elem != t.elem { + return &Chan{dir: t.dir, elem: elem} + } + + case *Named: + subst.check.indent++ + defer func() { + subst.check.indent-- + }() + dump := func(format string, args ...interface{}) { + if trace { + subst.check.trace(subst.pos, format, args...) + } + } + + if t.tparams == nil { + dump(">>> %s is not parameterized", t) + return t // type is not parameterized + } + + var newTargs []Type + + if len(t.targs) > 0 { + // already instantiated + dump(">>> %s already instantiated", t) + assert(len(t.targs) == len(t.tparams)) + // For each (existing) type argument targ, determine if it needs + // to be substituted; i.e., if it is or contains a type parameter + // that has a type argument for it. + for i, targ := range t.targs { + dump(">>> %d targ = %s", i, targ) + newTarg := subst.typ(targ) + if newTarg != targ { + dump(">>> substituted %d targ %s => %s", i, targ, newTarg) + if newTargs == nil { + newTargs = make([]Type, len(t.tparams)) + copy(newTargs, t.targs) + } + newTargs[i] = newTarg + } + } + + if newTargs == nil { + dump(">>> nothing to substitute in %s", t) + return t // nothing to substitute + } + } else { + // not yet instantiated + dump(">>> first instantiation of %s", t) + // TODO(rFindley) can we instead subst the tparam types here? + newTargs = subst.smap.targs + } + + // before creating a new named type, check if we have this one already + h := instantiatedHash(t, newTargs) + dump(">>> new type hash: %s", h) + if named, found := subst.check.typMap[h]; found { + dump(">>> found %s", named) + subst.cache[t] = named + return named + } + + // create a new named type and populate caches to avoid endless recursion + tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) + named := subst.check.newNamed(tname, t.underlying, t.methods) // method signatures are updated lazily + named.tparams = t.tparams // new type is still parameterized + named.targs = newTargs + subst.check.typMap[h] = named + subst.cache[t] = named + + // do the substitution + dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTargs) + named.underlying = subst.typOrNil(t.underlying) + named.orig = named.underlying // for cycle detection (Checker.validType) + + return named + + case *_TypeParam: + return subst.smap.lookup(t) + + case *instance: + // TODO(gri) can we avoid the expansion here and just substitute the type parameters? + return subst.typ(t.expand()) + + default: + panic("unimplemented") + } + + return typ +} + +// TODO(gri) Eventually, this should be more sophisticated. +// It won't work correctly for locally declared types. +func instantiatedHash(typ *Named, targs []Type) string { + var buf bytes.Buffer + writeTypeName(&buf, typ.obj, nil) + buf.WriteByte('[') + writeTypeList(&buf, targs, nil, nil) + buf.WriteByte(']') + + // With respect to the represented type, whether a + // type is fully expanded or stored as instance + // does not matter - they are the same types. + // Remove the instanceMarkers printed for instances. + res := buf.Bytes() + i := 0 + for _, b := range res { + if b != instanceMarker { + res[i] = b + i++ + } + } + + return string(res[:i]) +} + +func typeListString(list []Type) string { + var buf bytes.Buffer + writeTypeList(&buf, list, nil, nil) + return buf.String() +} + +// typOrNil is like typ but if the argument is nil it is replaced with Typ[Invalid]. +// A nil type may appear in pathological cases such as type T[P any] []func(_ T([]_)) +// where an array/slice element is accessed before it is set up. +func (subst *subster) typOrNil(typ Type) Type { + if typ == nil { + return Typ[Invalid] + } + return subst.typ(typ) +} + +func (subst *subster) var_(v *Var) *Var { + if v != nil { + if typ := subst.typ(v.typ); typ != v.typ { + copy := *v + copy.typ = typ + return © + } + } + return v +} + +func (subst *subster) tuple(t *Tuple) *Tuple { + if t != nil { + if vars, copied := subst.varList(t.vars); copied { + return &Tuple{vars: vars} + } + } + return t +} + +func (subst *subster) varList(in []*Var) (out []*Var, copied bool) { + out = in + for i, v := range in { + if w := subst.var_(v); w != v { + if !copied { + // first variable that got substituted => allocate new out slice + // and copy all variables + new := make([]*Var, len(in)) + copy(new, out) + out = new + copied = true + } + out[i] = w + } + } + return +} + +func (subst *subster) func_(f *Func) *Func { + if f != nil { + if typ := subst.typ(f.typ); typ != f.typ { + copy := *f + copy.typ = typ + return © + } + } + return f +} + +func (subst *subster) funcList(in []*Func) (out []*Func, copied bool) { + out = in + for i, f := range in { + if g := subst.func_(f); g != f { + if !copied { + // first function that got substituted => allocate new out slice + // and copy all functions + new := make([]*Func, len(in)) + copy(new, out) + out = new + copied = true + } + out[i] = g + } + } + return +} + +func (subst *subster) typeList(in []Type) (out []Type, copied bool) { + out = in + for i, t := range in { + if u := subst.typ(t); u != t { + if !copied { + // first function that got substituted => allocate new out slice + // and copy all functions + new := make([]Type, len(in)) + copy(new, out) + out = new + copied = true + } + out[i] = u + } + } + return +} diff --git a/libgo/go/go/types/testdata/blank.src b/libgo/go/go/types/testdata/check/blank.src index 6a2507f..6a2507f 100644 --- a/libgo/go/go/types/testdata/blank.src +++ b/libgo/go/go/types/testdata/check/blank.src diff --git a/libgo/go/go/types/testdata/check/builtins.go2 b/libgo/go/go/types/testdata/check/builtins.go2 new file mode 100644 index 0000000..3918d83 --- /dev/null +++ b/libgo/go/go/types/testdata/check/builtins.go2 @@ -0,0 +1,53 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file tests built-in calls on generic types. + +package builtins + +type Bmc interface { + type map[rune]string, chan int +} + +type Bms interface { + type map[string]int, []int +} + +type Bcs interface { + type chan bool, []float64 +} + +type Bss interface { + type []int, []string +} + +func _[T any] () { + _ = make(T /* ERROR invalid argument */ ) + _ = make(T /* ERROR invalid argument */ , 10) + _ = make(T /* ERROR invalid argument */ , 10, 20) +} + +func _[T Bmc] () { + _ = make(T) + _ = make(T, 10) + _ = make /* ERROR expects 1 or 2 arguments */ (T, 10, 20) +} + +func _[T Bms] () { + _ = make /* ERROR expects 2 arguments */ (T) + _ = make(T, 10) + _ = make /* ERROR expects 2 arguments */ (T, 10, 20) +} + +func _[T Bcs] () { + _ = make /* ERROR expects 2 arguments */ (T) + _ = make(T, 10) + _ = make /* ERROR expects 2 arguments */ (T, 10, 20) +} + +func _[T Bss] () { + _ = make /* ERROR expects 2 or 3 arguments */ (T) + _ = make(T, 10) + _ = make(T, 10, 20) +} diff --git a/libgo/go/go/types/testdata/builtins.src b/libgo/go/go/types/testdata/check/builtins.src index 98830eb..3707528 100644 --- a/libgo/go/go/types/testdata/builtins.src +++ b/libgo/go/go/types/testdata/check/builtins.src @@ -25,11 +25,11 @@ func append1() { _ = append(s, b) _ = append(s, x /* ERROR cannot use x */ ) _ = append(s, s /* ERROR cannot use s */ ) - _ = append(s... /* ERROR can only use ... with matching parameter */ ) - _ = append(s, b, s... /* ERROR can only use ... with matching parameter */ ) + _ = append(s...) /* ERROR not enough arguments */ + _ = append(s, b, s /* ERROR too many arguments */ ...) _ = append(s, 1, 2, 3) _ = append(s, 1, 2, 3, x /* ERROR cannot use x */ , 5, 6, 6) - _ = append(s, 1, 2, s... /* ERROR can only use ... with matching parameter */ ) + _ = append(s, 1, 2 /* ERROR too many arguments */, s...) _ = append([]interface{}(nil), 1, 2, "foo", x, 3.1425, false) type S []byte @@ -283,7 +283,7 @@ func delete1() { delete() // ERROR not enough arguments delete(1) // ERROR not enough arguments delete(1, 2, 3) // ERROR too many arguments - delete(m, 0 /* ERROR not assignable */) + delete(m, 0 /* ERROR cannot use */) delete(m, s) _ = delete /* ERROR used as value */ (m, s) @@ -514,7 +514,7 @@ func panic1() { panic("foo") panic(false) panic(1<<10) - panic(1 /* ERROR overflows */ <<1000) + panic(1 << /* ERROR constant shift overflow */ 1000) _ = panic /* ERROR used as value */ (0) var s []byte @@ -538,7 +538,7 @@ func print1() { print(2.718281828) print(false) print(1<<10) - print(1 /* ERROR overflows */ <<1000) + print(1 << /* ERROR constant shift overflow */ 1000) println(nil /* ERROR untyped nil */ ) var s []int @@ -564,7 +564,7 @@ func println1() { println(2.718281828) println(false) println(1<<10) - println(1 /* ERROR overflows */ <<1000) + println(1 << /* ERROR constant shift overflow */ 1000) println(nil /* ERROR untyped nil */ ) var s []int @@ -695,7 +695,7 @@ func Alignof1() { _ = unsafe.Alignof(42) _ = unsafe.Alignof(new(struct{})) _ = unsafe.Alignof(1<<10) - _ = unsafe.Alignof(1 /* ERROR overflows */ <<1000) + _ = unsafe.Alignof(1 << /* ERROR constant shift overflow */ 1000) _ = unsafe.Alignof(nil /* ERROR "untyped nil */ ) unsafe /* ERROR not used */ .Alignof(x) @@ -783,7 +783,7 @@ func Sizeof1() { _ = unsafe.Sizeof(42) _ = unsafe.Sizeof(new(complex128)) _ = unsafe.Sizeof(1<<10) - _ = unsafe.Sizeof(1 /* ERROR overflows */ <<1000) + _ = unsafe.Sizeof(1 << /* ERROR constant shift overflow */ 1000) _ = unsafe.Sizeof(nil /* ERROR untyped nil */ ) unsafe /* ERROR not used */ .Sizeof(x) diff --git a/libgo/go/go/types/testdata/check/chans.go2 b/libgo/go/go/types/testdata/check/chans.go2 new file mode 100644 index 0000000..fad2bce --- /dev/null +++ b/libgo/go/go/types/testdata/check/chans.go2 @@ -0,0 +1,62 @@ +package chans + +import "runtime" + +// Ranger returns a Sender and a Receiver. The Receiver provides a +// Next method to retrieve values. The Sender provides a Send method +// to send values and a Close method to stop sending values. The Next +// method indicates when the Sender has been closed, and the Send +// method indicates when the Receiver has been freed. +// +// This is a convenient way to exit a goroutine sending values when +// the receiver stops reading them. +func Ranger[T any]() (*Sender[T], *Receiver[T]) { + c := make(chan T) + d := make(chan bool) + s := &Sender[T]{values: c, done: d} + r := &Receiver[T]{values: c, done: d} + runtime.SetFinalizer(r, r.finalize) + return s, r +} + +// A sender is used to send values to a Receiver. +type Sender[T any] struct { + values chan<- T + done <-chan bool +} + +// Send sends a value to the receiver. It returns whether any more +// values may be sent; if it returns false the value was not sent. +func (s *Sender[T]) Send(v T) bool { + select { + case s.values <- v: + return true + case <-s.done: + return false + } +} + +// Close tells the receiver that no more values will arrive. +// After Close is called, the Sender may no longer be used. +func (s *Sender[T]) Close() { + close(s.values) +} + +// A Receiver receives values from a Sender. +type Receiver[T any] struct { + values <-chan T + done chan<- bool +} + +// Next returns the next value from the channel. The bool result +// indicates whether the value is valid, or whether the Sender has +// been closed and no more values will be received. +func (r *Receiver[T]) Next() (T, bool) { + v, ok := <-r.values + return v, ok +} + +// finalize is a finalizer for the receiver. +func (r *Receiver[T]) finalize() { + close(r.done) +} diff --git a/libgo/go/go/types/testdata/const0.src b/libgo/go/go/types/testdata/check/const0.src index adbbf28..5608b15 100644 --- a/libgo/go/go/types/testdata/const0.src +++ b/libgo/go/go/types/testdata/check/const0.src @@ -348,3 +348,16 @@ const _ = unsafe.Sizeof(func() { assert(one == 1) assert(iota == 0) }) + +// untyped constants must not get arbitrarily large +const prec = 512 // internal maximum precision for integers +const maxInt = (1<<(prec/2) - 1) * (1<<(prec/2) + 1) // == 1<<prec - 1 + +const _ = maxInt + /* ERROR constant addition overflow */ 1 +const _ = -maxInt - /* ERROR constant subtraction overflow */ 1 +const _ = maxInt ^ /* ERROR constant bitwise XOR overflow */ -1 +const _ = maxInt * /* ERROR constant multiplication overflow */ 2 +const _ = maxInt << /* ERROR constant shift overflow */ 2 +const _ = 1 << /* ERROR constant shift overflow */ prec + +const _ = ^ /* ERROR constant bitwise complement overflow */ maxInt diff --git a/libgo/go/go/types/testdata/const1.src b/libgo/go/go/types/testdata/check/const1.src index d827704..c912801 100644 --- a/libgo/go/go/types/testdata/const1.src +++ b/libgo/go/go/types/testdata/check/const1.src @@ -6,6 +6,8 @@ package const1 +import "math" + const( mi = ^int(0) mu = ^uint(0) @@ -43,7 +45,12 @@ const ( const ( smallestFloat32 = 1.0 / (1<<(127 - 1 + 23)) - smallestFloat64 = 1.0 / (1<<(1023 - 1 + 52)) + // TODO(gri) The compiler limits integers to 512 bit and thus + // we cannot compute the value (1<<(1023 - 1 + 52)) + // without overflow. For now we match the compiler. + // See also issue #44057. + // smallestFloat64 = 1.0 / (1<<(1023 - 1 + 52)) + smallestFloat64 = math.SmallestNonzeroFloat64 ) const ( @@ -53,7 +60,12 @@ const ( const ( maxFloat32 = 1<<127 * (1<<24 - 1) / (1.0<<23) - maxFloat64 = 1<<1023 * (1<<53 - 1) / (1.0<<52) + // TODO(gri) The compiler limits integers to 512 bit and thus + // we cannot compute the value 1<<1023 + // without overflow. For now we match the compiler. + // See also issue #44057. + // maxFloat64 = 1<<1023 * (1<<53 - 1) / (1.0<<52) + maxFloat64 = math.MaxFloat64 ) const ( diff --git a/libgo/go/go/types/testdata/constdecl.src b/libgo/go/go/types/testdata/check/constdecl.src index 680c85a..680c85a 100644 --- a/libgo/go/go/types/testdata/constdecl.src +++ b/libgo/go/go/types/testdata/check/constdecl.src diff --git a/libgo/go/go/types/testdata/conversions.src b/libgo/go/go/types/testdata/check/conversions.src index e1336c0..e1336c0 100644 --- a/libgo/go/go/types/testdata/conversions.src +++ b/libgo/go/go/types/testdata/check/conversions.src diff --git a/libgo/go/go/types/testdata/conversions2.src b/libgo/go/go/types/testdata/check/conversions2.src index 93a5f18..93a5f18 100644 --- a/libgo/go/go/types/testdata/conversions2.src +++ b/libgo/go/go/types/testdata/check/conversions2.src diff --git a/libgo/go/go/types/testdata/cycles.src b/libgo/go/go/types/testdata/check/cycles.src index 218b4ca..218b4ca 100644 --- a/libgo/go/go/types/testdata/cycles.src +++ b/libgo/go/go/types/testdata/check/cycles.src diff --git a/libgo/go/go/types/testdata/cycles1.src b/libgo/go/go/types/testdata/check/cycles1.src index ae2b38e..ae2b38e 100644 --- a/libgo/go/go/types/testdata/cycles1.src +++ b/libgo/go/go/types/testdata/check/cycles1.src diff --git a/libgo/go/go/types/testdata/cycles2.src b/libgo/go/go/types/testdata/check/cycles2.src index 1a7f40a..1a7f40a 100644 --- a/libgo/go/go/types/testdata/cycles2.src +++ b/libgo/go/go/types/testdata/check/cycles2.src diff --git a/libgo/go/go/types/testdata/cycles3.src b/libgo/go/go/types/testdata/check/cycles3.src index 5e89b62..5e89b62 100644 --- a/libgo/go/go/types/testdata/cycles3.src +++ b/libgo/go/go/types/testdata/check/cycles3.src diff --git a/libgo/go/go/types/testdata/cycles4.src b/libgo/go/go/types/testdata/check/cycles4.src index 445babc..445babc 100644 --- a/libgo/go/go/types/testdata/cycles4.src +++ b/libgo/go/go/types/testdata/check/cycles4.src diff --git a/libgo/go/go/types/testdata/cycles5.src b/libgo/go/go/types/testdata/check/cycles5.src index 397adcc..397adcc 100644 --- a/libgo/go/go/types/testdata/cycles5.src +++ b/libgo/go/go/types/testdata/check/cycles5.src diff --git a/libgo/go/go/types/testdata/decls0.src b/libgo/go/go/types/testdata/check/decls0.src index 5501b65..5ad8f53 100644 --- a/libgo/go/go/types/testdata/decls0.src +++ b/libgo/go/go/types/testdata/check/decls0.src @@ -184,11 +184,13 @@ func f1(x f1 /* ERROR "not a type" */ ) {} func f2(x *f2 /* ERROR "not a type" */ ) {} func f3() (x f3 /* ERROR "not a type" */ ) { return } func f4() (x *f4 /* ERROR "not a type" */ ) { return } +// TODO(#43215) this should be detected as a cycle error +func f5([unsafe.Sizeof(f5)]int) {} -func (S0) m1 /* ERROR illegal cycle */ (x S0 /* ERROR value .* is not a type */ .m1) {} -func (S0) m2 /* ERROR illegal cycle */ (x *S0 /* ERROR value .* is not a type */ .m2) {} -func (S0) m3 /* ERROR illegal cycle */ () (x S0 /* ERROR value .* is not a type */ .m3) { return } -func (S0) m4 /* ERROR illegal cycle */ () (x *S0 /* ERROR value .* is not a type */ .m4) { return } +func (S0) m1 (x S0 /* ERROR value .* is not a type */ .m1) {} +func (S0) m2 (x *S0 /* ERROR value .* is not a type */ .m2) {} +func (S0) m3 () (x S0 /* ERROR value .* is not a type */ .m3) { return } +func (S0) m4 () (x *S0 /* ERROR value .* is not a type */ .m4) { return } // interfaces may not have any blank methods type BlankI interface { diff --git a/libgo/go/go/types/testdata/decls1.src b/libgo/go/go/types/testdata/check/decls1.src index f4d2eab..f4d2eab 100644 --- a/libgo/go/go/types/testdata/decls1.src +++ b/libgo/go/go/types/testdata/check/decls1.src diff --git a/libgo/go/go/types/testdata/decls2a.src b/libgo/go/go/types/testdata/check/decls2/decls2a.src index bdbecd9..bdbecd9 100644 --- a/libgo/go/go/types/testdata/decls2a.src +++ b/libgo/go/go/types/testdata/check/decls2/decls2a.src diff --git a/libgo/go/go/types/testdata/decls2b.src b/libgo/go/go/types/testdata/check/decls2/decls2b.src index 5c55750..5c55750 100644 --- a/libgo/go/go/types/testdata/decls2b.src +++ b/libgo/go/go/types/testdata/check/decls2/decls2b.src diff --git a/libgo/go/go/types/testdata/decls3.src b/libgo/go/go/types/testdata/check/decls3.src index 745175c..745175c 100644 --- a/libgo/go/go/types/testdata/decls3.src +++ b/libgo/go/go/types/testdata/check/decls3.src diff --git a/libgo/go/go/types/testdata/decls4.src b/libgo/go/go/types/testdata/check/decls4.src index 140bbfd..140bbfd 100644 --- a/libgo/go/go/types/testdata/decls4.src +++ b/libgo/go/go/types/testdata/check/decls4.src diff --git a/libgo/go/go/types/testdata/decls5.src b/libgo/go/go/types/testdata/check/decls5.src index 88d3194..88d3194 100644 --- a/libgo/go/go/types/testdata/decls5.src +++ b/libgo/go/go/types/testdata/check/decls5.src diff --git a/libgo/go/go/types/testdata/errors.src b/libgo/go/go/types/testdata/check/errors.src index ff92921..ff92921 100644 --- a/libgo/go/go/types/testdata/errors.src +++ b/libgo/go/go/types/testdata/check/errors.src diff --git a/libgo/go/go/types/testdata/expr0.src b/libgo/go/go/types/testdata/check/expr0.src index 1aac726..1aac726 100644 --- a/libgo/go/go/types/testdata/expr0.src +++ b/libgo/go/go/types/testdata/check/expr0.src diff --git a/libgo/go/go/types/testdata/expr1.src b/libgo/go/go/types/testdata/check/expr1.src index 4ead815..4ead815 100644 --- a/libgo/go/go/types/testdata/expr1.src +++ b/libgo/go/go/types/testdata/check/expr1.src diff --git a/libgo/go/go/types/testdata/expr2.src b/libgo/go/go/types/testdata/check/expr2.src index 0c959e8..0c959e8 100644 --- a/libgo/go/go/types/testdata/expr2.src +++ b/libgo/go/go/types/testdata/check/expr2.src diff --git a/libgo/go/go/types/testdata/expr3.src b/libgo/go/go/types/testdata/check/expr3.src index e6777aa..0525a5a 100644 --- a/libgo/go/go/types/testdata/expr3.src +++ b/libgo/go/go/types/testdata/check/expr3.src @@ -34,6 +34,7 @@ func indexes() { _ = a[9] _ = a[10 /* ERROR "index .* out of bounds" */ ] _ = a[1 /* ERROR "overflows" */ <<100] + _ = a[1<< /* ERROR "constant shift overflow" */ 1000] // no out-of-bounds follow-on error _ = a[10:] _ = a[:10] _ = a[10:10] @@ -492,26 +493,26 @@ func _calls() { f1(0) f1(x) f1(10.0) - f1() /* ERROR "too few arguments" */ + f1() /* ERROR "not enough arguments" */ f1(x, y /* ERROR "too many arguments" */ ) f1(s /* ERROR "cannot use .* in argument" */ ) f1(x ... /* ERROR "cannot use ..." */ ) f1(g0 /* ERROR "used as value" */ ()) f1(g1()) - f1(g2 /* ERROR "cannot use g2" */ /* ERROR "too many arguments" */ ()) + f1(g2 /* ERROR "too many arguments" */ ()) - f2() /* ERROR "too few arguments" */ - f2(3.14) /* ERROR "too few arguments" */ + f2() /* ERROR "not enough arguments" */ + f2(3.14) /* ERROR "not enough arguments" */ f2(3.14, "foo") f2(x /* ERROR "cannot use .* in argument" */ , "foo") f2(g0 /* ERROR "used as value" */ ()) - f2(g1 /* ERROR "cannot use .* in argument" */ ()) /* ERROR "too few arguments" */ + f2(g1()) /* ERROR "not enough arguments" */ f2(g2()) - fs() /* ERROR "too few arguments" */ + fs() /* ERROR "not enough arguments" */ fs(g0 /* ERROR "used as value" */ ()) fs(g1 /* ERROR "cannot use .* in argument" */ ()) - fs(g2 /* ERROR "cannot use .* in argument" */ /* ERROR "too many arguments" */ ()) + fs(g2 /* ERROR "too many arguments" */ ()) fs(gs()) fv() @@ -519,7 +520,7 @@ func _calls() { fv(s /* ERROR "cannot use .* in argument" */ ) fv(s...) fv(x /* ERROR "cannot use" */ ...) - fv(1, s... /* ERROR "can only use ... with matching parameter" */ ) + fv(1, s /* ERROR "too many arguments" */ ...) fv(gs /* ERROR "cannot use .* in argument" */ ()) fv(gs /* ERROR "cannot use .* in argument" */ ()...) @@ -528,7 +529,7 @@ func _calls() { t.fm(1, 2.0, x) t.fm(s /* ERROR "cannot use .* in argument" */ ) t.fm(g1()) - t.fm(1, s... /* ERROR "can only use ... with matching parameter" */ ) + t.fm(1, s /* ERROR "too many arguments" */ ...) t.fm(gs /* ERROR "cannot use .* in argument" */ ()) t.fm(gs /* ERROR "cannot use .* in argument" */ ()...) @@ -536,7 +537,7 @@ func _calls() { T.fm(t, 1, 2.0, x) T.fm(t, s /* ERROR "cannot use .* in argument" */ ) T.fm(t, g1()) - T.fm(t, 1, s... /* ERROR "can only use ... with matching parameter" */ ) + T.fm(t, 1, s /* ERROR "too many arguments" */ ...) T.fm(t, gs /* ERROR "cannot use .* in argument" */ ()) T.fm(t, gs /* ERROR "cannot use .* in argument" */ ()...) @@ -545,7 +546,7 @@ func _calls() { i.fm(1, 2.0, x) i.fm(s /* ERROR "cannot use .* in argument" */ ) i.fm(g1()) - i.fm(1, s... /* ERROR "can only use ... with matching parameter" */ ) + i.fm(1, s /* ERROR "too many arguments" */ ...) i.fm(gs /* ERROR "cannot use .* in argument" */ ()) i.fm(gs /* ERROR "cannot use .* in argument" */ ()...) diff --git a/libgo/go/go/types/testdata/check/go1_12.src b/libgo/go/go/types/testdata/check/go1_12.src new file mode 100644 index 0000000..1e529f1 --- /dev/null +++ b/libgo/go/go/types/testdata/check/go1_12.src @@ -0,0 +1,35 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Check Go language version-specific errors. + +package go1_12 // go1.12 + +// numeric literals +const ( + _ = 1_000 // ERROR "underscores in numeric literals requires go1.13 or later" + _ = 0b111 // ERROR "binary literals requires go1.13 or later" + _ = 0o567 // ERROR "0o/0O-style octal literals requires go1.13 or later" + _ = 0xabc // ok + _ = 0x0p1 // ERROR "hexadecimal floating-point literals requires go1.13 or later" + + _ = 0B111 // ERROR "binary" + _ = 0O567 // ERROR "octal" + _ = 0Xabc // ok + _ = 0X0P1 // ERROR "hexadecimal floating-point" + + _ = 1_000i // ERROR "underscores" + _ = 0b111i // ERROR "binary" + _ = 0o567i // ERROR "octal" + _ = 0xabci // ERROR "hexadecimal floating-point" + _ = 0x0p1i // ERROR "hexadecimal floating-point" +) + +// signed shift counts +var ( + s int + _ = 1 << s // ERROR "invalid operation: signed shift count s \(variable of type int\) requires go1.13 or later" + _ = 1 >> s // ERROR "signed shift count" +) + diff --git a/libgo/go/go/types/testdata/check/go1_13.src b/libgo/go/go/types/testdata/check/go1_13.src new file mode 100644 index 0000000..6aa1364 --- /dev/null +++ b/libgo/go/go/types/testdata/check/go1_13.src @@ -0,0 +1,22 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Check Go language version-specific errors. + +package go1_13 // go1.13 + +// interface embedding + +type I interface { m() } + +type _ interface { + m() + I // ERROR "duplicate method m" +} + +type _ interface { + I + I // ERROR "duplicate method m" +} + diff --git a/libgo/go/go/types/testdata/check/go1_16.src b/libgo/go/go/types/testdata/check/go1_16.src new file mode 100644 index 0000000..fdf5c99 --- /dev/null +++ b/libgo/go/go/types/testdata/check/go1_16.src @@ -0,0 +1,13 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Check Go language version-specific errors. + +package go1_16 // go1.16 + +type Slice []byte +type Array [8]byte + +var s Slice +var p = (*Array)(s /* ERROR requires go1.17 or later */ ) diff --git a/libgo/go/go/types/testdata/check/go1_8.src b/libgo/go/go/types/testdata/check/go1_8.src new file mode 100644 index 0000000..3ead1e9 --- /dev/null +++ b/libgo/go/go/types/testdata/check/go1_8.src @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Check Go language version-specific errors. + +package go1_8 // go1.8 + +// type alias declarations +type any = /* ERROR type aliases requires go1.9 or later */ interface{} + diff --git a/libgo/go/go/types/testdata/gotos.src b/libgo/go/go/types/testdata/check/gotos.src index 069a94b..069a94b 100644 --- a/libgo/go/go/types/testdata/gotos.src +++ b/libgo/go/go/types/testdata/check/gotos.src diff --git a/libgo/go/go/types/testdata/importC.src b/libgo/go/go/types/testdata/check/importC.src index f55be2d..f55be2d 100644 --- a/libgo/go/go/types/testdata/importC.src +++ b/libgo/go/go/types/testdata/check/importC.src diff --git a/libgo/go/go/types/testdata/importdecl0a.src b/libgo/go/go/types/testdata/check/importdecl0/importdecl0a.src index e96fca3..5ceb96e 100644 --- a/libgo/go/go/types/testdata/importdecl0a.src +++ b/libgo/go/go/types/testdata/check/importdecl0/importdecl0a.src @@ -10,7 +10,7 @@ import ( // we can have multiple blank imports (was bug) _ "math" _ "net/rpc" - init /* ERROR "cannot declare init" */ "fmt" + init /* ERROR "cannot import package as init" */ "fmt" // reflect defines a type "flag" which shows up in the gc export data "reflect" . /* ERROR "imported but not used" */ "reflect" diff --git a/libgo/go/go/types/testdata/importdecl0b.src b/libgo/go/go/types/testdata/check/importdecl0/importdecl0b.src index 6844e70..5569042 100644 --- a/libgo/go/go/types/testdata/importdecl0b.src +++ b/libgo/go/go/types/testdata/check/importdecl0/importdecl0b.src @@ -8,7 +8,7 @@ import "math" import m "math" import . "testing" // declares T in file scope -import . /* ERROR "imported but not used" */ "unsafe" +import . /* ERROR .unsafe. imported but not used */ "unsafe" import . "fmt" // declares Println in file scope import ( diff --git a/libgo/go/go/types/testdata/importdecl1a.src b/libgo/go/go/types/testdata/check/importdecl1/importdecl1a.src index d377c01..d377c01 100644 --- a/libgo/go/go/types/testdata/importdecl1a.src +++ b/libgo/go/go/types/testdata/check/importdecl1/importdecl1a.src diff --git a/libgo/go/go/types/testdata/importdecl1b.src b/libgo/go/go/types/testdata/check/importdecl1/importdecl1b.src index ee70bbd..43a7bcd 100644 --- a/libgo/go/go/types/testdata/importdecl1b.src +++ b/libgo/go/go/types/testdata/check/importdecl1/importdecl1b.src @@ -4,7 +4,7 @@ package importdecl1 -import . /* ERROR "imported but not used" */ "unsafe" +import . /* ERROR .unsafe. imported but not used */ "unsafe" type B interface { A diff --git a/libgo/go/go/types/testdata/init0.src b/libgo/go/go/types/testdata/check/init0.src index 6e8746a..6e8746a 100644 --- a/libgo/go/go/types/testdata/init0.src +++ b/libgo/go/go/types/testdata/check/init0.src diff --git a/libgo/go/go/types/testdata/init1.src b/libgo/go/go/types/testdata/check/init1.src index 39ca314..39ca314 100644 --- a/libgo/go/go/types/testdata/init1.src +++ b/libgo/go/go/types/testdata/check/init1.src diff --git a/libgo/go/go/types/testdata/init2.src b/libgo/go/go/types/testdata/check/init2.src index 614db6c..614db6c 100644 --- a/libgo/go/go/types/testdata/init2.src +++ b/libgo/go/go/types/testdata/check/init2.src diff --git a/libgo/go/go/types/testdata/issue25008a.src b/libgo/go/go/types/testdata/check/issue25008/issue25008a.src index cf71ca1..cf71ca1 100644 --- a/libgo/go/go/types/testdata/issue25008a.src +++ b/libgo/go/go/types/testdata/check/issue25008/issue25008a.src diff --git a/libgo/go/go/types/testdata/issue25008b.src b/libgo/go/go/types/testdata/check/issue25008/issue25008b.src index f132b7f..f132b7f 100644 --- a/libgo/go/go/types/testdata/issue25008b.src +++ b/libgo/go/go/types/testdata/check/issue25008/issue25008b.src diff --git a/libgo/go/go/types/testdata/check/issues.go2 b/libgo/go/go/types/testdata/check/issues.go2 new file mode 100644 index 0000000..8994164 --- /dev/null +++ b/libgo/go/go/types/testdata/check/issues.go2 @@ -0,0 +1,256 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains regression tests for bugs found. + +package p + +import "io" +import "context" + +// Interfaces are always comparable (though the comparison may panic at runtime). +func eql[T comparable](x, y T) bool { + return x == y +} + +func _() { + var x interface{} + var y interface{ m() } + eql(x, y /* ERROR does not match */ ) // interfaces of different types + eql(x, x) + eql(y, y) + eql(y, nil) + eql[io.Reader](nil, nil) +} + +// If we have a receiver of pointer type (below: *T) we must ignore +// the pointer in the implementation of the method lookup because +// the type bound of T is an interface and pointer to interface types +// have no methods and then the lookup would fail. +type C[T any] interface { + m() +} + +// using type bound C +func _[T C[T]](x *T) { + x.m() +} + +// using an interface literal as bound +func _[T interface{ m() }](x *T) { + x.m() +} + +// In a generic function body all method calls will be pointer method calls. +// If necessary, the function body will insert temporary variables, not seen +// by the user, in order to get an addressable variable to use to call the method. +// Thus, assume an argument type for a generic function to be the type of addressable +// values in the generic function when checking if the argument type satisfies the +// generic function's type bound. +func f2[_ interface{ m1(); m2() }]() + +type T struct{} +func (T) m1() +func (*T) m2() + +func _() { + // TODO(rFindley) this error should be positioned on the 'T'. + f2 /* ERROR wrong method signature */ [T]() + f2[*T]() +} + +// When a type parameter is used as an argument to instantiate a parameterized +// type with a type list constraint, all of the type argument's types in its +// bound, but at least one (!), must be in the type list of the bound of the +// corresponding parameterized type's type parameter. +type T1[P interface{type uint}] struct{} + +func _[P any]() { + _ = T1[P /* ERROR P has no type constraints */ ]{} +} + +// This is the original (simplified) program causing the same issue. +type Unsigned interface { + type uint +} + +type T2[U Unsigned] struct { + s U +} + +func (u T2[U]) Add1() U { + return u.s + 1 +} + +func NewT2[U any]() T2[U /* ERROR U has no type constraints */ ] { + return T2[U /* ERROR U has no type constraints */ ]{} +} + +func _() { + u := NewT2[string]() + _ = u.Add1() +} + +// When we encounter an instantiated type such as Elem[T] we must +// not "expand" the instantiation when the type to be instantiated +// (Elem in this case) is not yet fully set up. +type Elem[T any] struct { + next *Elem[T] + list *List[T] +} + +type List[T any] struct { + root Elem[T] +} + +func (l *List[T]) Init() { + l.root.next = &l.root +} + +// This is the original program causing the same issue. +type Element2[TElem any] struct { + next, prev *Element2[TElem] + list *List2[TElem] + Value TElem +} + +type List2[TElem any] struct { + root Element2[TElem] + len int +} + +func (l *List2[TElem]) Init() *List2[TElem] { + l.root.next = &l.root + l.root.prev = &l.root + l.len = 0 + return l +} + +// Self-recursive instantiations must work correctly. +type A[P any] struct { _ *A[P] } + +type AB[P any] struct { _ *BA[P] } +type BA[P any] struct { _ *AB[P] } + +// And a variation that also caused a problem with an +// unresolved underlying type. +type Element3[TElem any] struct { + next, prev *Element3[TElem] + list *List3[TElem] + Value TElem +} + +func (e *Element3[TElem]) Next() *Element3[TElem] { + if p := e.next; e.list != nil && p != &e.list.root { + return p + } + return nil +} + +type List3[TElem any] struct { + root Element3[TElem] + len int +} + +// Infinite generic type declarations must lead to an error. +type inf1[T any] struct{ _ inf1 /* ERROR illegal cycle */ [T] } +type inf2[T any] struct{ inf2 /* ERROR illegal cycle */ [T] } + +// The implementation of conversions T(x) between integers and floating-point +// numbers checks that both T and x have either integer or floating-point +// type. When the type of T or x is a type parameter, the respective simple +// predicate disjunction in the implementation was wrong because if a type list +// contains both an integer and a floating-point type, the type parameter is +// neither an integer or a floating-point number. +func convert[T1, T2 interface{type int, uint, float32}](v T1) T2 { + return T2(v) +} + +func _() { + convert[int, uint](5) +} + +// When testing binary operators, for +, the operand types must either be +// both numeric, or both strings. The implementation had the same problem +// with this check as the conversion issue above (issue #39623). + +func issue39623[T interface{type int, string}](x, y T) T { + return x + y +} + +// Simplified, from https://go2goplay.golang.org/p/efS6x6s-9NI: +func Sum[T interface{type int, string}](s []T) (sum T) { + for _, v := range s { + sum += v + } + return +} + +// Assignability of an unnamed pointer type to a type parameter that +// has a matching underlying type. +func _[T interface{}, PT interface{type *T}] (x T) PT { + return &x +} + +// Indexing of generic types containing type parameters in their type list: +func at[T interface{ type []E }, E interface{}](x T, i int) E { + return x[i] +} + +// A generic type inside a function acts like a named type. Its underlying +// type is itself, its "operational type" is defined by the type list in +// the tybe bound, if any. +func _[T interface{type int}](x T) { + type myint int + var _ int = int(x) + var _ T = 42 + var _ T = T(myint(42)) +} + +// Indexing a generic type with an array type bound checks length. +// (Example by mdempsky@.) +func _[T interface { type [10]int }](x T) { + _ = x[9] // ok + _ = x[20 /* ERROR out of bounds */ ] +} + +// Pointer indirection of a generic type. +func _[T interface{ type *int }](p T) int { + return *p +} + +// Channel sends and receives on generic types. +func _[T interface{ type chan int }](ch T) int { + ch <- 0 + return <- ch +} + +// Calling of a generic variable. +func _[T interface{ type func() }](f T) { + f() + go f() +} + +// We must compare against the underlying type of type list entries +// when checking if a constraint is satisfied by a type. The under- +// lying type of each type list entry must be computed after the +// interface has been instantiated as its typelist may contain a +// type parameter that was substituted with a defined type. +// Test case from an (originally) failing example. + +type sliceOf[E any] interface{ type []E } + +func append[T interface{}, S sliceOf[T], T2 interface{ type T }](s S, t ...T2) S + +var f func() +var cancelSlice []context.CancelFunc +var _ = append[context.CancelFunc, []context.CancelFunc, context.CancelFunc](cancelSlice, f) + +// A generic function must be instantiated with a type, not a value. + +func g[T any](T) T + +var _ = g[int] +var _ = g[nil /* ERROR is not a type */ ] +var _ = g(0) diff --git a/libgo/go/go/types/testdata/issues.src b/libgo/go/go/types/testdata/check/issues.src index e0c5d7a..55fe220 100644 --- a/libgo/go/go/types/testdata/issues.src +++ b/libgo/go/go/types/testdata/check/issues.src @@ -6,7 +6,7 @@ package issues import ( "fmt" - syn "cmd/compile/internal/syntax" + syn "regexp/syntax" t1 "text/template" t2 "html/template" ) @@ -325,14 +325,14 @@ func issue28281c(a, b, c ... /* ERROR can only use ... with final parameter */ i func issue28281d(... /* ERROR can only use ... with final parameter */ int, int) func issue28281e(a, b, c ... /* ERROR can only use ... with final parameter */ int, d int) func issue28281f(... /* ERROR can only use ... with final parameter */ int, ... /* ERROR can only use ... with final parameter */ int, int) -func (... /* ERROR expected type */ TT) f() -func issue28281g() (... /* ERROR expected type */ TT) +func (... /* ERROR can only use ... with final parameter */ TT) f() +func issue28281g() (... /* ERROR can only use ... with final parameter */ TT) // Issue #26234: Make various field/method lookup errors easier to read by matching cmd/compile's output -func issue26234a(f *syn.File) { +func issue26234a(f *syn.Prog) { // The error message below should refer to the actual package name (syntax) // not the local package name (syn). - f.foo /* ERROR f.foo undefined \(type \*syntax.File has no field or method foo\) */ + f.foo /* ERROR f\.foo undefined \(type \*syntax\.Prog has no field or method foo\) */ } type T struct { @@ -357,9 +357,15 @@ func issue35895() { var _ T = 0 // ERROR cannot use 0 \(untyped int constant\) as T // There is only one package with name syntax imported, only use the (global) package name in error messages. - var _ *syn.File = 0 // ERROR cannot use 0 \(untyped int constant\) as \*syntax.File + var _ *syn.Prog = 0 // ERROR cannot use 0 \(untyped int constant\) as \*syntax.Prog // Because both t1 and t2 have the same global package name (template), // qualify packages with full path name in this case. - var _ t1.Template = t2 /* ERROR cannot use .* \(value of type "html/template".Template\) as "text/template".Template */ .Template{} + var _ t1.Template = t2 /* ERROR cannot use .* \(value of type .html/template.\.Template\) as .text/template.\.Template */ .Template{} +} + +func issue42989(s uint) { + var m map[int]string + delete(m, 1<<s) + delete(m, 1.<<s) } diff --git a/libgo/go/go/types/testdata/labels.src b/libgo/go/go/types/testdata/check/labels.src index 9f42406..9f42406 100644 --- a/libgo/go/go/types/testdata/labels.src +++ b/libgo/go/go/types/testdata/check/labels.src diff --git a/libgo/go/go/types/testdata/check/linalg.go2 b/libgo/go/go/types/testdata/check/linalg.go2 new file mode 100644 index 0000000..0d27603 --- /dev/null +++ b/libgo/go/go/types/testdata/check/linalg.go2 @@ -0,0 +1,83 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package linalg + +import "math" + +// Numeric is type bound that matches any numeric type. +// It would likely be in a constraints package in the standard library. +type Numeric interface { + type int, int8, int16, int32, int64, + uint, uint8, uint16, uint32, uint64, uintptr, + float32, float64, + complex64, complex128 +} + +func DotProduct[T Numeric](s1, s2 []T) T { + if len(s1) != len(s2) { + panic("DotProduct: slices of unequal length") + } + var r T + for i := range s1 { + r += s1[i] * s2[i] + } + return r +} + +// NumericAbs matches numeric types with an Abs method. +type NumericAbs[T any] interface { + Numeric + + Abs() T +} + +// AbsDifference computes the absolute value of the difference of +// a and b, where the absolute value is determined by the Abs method. +func AbsDifference[T NumericAbs[T]](a, b T) T { + d := a - b + return d.Abs() +} + +// OrderedNumeric is a type bound that matches numeric types that support the < operator. +type OrderedNumeric interface { + type int, int8, int16, int32, int64, + uint, uint8, uint16, uint32, uint64, uintptr, + float32, float64 +} + +// Complex is a type bound that matches the two complex types, which do not have a < operator. +type Complex interface { + type complex64, complex128 +} + +// OrderedAbs is a helper type that defines an Abs method for +// ordered numeric types. +type OrderedAbs[T OrderedNumeric] T + +func (a OrderedAbs[T]) Abs() OrderedAbs[T] { + if a < 0 { + return -a + } + return a +} + +// ComplexAbs is a helper type that defines an Abs method for +// complex types. +type ComplexAbs[T Complex] T + +func (a ComplexAbs[T]) Abs() ComplexAbs[T] { + r := float64(real(a)) + i := float64(imag(a)) + d := math.Sqrt(r * r + i * i) + return ComplexAbs[T](complex(d, 0)) +} + +func OrderedAbsDifference[T OrderedNumeric](a, b T) T { + return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b))) +} + +func ComplexAbsDifference[T Complex](a, b T) T { + return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b))) +} diff --git a/libgo/go/go/types/testdata/literals.src b/libgo/go/go/types/testdata/check/literals.src index 494a465..494a465 100644 --- a/libgo/go/go/types/testdata/literals.src +++ b/libgo/go/go/types/testdata/check/literals.src diff --git a/libgo/go/go/types/testdata/check/main.go2 b/libgo/go/go/types/testdata/check/main.go2 new file mode 100644 index 0000000..65e9aa2 --- /dev/null +++ b/libgo/go/go/types/testdata/check/main.go2 @@ -0,0 +1,7 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func main[ /* ERROR "func main must have no type parameters" */ T any]() {} diff --git a/libgo/go/go/types/testdata/check/main.src b/libgo/go/go/types/testdata/check/main.src new file mode 100644 index 0000000..f892938 --- /dev/null +++ b/libgo/go/go/types/testdata/check/main.src @@ -0,0 +1,9 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func main() +func /* ERROR "no arguments and no return values" */ main /* ERROR redeclared */ (int) +func /* ERROR "no arguments and no return values" */ main /* ERROR redeclared */ () int diff --git a/libgo/go/go/types/testdata/check/map.go2 b/libgo/go/go/types/testdata/check/map.go2 new file mode 100644 index 0000000..814d953 --- /dev/null +++ b/libgo/go/go/types/testdata/check/map.go2 @@ -0,0 +1,113 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package orderedmap provides an ordered map, implemented as a binary tree. +package orderedmap + +// TODO(gri) fix imports for tests +import "chans" // ERROR could not import + +// Map is an ordered map. +type Map[K, V any] struct { + root *node[K, V] + compare func(K, K) int +} + +// node is the type of a node in the binary tree. +type node[K, V any] struct { + key K + val V + left, right *node[K, V] +} + +// New returns a new map. +func New[K, V any](compare func(K, K) int) *Map[K, V] { + return &Map[K, V]{compare: compare} +} + +// find looks up key in the map, and returns either a pointer +// to the node holding key, or a pointer to the location where +// such a node would go. +func (m *Map[K, V]) find(key K) **node[K, V] { + pn := &m.root + for *pn != nil { + switch cmp := m.compare(key, (*pn).key); { + case cmp < 0: + pn = &(*pn).left + case cmp > 0: + pn = &(*pn).right + default: + return pn + } + } + return pn +} + +// Insert inserts a new key/value into the map. +// If the key is already present, the value is replaced. +// Returns true if this is a new key, false if already present. +func (m *Map[K, V]) Insert(key K, val V) bool { + pn := m.find(key) + if *pn != nil { + (*pn).val = val + return false + } + *pn = &node[K, V]{key: key, val: val} + return true +} + +// Find returns the value associated with a key, or zero if not present. +// The found result reports whether the key was found. +func (m *Map[K, V]) Find(key K) (V, bool) { + pn := m.find(key) + if *pn == nil { + var zero V // see the discussion of zero values, above + return zero, false + } + return (*pn).val, true +} + +// keyValue is a pair of key and value used when iterating. +type keyValue[K, V any] struct { + key K + val V +} + +// InOrder returns an iterator that does an in-order traversal of the map. +func (m *Map[K, V]) InOrder() *Iterator[K, V] { + sender, receiver := chans.Ranger[keyValue[K, V]]() + var f func(*node[K, V]) bool + f = func(n *node[K, V]) bool { + if n == nil { + return true + } + // Stop sending values if sender.Send returns false, + // meaning that nothing is listening at the receiver end. + return f(n.left) && + sender.Send(keyValue[K, V]{n.key, n.val}) && + f(n.right) + } + go func() { + f(m.root) + sender.Close() + }() + return &Iterator[K, V]{receiver} +} + +// Iterator is used to iterate over the map. +type Iterator[K, V any] struct { + r *chans.Receiver[keyValue[K, V]] +} + +// Next returns the next key and value pair, and a boolean indicating +// whether they are valid or whether we have reached the end. +func (it *Iterator[K, V]) Next() (K, V, bool) { + keyval, ok := it.r.Next() + if !ok { + var zerok K + var zerov V + return zerok, zerov, false + } + return keyval.key, keyval.val, true +} diff --git a/libgo/go/go/types/testdata/check/map2.go2 b/libgo/go/go/types/testdata/check/map2.go2 new file mode 100644 index 0000000..2833445 --- /dev/null +++ b/libgo/go/go/types/testdata/check/map2.go2 @@ -0,0 +1,146 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file is like map.go2, but instead if importing chans, it contains +// the necessary functionality at the end of the file. + +// Package orderedmap provides an ordered map, implemented as a binary tree. +package orderedmap + +// Map is an ordered map. +type Map[K, V any] struct { + root *node[K, V] + compare func(K, K) int +} + +// node is the type of a node in the binary tree. +type node[K, V any] struct { + key K + val V + left, right *node[K, V] +} + +// New returns a new map. +func New[K, V any](compare func(K, K) int) *Map[K, V] { + return &Map[K, V]{compare: compare} +} + +// find looks up key in the map, and returns either a pointer +// to the node holding key, or a pointer to the location where +// such a node would go. +func (m *Map[K, V]) find(key K) **node[K, V] { + pn := &m.root + for *pn != nil { + switch cmp := m.compare(key, (*pn).key); { + case cmp < 0: + pn = &(*pn).left + case cmp > 0: + pn = &(*pn).right + default: + return pn + } + } + return pn +} + +// Insert inserts a new key/value into the map. +// If the key is already present, the value is replaced. +// Returns true if this is a new key, false if already present. +func (m *Map[K, V]) Insert(key K, val V) bool { + pn := m.find(key) + if *pn != nil { + (*pn).val = val + return false + } + *pn = &node[K, V]{key: key, val: val} + return true +} + +// Find returns the value associated with a key, or zero if not present. +// The found result reports whether the key was found. +func (m *Map[K, V]) Find(key K) (V, bool) { + pn := m.find(key) + if *pn == nil { + var zero V // see the discussion of zero values, above + return zero, false + } + return (*pn).val, true +} + +// keyValue is a pair of key and value used when iterating. +type keyValue[K, V any] struct { + key K + val V +} + +// InOrder returns an iterator that does an in-order traversal of the map. +func (m *Map[K, V]) InOrder() *Iterator[K, V] { + sender, receiver := chans_Ranger[keyValue[K, V]]() + var f func(*node[K, V]) bool + f = func(n *node[K, V]) bool { + if n == nil { + return true + } + // Stop sending values if sender.Send returns false, + // meaning that nothing is listening at the receiver end. + return f(n.left) && + sender.Send(keyValue[K, V]{n.key, n.val}) && + f(n.right) + } + go func() { + f(m.root) + sender.Close() + }() + return &Iterator[K, V]{receiver} +} + +// Iterator is used to iterate over the map. +type Iterator[K, V any] struct { + r *chans_Receiver[keyValue[K, V]] +} + +// Next returns the next key and value pair, and a boolean indicating +// whether they are valid or whether we have reached the end. +func (it *Iterator[K, V]) Next() (K, V, bool) { + keyval, ok := it.r.Next() + if !ok { + var zerok K + var zerov V + return zerok, zerov, false + } + return keyval.key, keyval.val, true +} + +// chans + +func chans_Ranger[T any]() (*chans_Sender[T], *chans_Receiver[T]) + +// A sender is used to send values to a Receiver. +type chans_Sender[T any] struct { + values chan<- T + done <-chan bool +} + +func (s *chans_Sender[T]) Send(v T) bool { + select { + case s.values <- v: + return true + case <-s.done: + return false + } +} + +func (s *chans_Sender[T]) Close() { + close(s.values) +} + +type chans_Receiver[T any] struct { + values <-chan T + done chan<- bool +} + +func (r *chans_Receiver[T]) Next() (T, bool) { + v, ok := <-r.values + return v, ok +}
\ No newline at end of file diff --git a/libgo/go/go/types/testdata/methodsets.src b/libgo/go/go/types/testdata/check/methodsets.src index 9fb10de..9fb10de 100644 --- a/libgo/go/go/types/testdata/methodsets.src +++ b/libgo/go/go/types/testdata/check/methodsets.src diff --git a/libgo/go/go/types/testdata/shifts.src b/libgo/go/go/types/testdata/check/shifts.src index c9a38ae..4d3c59a 100644 --- a/libgo/go/go/types/testdata/shifts.src +++ b/libgo/go/go/types/testdata/check/shifts.src @@ -20,7 +20,7 @@ func shifts0() { // This depends on the exact spec wording which is not // done yet. // TODO(gri) revisit and adjust when spec change is done - _ = 1<<- /* ERROR "truncated to uint" */ 1.0 + _ = 1<<- /* ERROR "negative shift count" */ 1.0 _ = 1<<1075 /* ERROR "invalid shift" */ _ = 2.0<<1 _ = 1<<1.0 @@ -60,11 +60,13 @@ func shifts1() { _ uint = 1 << u _ float32 = 1 /* ERROR "must be integer" */ << u - // for issue 14822 + // issue #14822 + _ = 1<<( /* ERROR "overflows uint" */ 1<<64) _ = 1<<( /* ERROR "invalid shift count" */ 1<<64-1) - _ = 1<<( /* ERROR "invalid shift count" */ 1<<64) - _ = u<<(1<<63) // valid - _ = u<<(1<<64) // valid + + // issue #43697 + _ = u<<( /* ERROR "overflows uint" */ 1<<64) + _ = u<<(1<<64-1) ) } diff --git a/libgo/go/go/types/testdata/check/slices.go2 b/libgo/go/go/types/testdata/check/slices.go2 new file mode 100644 index 0000000..2bacd1c --- /dev/null +++ b/libgo/go/go/types/testdata/check/slices.go2 @@ -0,0 +1,68 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package slices implements various slice algorithms. +package slices + +// Map turns a []T1 to a []T2 using a mapping function. +func Map[T1, T2 any](s []T1, f func(T1) T2) []T2 { + r := make([]T2, len(s)) + for i, v := range s { + r[i] = f(v) + } + return r +} + +// Reduce reduces a []T1 to a single value using a reduction function. +func Reduce[T1, T2 any](s []T1, initializer T2, f func(T2, T1) T2) T2 { + r := initializer + for _, v := range s { + r = f(r, v) + } + return r +} + +// Filter filters values from a slice using a filter function. +func Filter[T any](s []T, f func(T) bool) []T { + var r []T + for _, v := range s { + if f(v) { + r = append(r, v) + } + } + return r +} + +// Example uses + +func limiter(x int) byte { + switch { + case x < 0: + return 0 + default: + return byte(x) + case x > 255: + return 255 + } +} + +var input = []int{-4, 68954, 7, 44, 0, -555, 6945} +var limited1 = Map[int, byte](input, limiter) +var limited2 = Map(input, limiter) // using type inference + +func reducer(x float64, y int) float64 { + return x + float64(y) +} + +var reduced1 = Reduce[int, float64](input, 0, reducer) +var reduced2 = Reduce(input, 1i /* ERROR overflows */, reducer) // using type inference +var reduced3 = Reduce(input, 1, reducer) // using type inference + +func filter(x int) bool { + return x&1 != 0 +} + +var filtered1 = Filter[int](input, filter) +var filtered2 = Filter(input, filter) // using type inference + diff --git a/libgo/go/go/types/testdata/stmt0.src b/libgo/go/go/types/testdata/check/stmt0.src index 1377729..76b6e70 100644 --- a/libgo/go/go/types/testdata/stmt0.src +++ b/libgo/go/go/types/testdata/check/stmt0.src @@ -86,11 +86,11 @@ func assignments1() { g := func(int, bool){} var m map[int]int - g(m[0]) /* ERROR "too few arguments" */ + g(m[0]) /* ERROR "not enough arguments" */ // assignments to _ _ = nil /* ERROR "use of untyped nil" */ - _ = 1 /* ERROR overflow */ <<1000 + _ = 1 << /* ERROR constant shift overflow */ 1000 (_) = 0 } @@ -143,11 +143,11 @@ func issue6487() { } func issue6766a() { - a, a /* ERROR redeclared */ := 1, 2 + a, a /* ERROR a repeated on left side of := */ := 1, 2 _ = a - a, b, b /* ERROR redeclared */ := 1, 2, 3 + a, b, b /* ERROR b repeated on left side of := */ := 1, 2, 3 _ = b - c, c /* ERROR redeclared */, b := 1, 2, 3 + c, c /* ERROR c repeated on left side of := */, b := 1, 2, 3 _ = c a, b := /* ERROR no new variables */ 1, 2 } @@ -886,7 +886,7 @@ func rangeloops1() { ee = e _ = ee } - for _ = range sc /* ERROR "cannot range over send-only channel" */ {} + for _ = range sc /* ERROR "cannot range over" */ {} for _ = range rc {} // constant strings diff --git a/libgo/go/go/types/testdata/stmt1.src b/libgo/go/go/types/testdata/check/stmt1.src index f79f920..f79f920 100644 --- a/libgo/go/go/types/testdata/stmt1.src +++ b/libgo/go/go/types/testdata/check/stmt1.src diff --git a/libgo/go/go/types/testdata/check/tinference.go2 b/libgo/go/go/types/testdata/check/tinference.go2 new file mode 100644 index 0000000..31338b33 --- /dev/null +++ b/libgo/go/go/types/testdata/check/tinference.go2 @@ -0,0 +1,108 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tinferenceB + +import "strconv" + +type any interface{} + +// TODO(rFindley) the below partially applied function types should probably +// not be permitted (spec question). + +func f0[A any, B interface{type C}, C interface{type D}, D interface{type A}](A, B, C, D) +func _() { + f := f0[string] + f("a", "b", "c", "d") + f0("a", "b", "c", "d") +} + +func f1[A any, B interface{type A}](A, B) +func _() { + f := f1[int] + f(int(0), int(0)) + f1(int(0), int(0)) +} + +func f2[A any, B interface{type []A}](A, B) +func _() { + f := f2[byte] + f(byte(0), []byte{}) + f2(byte(0), []byte{}) +} + +func f3[A any, B interface{type C}, C interface{type *A}](A, B, C) +func _() { + f := f3[int] + var x int + f(x, &x, &x) + f3(x, &x, &x) +} + +func f4[A any, B interface{type []C}, C interface{type *A}](A, B, C) +func _() { + f := f4[int] + var x int + f(x, []*int{}, &x) + f4(x, []*int{}, &x) +} + +func f5[A interface{type struct{b B; c C}}, B any, C interface{type *B}](x B) A +func _() { + x := f5(1.2) + var _ float64 = x.b + var _ float64 = *x.c +} + +func f6[A any, B interface{type struct{f []A}}](B) A +func _() { + x := f6(struct{f []string}{}) + var _ string = x +} + +// TODO(gri) Need to flag invalid recursive constraints. At the +// moment these cause infinite recursions and stack overflow. +// func f7[A interface{type B}, B interface{type A}]() + +// More realistic examples + +func Double[S interface{ type []E }, E interface{ type int, int8, int16, int32, int64 }](s S) S { + r := make(S, len(s)) + for i, v := range s { + r[i] = v + v + } + return r +} + +type MySlice []int + +var _ = Double(MySlice{1}) + +// From the draft design. + +type Setter[B any] interface { + Set(string) + type *B +} + +func FromStrings[T interface{}, PT Setter[T]](s []string) []T { + result := make([]T, len(s)) + for i, v := range s { + // The type of &result[i] is *T which is in the type list + // of Setter2, so we can convert it to PT. + p := PT(&result[i]) + // PT has a Set method. + p.Set(v) + } + return result +} + +type Settable int + +func (p *Settable) Set(s string) { + i, _ := strconv.Atoi(s) // real code should not ignore the error + *p = Settable(i) +} + +var _ = FromStrings[Settable]([]string{"1", "2"}) diff --git a/libgo/go/go/types/testdata/check/tmp.go2 b/libgo/go/go/types/testdata/check/tmp.go2 new file mode 100644 index 0000000..dae78ca --- /dev/null +++ b/libgo/go/go/types/testdata/check/tmp.go2 @@ -0,0 +1,17 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file is meant as "dumping ground" for debugging code. + +package p + +// fun test case +type C[P interface{m()}] P + +func (r C[P]) m() { r.m() } + +func f[T interface{m(); n()}](x T) { + y := C[T](x) + y.m() +} diff --git a/libgo/go/go/types/testdata/check/todos.go2 b/libgo/go/go/types/testdata/check/todos.go2 new file mode 100644 index 0000000..09e9b4c --- /dev/null +++ b/libgo/go/go/types/testdata/check/todos.go2 @@ -0,0 +1,22 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file is meant as "dumping ground" for tests +// of not yet implemented features. It will grow and +// shrink over time. + +package p + +// When using []'s instead of ()'s for type parameters +// we don't need extra parentheses for some composite +// literal types. +type T1[P any] struct{} +type T2[P, Q any] struct{} + +func _() { + _ = []T1[int]{} // ok if we use []'s + _ = [](T1[int]){} + _ = []T2[int, string]{} // ok if we use []'s + _ = [](T2[int, string]){} +} diff --git a/libgo/go/go/types/testdata/check/typeinst.go2 b/libgo/go/go/types/testdata/check/typeinst.go2 new file mode 100644 index 0000000..3184a4b --- /dev/null +++ b/libgo/go/go/types/testdata/check/typeinst.go2 @@ -0,0 +1,59 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type myInt int + +// Parameterized type declarations + +type T1[P any] P + +type T2[P any] struct { + f P + g int // int should still be in scope chain +} + +type List[P any] []P + +// Alias type declarations cannot have type parameters. Syntax error. +type A1[P any] = /* ERROR cannot be alias */ P + +// But an alias may refer to a generic, uninstantiated type. +type A2 = List +var _ A2[int] +var _ A2 /* ERROR without instantiation */ + +type A3 = List[int] +var _ A3 + +// Parameterized type instantiations + +var x int +type _ x /* ERROR not a type */ [int] + +type _ int /* ERROR not a generic type */ [] +type _ myInt /* ERROR not a generic type */ [] + +// TODO(gri) better error messages +type _ T1 /* ERROR got 0 arguments but 1 type parameters */ [] +type _ T1[x /* ERROR not a type */ ] +type _ T1 /* ERROR got 2 arguments but 1 type parameters */ [int, float32] + +var _ T2[int] = T2[int]{} + +var _ List[int] = []int{1, 2, 3} +var _ List[[]int] = [][]int{{1, 2, 3}} +var _ List[List[List[int]]] + +// Parameterized types containing parameterized types + +type T3[P any] List[P] + +var _ T3[int] = T3[int](List[int]{1, 2, 3}) + +// Self-recursive generic types are not permitted + +type self1[P any] self1 /* ERROR illegal cycle */ [P] +type self2[P any] *self2[P] // this is ok diff --git a/libgo/go/go/types/testdata/check/typeinst2.go2 b/libgo/go/go/types/testdata/check/typeinst2.go2 new file mode 100644 index 0000000..6e2104a --- /dev/null +++ b/libgo/go/go/types/testdata/check/typeinst2.go2 @@ -0,0 +1,256 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type List[E any] []E +var _ List[List[List[int]]] +var _ List[List[List[int]]] = []List[List[int]]{} + +type ( + T1[P1 any] struct { + f1 T2[P1, float32] + } + + T2[P2, P3 any] struct { + f2 P2 + f3 P3 + } +) + +func _() { + var x1 T1[int] + var x2 T2[int, float32] + + x1.f1.f2 = 0 + x1.f1 = x2 +} + +type T3[P any] T1[T2[P, P]] + +func _() { + var x1 T3[int] + var x2 T2[int, int] + x1.f1.f2 = x2 +} + +func f[P any] (x P) List[P] { + return List[P]{x} +} + +var ( + _ []int = f(0) + _ []float32 = f[float32](10) + _ List[complex128] = f(1i) + _ []List[int] = f(List[int]{}) + _ List[List[int]] = []List[int]{} + _ = []List[int]{} +) + +// Parameterized types with methods + +func (l List[E]) Head() (_ E, _ bool) { + if len(l) > 0 { + return l[0], true + } + return +} + +// A test case for instantiating types with other types (extracted from map.go2) + +type Pair[K any] struct { + key K +} + +type Receiver[T any] struct { + values T +} + +type Iterator[K any] struct { + r Receiver[Pair[K]] +} + +func Values [T any] (r Receiver[T]) T { + return r.values +} + +func (it Iterator[K]) Next() K { + return Values[Pair[K]](it.r).key +} + +// A more complex test case testing type bounds (extracted from linalg.go2 and reduced to essence) + +type NumericAbs[T any] interface { + Abs() T +} + +func AbsDifference[T NumericAbs[T]](x T) + +type OrderedAbs[T any] T + +func (a OrderedAbs[T]) Abs() OrderedAbs[T] + +func OrderedAbsDifference[T any](x T) { + AbsDifference(OrderedAbs[T](x)) +} + +// same code, reduced to essence + +func g[P interface{ m() P }](x P) + +type T4[P any] P + +func (_ T4[P]) m() T4[P] + +func _[Q any](x Q) { + g(T4[Q](x)) +} + +// Another test case that caused problems in the past + +type T5[_ interface { a() }, _ interface{}] struct{} + +type A[P any] struct{ x P } + +func (_ A[P]) a() {} + +var _ T5[A[int], int] + +// Invoking methods with parameterized receiver types uses +// type inference to determine the actual type arguments matching +// the receiver type parameters from the actual receiver argument. +// Go does implicit address-taking and dereferenciation depending +// on the actual receiver and the method's receiver type. To make +// type inference work, the type-checker matches "pointer-ness" +// of the actual receiver and the method's receiver type. +// The following code tests this mechanism. + +type R1[A any] struct{} +func (_ R1[A]) vm() +func (_ *R1[A]) pm() + +func _[T any](r R1[T], p *R1[T]) { + r.vm() + r.pm() + p.vm() + p.pm() +} + +type R2[A, B any] struct{} +func (_ R2[A, B]) vm() +func (_ *R2[A, B]) pm() + +func _[T any](r R2[T, int], p *R2[string, T]) { + r.vm() + r.pm() + p.vm() + p.pm() +} + +// An interface can (explicitly) declare at most one type list. +type _ interface { + m0() + type int, string, bool + type /* ERROR multiple type lists */ float32, float64 + m1() + m2() + type /* ERROR multiple type lists */ complex64, complex128 + type /* ERROR multiple type lists */ rune +} + +// Interface type lists may contain each type at most once. +// (If there are multiple lists, we assume the author intended +// for them to be all in a single list, and we report the error +// as well.) +type _ interface { + type int, int /* ERROR duplicate type int */ + type /* ERROR multiple type lists */ int /* ERROR duplicate type int */ +} + +type _ interface { + type struct{f int}, struct{g int}, struct /* ERROR duplicate type */ {f int} +} + +// Interface type lists can contain any type, incl. *Named types. +// Verify that we use the underlying type to compute the operational type. +type MyInt int +func add1[T interface{type MyInt}](x T) T { + return x + 1 +} + +type MyString string +func double[T interface{type MyInt, MyString}](x T) T { + return x + x +} + +// Embedding of interfaces with type lists leads to interfaces +// with type lists that are the intersection of the embedded +// type lists. + +type E0 interface { + type int, bool, string +} + +type E1 interface { + type int, float64, string +} + +type E2 interface { + type float64 +} + +type I0 interface { + E0 +} + +func f0[T I0]() +var _ = f0[int] +var _ = f0[bool] +var _ = f0[string] +var _ = f0[float64 /* ERROR does not satisfy I0 */ ] + +type I01 interface { + E0 + E1 +} + +func f01[T I01]() +var _ = f01[int] +var _ = f01[bool /* ERROR does not satisfy I0 */ ] +var _ = f01[string] +var _ = f01[float64 /* ERROR does not satisfy I0 */ ] + +type I012 interface { + E0 + E1 + E2 +} + +func f012[T I012]() +var _ = f012[int /* ERROR does not satisfy I012 */ ] +var _ = f012[bool /* ERROR does not satisfy I012 */ ] +var _ = f012[string /* ERROR does not satisfy I012 */ ] +var _ = f012[float64 /* ERROR does not satisfy I012 */ ] + +type I12 interface { + E1 + E2 +} + +func f12[T I12]() +var _ = f12[int /* ERROR does not satisfy I12 */ ] +var _ = f12[bool /* ERROR does not satisfy I12 */ ] +var _ = f12[string /* ERROR does not satisfy I12 */ ] +var _ = f12[float64] + +type I0_ interface { + E0 + type int +} + +func f0_[T I0_]() +var _ = f0_[int] +var _ = f0_[bool /* ERROR does not satisfy I0_ */ ] +var _ = f0_[string /* ERROR does not satisfy I0_ */ ] +var _ = f0_[float64 /* ERROR does not satisfy I0_ */ ] diff --git a/libgo/go/go/types/testdata/check/typeparams.go2 b/libgo/go/go/types/testdata/check/typeparams.go2 new file mode 100644 index 0000000..d95e02e --- /dev/null +++ b/libgo/go/go/types/testdata/check/typeparams.go2 @@ -0,0 +1,433 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +// import "io" // for type assertion tests + +// The predeclared identifier "any" is only visible as a constraint +// in a type parameter list. +var _ any // ERROR undeclared +func _[_ any /* ok here */ , _ interface{any /* ERROR undeclared */ }](any /* ERROR undeclared */ ) { + var _ any /* ERROR undeclared */ +} + +func identity[T any](x T) T { return x } + +func _[_ any](x int) int +func _[T any](T /* ERROR redeclared */ T)() +func _[T, T /* ERROR redeclared */ any]() + +// Constraints (incl. any) may be parenthesized. +func _[_ (any)]() {} +func _[_ (interface{})]() {} + +func reverse[T any](list []T) []T { + rlist := make([]T, len(list)) + i := len(list) + for _, x := range list { + i-- + rlist[i] = x + } + return rlist +} + +var _ = reverse /* ERROR cannot use generic function reverse */ +var _ = reverse[int, float32 /* ERROR got 2 type arguments */ ] ([]int{1, 2, 3}) +var _ = reverse[int]([ /* ERROR cannot use */ ]float32{1, 2, 3}) +var f = reverse[chan int] +var _ = f(0 /* ERROR cannot use 0 .* as \[\]chan int */ ) + +func swap[A, B any](a A, b B) (B, A) { return b, a } + +var _ = swap /* ERROR single value is expected */ [int, float32](1, 2) +var f32, i = swap[int, float32](swap[float32, int](1, 2)) +var _ float32 = f32 +var _ int = i + +func swapswap[A, B any](a A, b B) (A, B) { + return swap[B, A](b, a) +} + +type F[A, B any] func(A, B) (B, A) + +func min[T interface{ type int }](x, y T) T { + if x < y { + return x + } + return y +} + +func _[T interface{type int, float32}](x, y T) bool { return x < y } +func _[T any](x, y T) bool { return x /* ERROR cannot compare */ < y } +func _[T interface{type int, float32, bool}](x, y T) bool { return x /* ERROR cannot compare */ < y } + +func _[T C1[T]](x, y T) bool { return x /* ERROR cannot compare */ < y } +func _[T C2[T]](x, y T) bool { return x < y } + +type C1[T any] interface{} +type C2[T any] interface{ type int, float32 } + +func new[T any]() *T { + var x T + return &x +} + +var _ = new /* ERROR cannot use generic function new */ +var _ *int = new[int]() + +func _[T any](map[T /* ERROR incomparable map key type T \(missing comparable constraint\) */]int) // w/o constraint we don't know if T is comparable + +func f1[T1 any](struct{T1}) int +var _ = f1[int](struct{T1}{}) +type T1 = int + +func f2[t1 any](struct{t1; x float32}) int +var _ = f2[t1](struct{t1; x float32}{}) +type t1 = int + + +func f3[A, B, C any](A, struct{x B}, func(A, struct{x B}, *C)) int + +var _ = f3[int, rune, bool](1, struct{x rune}{}, nil) + +// indexing + +func _[T any] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } +func _[T interface{ type int }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } +func _[T interface{ type string }] (x T, i int) { _ = x[i] } +func _[T interface{ type []int }] (x T, i int) { _ = x[i] } +func _[T interface{ type [10]int, *[20]int, map[int]int }] (x T, i int) { _ = x[i] } +func _[T interface{ type string, []byte }] (x T, i int) { _ = x[i] } +func _[T interface{ type []int, [1]rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } +func _[T interface{ type string, []rune }] (x T, i int) { _ = x /* ERROR "cannot index" */ [i] } + +// indexing with various combinations of map types in type lists (see issue #42616) +func _[T interface{ type []E, map[int]E }, E any](x T, i int) { _ = x[i] } +func _[T interface{ type []E }, E any](x T, i int) { _ = &x[i] } +func _[T interface{ type map[int]E }, E any](x T, i int) { _, _ = x[i] } // comma-ok permitted +func _[T interface{ type []E, map[int]E }, E any](x T, i int) { _ = &x /* ERROR cannot take address */ [i] } +func _[T interface{ type []E, map[int]E, map[uint]E }, E any](x T, i int) { _ = x /* ERROR cannot index */ [i] } // different map element types +func _[T interface{ type []E, map[string]E }, E any](x T, i int) { _ = x[i /* ERROR cannot use i */ ] } + +// slicing +// TODO(gri) implement this + +func _[T interface{ type string }] (x T, i, j, k int) { _ = x /* ERROR invalid operation */ [i:j:k] } + +// len/cap built-ins + +func _[T any](x T) { _ = len(x /* ERROR invalid argument */ ) } +func _[T interface{ type int }](x T) { _ = len(x /* ERROR invalid argument */ ) } +func _[T interface{ type string, []byte, int }](x T) { _ = len(x /* ERROR invalid argument */ ) } +func _[T interface{ type string }](x T) { _ = len(x) } +func _[T interface{ type [10]int }](x T) { _ = len(x) } +func _[T interface{ type []byte }](x T) { _ = len(x) } +func _[T interface{ type map[int]int }](x T) { _ = len(x) } +func _[T interface{ type chan int }](x T) { _ = len(x) } +func _[T interface{ type string, []byte, chan int }](x T) { _ = len(x) } + +func _[T any](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ type int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ type string, []byte, int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ type string }](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ type [10]int }](x T) { _ = cap(x) } +func _[T interface{ type []byte }](x T) { _ = cap(x) } +func _[T interface{ type map[int]int }](x T) { _ = cap(x /* ERROR invalid argument */ ) } +func _[T interface{ type chan int }](x T) { _ = cap(x) } +func _[T interface{ type []byte, chan int }](x T) { _ = cap(x) } + +// range iteration + +func _[T interface{}](x T) { + for range x /* ERROR cannot range */ {} +} + +func _[T interface{ type string, []string }](x T) { + for range x {} + for i := range x { _ = i } + for i, _ := range x { _ = i } + for i, e := range x /* ERROR must have the same element type */ { _ = i } + for _, e := range x /* ERROR must have the same element type */ {} + var e rune + _ = e + for _, (e) = range x /* ERROR must have the same element type */ {} +} + + +func _[T interface{ type string, []rune, map[int]rune }](x T) { + for _, e := range x { _ = e } + for i, e := range x { _ = i; _ = e } +} + +func _[T interface{ type string, []rune, map[string]rune }](x T) { + for _, e := range x { _ = e } + for i, e := range x /* ERROR must have the same key type */ { _ = e } +} + +func _[T interface{ type string, chan int }](x T) { + for range x {} + for i := range x { _ = i } + for i, _ := range x { _ = i } // TODO(gri) should get an error here: channels only return one value +} + +func _[T interface{ type string, chan<-int }](x T) { + for i := range x /* ERROR send-only channel */ { _ = i } +} + +// type inference checks + +var _ = new /* ERROR cannot infer T */ () + +func f4[A, B, C any](A, B) C + +var _ = f4 /* ERROR cannot infer C */ (1, 2) +var _ = f4[int, float32, complex128](1, 2) + +func f5[A, B, C any](A, []*B, struct{f []C}) int + +var _ = f5[int, float32, complex128](0, nil, struct{f []complex128}{}) +var _ = f5 /* ERROR cannot infer */ (0, nil, struct{f []complex128}{}) +var _ = f5(0, []*float32{new[float32]()}, struct{f []complex128}{}) + +func f6[A any](A, []A) int + +var _ = f6(0, nil) + +func f6nil[A any](A) int + +var _ = f6nil /* ERROR cannot infer */ (nil) + +// type inference with variadic functions + +func f7[T any](...T) T + +var _ int = f7 /* ERROR cannot infer T */ () +var _ int = f7(1) +var _ int = f7(1, 2) +var _ int = f7([]int{}...) +var _ int = f7 /* ERROR cannot use */ ([]float64{}...) +var _ float64 = f7([]float64{}...) +var _ = f7[float64](1, 2.3) +var _ = f7(float64(1), 2.3) +var _ = f7(1, 2.3 /* ERROR does not match */ ) +var _ = f7(1.2, 3 /* ERROR does not match */ ) + +func f8[A, B any](A, B, ...B) int + +var _ = f8(1) /* ERROR not enough arguments */ +var _ = f8(1, 2.3) +var _ = f8(1, 2.3, 3.4, 4.5) +var _ = f8(1, 2.3, 3.4, 4 /* ERROR does not match */ ) +var _ = f8[int, float64](1, 2.3, 3.4, 4) + +var _ = f8[int, float64](0, 0, nil...) // test case for #18268 + +// init functions cannot have type parameters + +func init() {} +func init[/* ERROR func init must have no type parameters */ _ any]() {} +func init[/* ERROR func init must have no type parameters */ P any]() {} + +type T struct {} + +func (T) m1() {} +func (T) m2[ /* ERROR methods cannot have type parameters */ _ any]() {} +func (T) m3[ /* ERROR methods cannot have type parameters */ P any]() {} + +// type inference across parameterized types + +type S1[P any] struct { f P } + +func f9[P any](x S1[P]) + +func _() { + f9[int](S1[int]{42}) + f9(S1[int]{42}) +} + +type S2[A, B, C any] struct{} + +func f10[X, Y, Z any](a S2[X, int, Z], b S2[X, Y, bool]) + +func _[P any]() { + f10[int, float32, string](S2[int, int, string]{}, S2[int, float32, bool]{}) + f10(S2[int, int, string]{}, S2[int, float32, bool]{}) + f10(S2[P, int, P]{}, S2[P, float32, bool]{}) +} + +// corner case for type inference +// (was bug: after instanting f11, the type-checker didn't mark f11 as non-generic) + +func f11[T any]() + +func _() { + f11[int]() +} + +// the previous example was extracted from + +func f12[T interface{m() T}]() + +type A[T any] T + +func (a A[T]) m() A[T] + +func _[T any]() { + f12[A[T]]() +} + +// method expressions + +func (_ S1[P]) m() + +func _() { + m := S1[int].m + m(struct { f int }{42}) +} + +func _[T any] (x T) { + m := S1[T].m + m(S1[T]{x}) +} + +// type parameters in methods (generalization) + +type R0 struct{} + +func (R0) _[ /* ERROR methods cannot have type parameters */ T any](x T) +func (R0 /* ERROR invalid receiver */ ) _[ /* ERROR methods cannot have type parameters */ R0 any]() // scope of type parameters starts at "func" + +type R1[A, B any] struct{} + +func (_ R1[A, B]) m0(A, B) +func (_ R1[A, B]) m1[ /* ERROR methods cannot have type parameters */ T any](A, B, T) T +func (_ R1 /* ERROR not a generic type */ [R1, _]) _() +func (_ R1[A, B]) _[ /* ERROR methods cannot have type parameters */ A /* ERROR redeclared */ any](B) + +func _() { + var r R1[int, string] + r.m1[rune](42, "foo", 'a') + r.m1[rune](42, "foo", 1.2 /* ERROR cannot use .* as rune .* \(truncated\) */) + r.m1(42, "foo", 1.2) // using type inference + var _ float64 = r.m1(42, "foo", 1.2) +} + +type I1[A any] interface { + m1(A) +} + +var _ I1[int] = r1[int]{} + +type r1[T any] struct{} + +func (_ r1[T]) m1(T) + +type I2[A, B any] interface { + m1(A) + m2(A) B +} + +var _ I2[int, float32] = R2[int, float32]{} + +type R2[P, Q any] struct{} + +func (_ R2[X, Y]) m1(X) +func (_ R2[X, Y]) m2(X) Y + +// type assertions and type switches over generic types +// NOTE: These are currently disabled because it's unclear what the correct +// approach is, and one can always work around by assigning the variable to +// an interface first. + +// // ReadByte1 corresponds to the ReadByte example in the draft design. +// func ReadByte1[T io.Reader](r T) (byte, error) { +// if br, ok := r.(io.ByteReader); ok { +// return br.ReadByte() +// } +// var b [1]byte +// _, err := r.Read(b[:]) +// return b[0], err +// } +// +// // ReadBytes2 is like ReadByte1 but uses a type switch instead. +// func ReadByte2[T io.Reader](r T) (byte, error) { +// switch br := r.(type) { +// case io.ByteReader: +// return br.ReadByte() +// } +// var b [1]byte +// _, err := r.Read(b[:]) +// return b[0], err +// } +// +// // type assertions and type switches over generic types are strict +// type I3 interface { +// m(int) +// } +// +// type I4 interface { +// m() int // different signature from I3.m +// } +// +// func _[T I3](x I3, p T) { +// // type assertions and type switches over interfaces are not strict +// _ = x.(I4) +// switch x.(type) { +// case I4: +// } +// +// // type assertions and type switches over generic types are strict +// _ = p /* ERROR cannot have dynamic type I4 */.(I4) +// switch p.(type) { +// case I4 /* ERROR cannot have dynamic type I4 */ : +// } +// } + +// type assertions and type switches over generic types lead to errors for now + +func _[T any](x T) { + _ = x /* ERROR not an interface */ .(int) + switch x /* ERROR not an interface */ .(type) { + } + + // work-around + var t interface{} = x + _ = t.(int) + switch t.(type) { + } +} + +func _[T interface{type int}](x T) { + _ = x /* ERROR not an interface */ .(int) + switch x /* ERROR not an interface */ .(type) { + } + + // work-around + var t interface{} = x + _ = t.(int) + switch t.(type) { + } +} + +// error messages related to type bounds mention those bounds +type C[P any] interface{} + +func _[P C[P]] (x P) { + x.m /* ERROR x.m undefined */ () +} + +type I interface {} + +func _[P I] (x P) { + x.m /* ERROR interface I has no method m */ () +} + +func _[P interface{}] (x P) { + x.m /* ERROR type bound for P has no method m */ () +} + +func _[P any] (x P) { + x.m /* ERROR type bound for P has no method m */ () +} diff --git a/libgo/go/go/types/testdata/vardecl.src b/libgo/go/go/types/testdata/check/vardecl.src index 54f5ef1..54f5ef1 100644 --- a/libgo/go/go/types/testdata/vardecl.src +++ b/libgo/go/go/types/testdata/check/vardecl.src diff --git a/libgo/go/go/types/testdata/examples/functions.go2 b/libgo/go/go/types/testdata/examples/functions.go2 new file mode 100644 index 0000000..a053471 --- /dev/null +++ b/libgo/go/go/types/testdata/examples/functions.go2 @@ -0,0 +1,214 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file shows some examples of type-parameterized functions. + +package p + +// Reverse is a generic function that takes a []T argument and +// reverses that slice in place. +func Reverse[T any](list []T) { + i := 0 + j := len(list)-1 + for i < j { + list[i], list[j] = list[j], list[i] + i++ + j-- + } +} + +func _() { + // Reverse can be called with an explicit type argument. + Reverse[int](nil) + Reverse[string]([]string{"foo", "bar"}) + Reverse[struct{x, y int}]([]struct{x, y int}{{1, 2}, {2, 3}, {3, 4}}) + + // Since the type parameter is used for an incoming argument, + // it can be inferred from the provided argument's type. + Reverse([]string{"foo", "bar"}) + Reverse([]struct{x, y int}{{1, 2}, {2, 3}, {3, 4}}) + + // But the incoming argument must have a type, even if it's a + // default type. An untyped nil won't work. + // Reverse(nil) // this won't type-check + + // A typed nil will work, though. + Reverse([]int(nil)) +} + +// Certain functions, such as the built-in `new` could be written using +// type parameters. +func new[T any]() *T { + var x T + return &x +} + +// When calling our own `new`, we need to pass the type parameter +// explicitly since there is no (value) argument from which the +// result type could be inferred. We don't try to infer the +// result type from the assignment to keep things simple and +// easy to understand. +var _ = new[int]() +var _ *float64 = new[float64]() // the result type is indeed *float64 + +// A function may have multiple type parameters, of course. +func foo[A, B, C any](a A, b []B, c *C) B { + // do something here + return b[0] +} + +// As before, we can pass type parameters explicitly. +var s = foo[int, string, float64](1, []string{"first"}, new[float64]()) + +// Or we can use type inference. +var _ float64 = foo(42, []float64{1.0}, &s) + +// Type inference works in a straight-forward manner even +// for variadic functions. +func variadic[A, B any](A, B, ...B) int + +// var _ = variadic(1) // ERROR not enough arguments +var _ = variadic(1, 2.3) +var _ = variadic(1, 2.3, 3.4, 4.5) +var _ = variadic[int, float64](1, 2.3, 3.4, 4) + +// Type inference also works in recursive function calls where +// the inferred type is the type parameter of the caller. +func f1[T any](x T) { + f1(x) +} + +func f2a[T any](x, y T) { + f2a(x, y) +} + +func f2b[T any](x, y T) { + f2b(y, x) +} + +func g2a[P, Q any](x P, y Q) { + g2a(x, y) +} + +func g2b[P, Q any](x P, y Q) { + g2b(y, x) +} + +// Here's an example of a recursive function call with variadic +// arguments and type inference inferring the type parameter of +// the caller (i.e., itself). +func max[T interface{ type int }](x ...T) T { + var x0 T + if len(x) > 0 { + x0 = x[0] + } + if len(x) > 1 { + x1 := max(x[1:]...) + if x1 > x0 { + return x1 + } + } + return x0 +} + +// When inferring channel types, the channel direction is ignored +// for the purpose of type inference. Once the type has been in- +// fered, the usual parameter passing rules are applied. +// Thus even if a type can be inferred successfully, the function +// call may not be valid. + +func fboth[T any](chan T) +func frecv[T any](<-chan T) +func fsend[T any](chan<- T) + +func _() { + var both chan int + var recv <-chan int + var send chan<-int + + fboth(both) + fboth(recv /* ERROR cannot use */ ) + fboth(send /* ERROR cannot use */ ) + + frecv(both) + frecv(recv) + frecv(send /* ERROR cannot use */ ) + + fsend(both) + fsend(recv /* ERROR cannot use */) + fsend(send) +} + +func ffboth[T any](func(chan T)) +func ffrecv[T any](func(<-chan T)) +func ffsend[T any](func(chan<- T)) + +func _() { + var both func(chan int) + var recv func(<-chan int) + var send func(chan<- int) + + ffboth(both) + ffboth(recv /* ERROR cannot use */ ) + ffboth(send /* ERROR cannot use */ ) + + ffrecv(both /* ERROR cannot use */ ) + ffrecv(recv) + ffrecv(send /* ERROR cannot use */ ) + + ffsend(both /* ERROR cannot use */ ) + ffsend(recv /* ERROR cannot use */ ) + ffsend(send) +} + +// When inferring elements of unnamed composite parameter types, +// if the arguments are defined types, use their underlying types. +// Even though the matching types are not exactly structurally the +// same (one is a type literal, the other a named type), because +// assignment is permitted, parameter passing is permitted as well, +// so type inference should be able to handle these cases well. + +func g1[T any]([]T) +func g2[T any]([]T, T) +func g3[T any](*T, ...T) + +func _() { + type intSlize []int + g1([]int{}) + g1(intSlize{}) + g2(nil, 0) + + type myString string + var s1 string + g3(nil, "1", myString("2"), "3") + g3(&s1, "1", myString /* ERROR does not match */ ("2"), "3") + + type myStruct struct{x int} + var s2 myStruct + g3(nil, struct{x int}{}, myStruct{}) + g3(&s2, struct{x int}{}, myStruct{}) + g3(nil, myStruct{}, struct{x int}{}) + g3(&s2, myStruct{}, struct{x int}{}) +} + +// Here's a realistic example. + +func append[T any](s []T, t ...T) []T + +func _() { + var f func() + type Funcs []func() + var funcs Funcs + _ = append(funcs, f) +} + +// Generic type declarations cannot have empty type parameter lists +// (that would indicate a slice type). Thus, generic functions cannot +// have empty type parameter lists, either. This is a syntax error. + +func h[] /* ERROR empty type parameter list */ () + +func _() { + h /* ERROR cannot index */ [] /* ERROR operand */ () +} diff --git a/libgo/go/go/types/testdata/examples/inference.go2 b/libgo/go/go/types/testdata/examples/inference.go2 new file mode 100644 index 0000000..b4f3369 --- /dev/null +++ b/libgo/go/go/types/testdata/examples/inference.go2 @@ -0,0 +1,101 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file shows some examples of type inference. + +package p + +type Ordered interface { + type int, float64, string +} + +func min[T Ordered](x, y T) T + +func _() { + // min can be called with explicit instantiation. + _ = min[int](1, 2) + + // Alternatively, the type argument can be inferred from + // one of the arguments. Untyped arguments will be considered + // last. + var x int + _ = min(x, x) + _ = min(x, 1) + _ = min(x, 1.0) + _ = min(1, 2) + _ = min(1, 2.3 /* ERROR default type float64 .* does not match */ ) + + var y float64 + _ = min(1, y) + _ = min(1.2, y) + _ = min(1.2, 3.4) + _ = min(1.2, 3 /* ERROR default type int .* does not match */ ) + + var s string + _ = min(s, "foo") + _ = min("foo", "bar") +} + +func mixed[T1, T2, T3 any](T1, T2, T3) + +func _() { + // mixed can be called with explicit instantiation. + mixed[int, string, bool](0, "", false) + + // Alternatively, partial type arguments may be provided + // (from left to right), and the other may be inferred. + mixed[int, string](0, "", false) + mixed[int](0, "", false) + mixed(0, "", false) + + // Provided type arguments always take precedence over + // inferred types. + mixed[int, string](1.1 /* ERROR cannot use 1.1 */ , "", false) +} + +func related1[Slice interface{type []Elem}, Elem any](s Slice, e Elem) + +func _() { + // related1 can be called with explicit instantiation. + var si []int + related1[[]int, int](si, 0) + + // Alternatively, the 2nd type argument can be inferred + // from the first one through constraint type inference. + var ss []string + _ = related1[[]string] + related1[[]string](ss, "foo") + + // A type argument inferred from another explicitly provided + // type argument overrides whatever value argument type is given. + related1[[]string](ss, 0 /* ERROR cannot use 0 */ ) + + // A type argument may be inferred from a value argument + // and then help infer another type argument via constraint + // type inference. + related1(si, 0) + related1(si, "foo" /* ERROR cannot use "foo" */ ) +} + +func related2[Elem any, Slice interface{type []Elem}](e Elem, s Slice) + +func _() { + // related2 can be called with explicit instantiation. + var si []int + related2[int, []int](0, si) + + // Alternatively, the 2nd type argument can be inferred + // from the first one through constraint type inference. + var ss []string + _ = related2[string] + related2[string]("foo", ss) + + // A type argument may be inferred from a value argument + // and then help infer another type argument via constraint + // type inference. Untyped arguments are always considered + // last. + related2(1.2, []float64{}) + related2(1.0, []int{}) + related2 /* ERROR does not satisfy */ (float64(1.0), []int{}) +} diff --git a/libgo/go/go/types/testdata/examples/methods.go2 b/libgo/go/go/types/testdata/examples/methods.go2 new file mode 100644 index 0000000..76c6539 --- /dev/null +++ b/libgo/go/go/types/testdata/examples/methods.go2 @@ -0,0 +1,96 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file shows some examples of methods on type-parameterized types. + +package p + +// Parameterized types may have methods. +type T1[A any] struct{ a A } + +// When declaring a method for a parameterized type, the "instantiated" +// receiver type acts as an implicit declaration of the type parameters +// for the receiver type. In the example below, method m1 on type T1 has +// the receiver type T1[A] which declares the type parameter A for use +// with this method. That is, within the method m1, A stands for the +// actual type argument provided to an instantiated T1. +func (t T1[A]) m1() A { return t.a } + +// For instance, if T1 is instantiated with the type int, the type +// parameter A in m1 assumes that type (int) as well and we can write +// code like this: +var x T1[int] +var _ int = x.m1() + +// Because the type parameter provided to a parameterized receiver type +// is declared through that receiver declaration, it must be an identifier. +// It cannot possibly be some other type because the receiver type is not +// instantiated with concrete types, it is standing for the parameterized +// receiver type. +func (t T1[[ /* ERROR must be an identifier */ ]int]) m2() {} + +// Note that using what looks like a predeclared identifier, say int, +// as type parameter in this situation is deceptive and considered bad +// style. In m3 below, int is the name of the local receiver type parameter +// and it shadows the predeclared identifier int which then cannot be used +// anymore as expected. +// This is no different from locally redelaring a predeclared identifier +// and usually should be avoided. There are some notable exceptions; e.g., +// sometimes it makes sense to use the identifier "copy" which happens to +// also be the name of a predeclared built-in function. +func (t T1[int]) m3() { var _ int = 42 /* ERROR cannot use 42 .* as int */ } + +// The names of the type parameters used in a parameterized receiver +// type don't have to match the type parameter names in the declaration +// of the type used for the receiver. In our example, even though T1 is +// declared with type parameter named A, methods using that receiver type +// are free to use their own name for that type parameter. That is, the +// name of type parameters is always local to the declaration where they +// are introduced. In our example we can write a method m2 and use the +// name X instead of A for the type parameter w/o any difference. +func (t T1[X]) m4() X { return t.a } + +// If the receiver type is parameterized, type parameters must always be +// provided: this simply follows from the general rule that a parameterized +// type must be instantiated before it can be used. A method receiver +// declaration using a parameterized receiver type is no exception. It is +// simply that such receiver type expressions perform two tasks simultaneously: +// they declare the (local) type parameters and then use them to instantiate +// the receiver type. Forgetting to provide a type parameter leads to an error. +func (t T1 /* ERROR generic type .* without instantiation */ ) m5() {} + +// However, sometimes we don't need the type parameter, and thus it is +// inconvenient to have to choose a name. Since the receiver type expression +// serves as a declaration for its type parameters, we are free to choose the +// blank identifier: +func (t T1[_]) m6() {} + +// Naturally, these rules apply to any number of type parameters on the receiver +// type. Here are some more complex examples. +type T2[A, B, C any] struct { + a A + b B + c C +} + +// Naming of the type parameters is local and has no semantic impact: +func (t T2[A, B, C]) m1() (A, B, C) { return t.a, t.b, t.c } +func (t T2[C, B, A]) m2() (C, B, A) { return t.a, t.b, t.c } +func (t T2[X, Y, Z]) m3() (X, Y, Z) { return t.a, t.b, t.c } + +// Type parameters may be left blank if they are not needed: +func (t T2[A, _, C]) m4() (A, C) { return t.a, t.c } +func (t T2[_, _, X]) m5() X { return t.c } +func (t T2[_, _, _]) m6() {} + +// As usual, blank names may be used for any object which we don't care about +// using later. For instance, we may write an unnamed method with a receiver +// that cannot be accessed: +func (_ T2[_, _, _]) _() int { return 42 } + +// Because a receiver parameter list is simply a parameter list, we can +// leave the receiver argument away for receiver types. +type T0 struct{} +func (T0) _() {} +func (T1[A]) _() {} diff --git a/libgo/go/go/types/testdata/examples/types.go2 b/libgo/go/go/types/testdata/examples/types.go2 new file mode 100644 index 0000000..59c8804 --- /dev/null +++ b/libgo/go/go/types/testdata/examples/types.go2 @@ -0,0 +1,286 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file shows some examples of generic types. + +package p + +// List is just what it says - a slice of E elements. +type List[E any] []E + +// A generic (parameterized) type must always be instantiated +// before it can be used to designate the type of a variable +// (including a struct field, or function parameter); though +// for the latter cases, the provided type may be another type +// parameter. So: +var _ List[byte] = []byte{} + +// A generic binary tree might be declared as follows. +type Tree[E any] struct { + left, right *Tree[E] + payload E +} + +// A simple instantiation of Tree: +var root1 Tree[int] + +// The actual type parameter provided may be a generic type itself: +var root2 Tree[List[int]] + +// A couple of more complex examples. +// We don't need extra parentheses around the element type of the slices on +// the right (unlike when we use ()'s rather than []'s for type parameters). +var _ List[List[int]] = []List[int]{} +var _ List[List[List[Tree[int]]]] = []List[List[Tree[int]]]{} + +// Type parameters act like type aliases when used in generic types +// in the sense that we can "emulate" a specific type instantiation +// with type aliases. +type T1[P any] struct { + f P +} + +type T2[P any] struct { + f struct { + g P + } +} + +var x1 T1[struct{ g int }] +var x2 T2[int] + +func _() { + // This assignment is invalid because the types of x1, x2 are T1(...) + // and T2(...) respectively, which are two different defined types. + x1 = x2 // ERROR assignment + + // This assignment is valid because the types of x1.f and x2.f are + // both struct { g int }; the type parameters act like type aliases + // and their actual names don't come into play here. + x1.f = x2.f +} + +// We can verify this behavior using type aliases instead: +type T1a struct { + f A1 +} +type A1 = struct { g int } + +type T2a struct { + f struct { + g A2 + } +} +type A2 = int + +var x1a T1a +var x2a T2a + +func _() { + x1a = x2a // ERROR assignment + x1a.f = x2a.f +} + +// Another interesting corner case are generic types that don't use +// their type arguments. For instance: +type T[P any] struct{} + +var xint T[int] +var xbool T[bool] + +// Are these two variables of the same type? After all, their underlying +// types are identical. We consider them to be different because each type +// instantiation creates a new named type, in this case T<int> and T<bool> +// even if their underlying types are identical. This is sensible because +// we might still have methods that have different signatures or behave +// differently depending on the type arguments, and thus we can't possibly +// consider such types identical. Consequently: +func _() { + xint = xbool // ERROR assignment +} + +// Generic types cannot be used without instantiation. +var _ T // ERROR cannot use generic type T + +// In type context, generic (parameterized) types cannot be parenthesized before +// being instantiated. See also NOTES entry from 12/4/2019. +var _ (T /* ERROR cannot use generic type T */ )[ /* ERROR expected ';' */ int] + +// All types may be parameterized, including interfaces. +type I1[T any] interface{ + m1(T) +} + +// There is no such thing as a variadic generic type. +type _[T ... /* ERROR invalid use of ... */ interface{}] struct{} + +// Generic interfaces may be embedded as one would expect. +type I2 interface { + I1(int) // method! + I1[string] // embedded I1 +} + +func _() { + var x I2 + x.I1(0) + x.m1("foo") +} + +type I0 interface { + m0() +} + +type I3 interface { + I0 + I1[bool] + m(string) +} + +func _() { + var x I3 + x.m0() + x.m1(true) + x.m("foo") +} + +// We accept parenthesized embedded struct fields so we can distinguish between +// a named field with a parenthesized type foo (T) and an embedded parameterized +// type (foo(T)), similarly to interface embedding. +// They still need to be valid embedded types after the parentheses are stripped +// (i.e., in contrast to interfaces, we cannot embed a struct literal). The name +// of the embedded field is derived as before, after stripping parentheses. +// (7/14/2020: See comment above. We probably will revert this generalized ability +// if we go with [] for type parameters.) +type _ struct { + int8 + *int16 + *List[int] + + int8 /* ERROR int8 redeclared */ + * /* ERROR List redeclared */ List[int] +} + +// It's possible to declare local types whose underlying types +// are type parameters. As with ordinary type definitions, the +// types underlying properties are "inherited" but the methods +// are not. +func _[T interface{ m(); type int }]() { + type L T + var x L + + // m is not defined on L (it is not "inherited" from + // its underlying type). + x.m /* ERROR x.m undefined */ () + + // But the properties of T, such that as that it supports + // the operations of the types given by its type bound, + // are also the properties of L. + x++ + _ = x - x + + // On the other hand, if we define a local alias for T, + // that alias stands for T as expected. + type A = T + var y A + y.m() + _ = y < 0 +} + +// As a special case, an explicit type argument may be omitted +// from a type parameter bound if the type bound expects exactly +// one type argument. In that case, the type argument is the +// respective type parameter to which the type bound applies. +// Note: We may not permit this syntactic sugar at first. +// Note: This is now disabled. All examples below are adjusted. +type Adder[T any] interface { + Add(T) T +} + +// We don't need to explicitly instantiate the Adder bound +// if we have exactly one type parameter. +func Sum[T Adder[T]](list []T) T { + var sum T + for _, x := range list { + sum = sum.Add(x) + } + return sum +} + +// Valid and invalid variations. +type B0 interface {} +type B1[_ any] interface{} +type B2[_, _ any] interface{} + +func _[T1 B0]() +func _[T1 B1[T1]]() +func _[T1 B2 /* ERROR cannot use generic type .* without instantiation */ ]() + +func _[T1, T2 B0]() +func _[T1 B1[T1], T2 B1[T2]]() +func _[T1, T2 B2 /* ERROR cannot use generic type .* without instantiation */ ]() + +func _[T1 B0, T2 B1[T2]]() // here B1 applies to T2 + +// When the type argument is left away, the type bound is +// instantiated for each type parameter with that type +// parameter. +// Note: We may not permit this syntactic sugar at first. +func _[A Adder[A], B Adder[B], C Adder[A]]() { + var a A // A's type bound is Adder[A] + a = a.Add(a) + var b B // B's type bound is Adder[B] + b = b.Add(b) + var c C // C's type bound is Adder[A] + a = c.Add(a) +} + +// The type of variables (incl. parameters and return values) cannot +// be an interface with type constraints or be/embed comparable. +type I interface { + type int +} + +var ( + _ interface /* ERROR contains type constraints */ {type int} + _ I /* ERROR contains type constraints */ +) + +func _(I /* ERROR contains type constraints */ ) +func _(x, y, z I /* ERROR contains type constraints */ ) +func _() I /* ERROR contains type constraints */ + +func _() { + var _ I /* ERROR contains type constraints */ +} + +type C interface { + comparable +} + +var _ comparable /* ERROR comparable */ +var _ C /* ERROR comparable */ + +func _(_ comparable /* ERROR comparable */ , _ C /* ERROR comparable */ ) + +func _() { + var _ comparable /* ERROR comparable */ + var _ C /* ERROR comparable */ +} + +// Type parameters are never const types, i.e., it's +// not possible to declare a constant of type parameter type. +// (If a type list contains just a single const type, we could +// allow it, but such type lists don't make much sense in the +// first place.) +func _[T interface { type int, float64 }]() { + // not valid + const _ = T /* ERROR not constant */ (0) + const _ T /* ERROR invalid constant type T */ = 1 + + // valid + var _ = T(0) + var _ T = 1 + _ = T(0) +} + diff --git a/libgo/go/go/types/testdata/fixedbugs/issue20583.src b/libgo/go/go/types/testdata/fixedbugs/issue20583.src new file mode 100644 index 0000000..d26dbad --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue20583.src @@ -0,0 +1,14 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue20583 + +const ( + _ = 6e886451608 /* ERROR malformed constant */ /2 + _ = 6e886451608i /* ERROR malformed constant */ /2 + _ = 0 * 1e+1000000000 // ERROR malformed constant + + x = 1e100000000 + _ = x*x*x*x*x*x* /* ERROR not representable */ x +) diff --git a/libgo/go/go/types/testdata/fixedbugs/issue23203a.src b/libgo/go/go/types/testdata/fixedbugs/issue23203a.src new file mode 100644 index 0000000..48cb588 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue23203a.src @@ -0,0 +1,14 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "unsafe" + +type T struct{} + +func (T) m1() {} +func (T) m2([unsafe.Sizeof(T.m1)]int) {} + +func main() {} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue23203b.src b/libgo/go/go/types/testdata/fixedbugs/issue23203b.src new file mode 100644 index 0000000..638ec6c --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue23203b.src @@ -0,0 +1,14 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "unsafe" + +type T struct{} + +func (T) m2([unsafe.Sizeof(T.m1)]int) {} +func (T) m1() {} + +func main() {} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue26390.src b/libgo/go/go/types/testdata/fixedbugs/issue26390.src new file mode 100644 index 0000000..9e0101f --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue26390.src @@ -0,0 +1,13 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// stand-alone test to ensure case is triggered + +package issue26390 + +type A = T + +func (t *T) m() *A { return t } + +type T struct{} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue28251.src b/libgo/go/go/types/testdata/fixedbugs/issue28251.src new file mode 100644 index 0000000..cd79e0e --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue28251.src @@ -0,0 +1,65 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains test cases for various forms of +// method receiver declarations, per the spec clarification +// https://golang.org/cl/142757. + +package issue28251 + +// test case from issue28251 +type T struct{} + +type T0 = *T + +func (T0) m() {} + +func _() { (&T{}).m() } + +// various alternative forms +type ( + T1 = (((T))) +) + +func ((*(T1))) m1() {} +func _() { (T{}).m2() } +func _() { (&T{}).m2() } + +type ( + T2 = (((T3))) + T3 = T +) + +func (T2) m2() {} +func _() { (T{}).m2() } +func _() { (&T{}).m2() } + +type ( + T4 = ((*(T5))) + T5 = T +) + +func (T4) m4() {} +func _() { (T{}).m4 /* ERROR "cannot call pointer method m4 on T" */ () } +func _() { (&T{}).m4() } + +type ( + T6 = (((T7))) + T7 = (*(T8)) + T8 = T +) + +func (T6) m6() {} +func _() { (T{}).m6 /* ERROR "cannot call pointer method m6 on T" */ () } +func _() { (&T{}).m6() } + +type ( + T9 = *T10 + T10 = *T11 + T11 = T +) + +func (T9 /* ERROR invalid receiver \*\*T */ ) m9() {} +func _() { (T{}).m9 /* ERROR has no field or method m9 */ () } +func _() { (&T{}).m9 /* ERROR has no field or method m9 */ () } diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39634.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39634.go2 new file mode 100644 index 0000000..a13ed13 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue39634.go2 @@ -0,0 +1,91 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Examples adjusted to match new [T any] syntax for type parameters. +// Also, previously permitted empty type parameter lists and instantiations +// are now syntax errors. + +package p + +// crash 1 +type nt1[_ any]interface{g /* ERROR undeclared name */ } +type ph1[e nt1[e],g(d /* ERROR undeclared name */ )]s /* ERROR undeclared name */ +func(*ph1[e,e /* ERROR redeclared */ ])h(d /* ERROR undeclared name */ ) + +// crash 2 +// Disabled: empty []'s are now syntax errors. This example leads to too many follow-on errors. +// type Numeric2 interface{t2 /* ERROR not a type */ } +// func t2[T Numeric2](s[]T){0 /* ERROR not a type */ []{s /* ERROR cannot index */ [0][0]}} + +// crash 3 +type t3 *interface{ t3.p /* ERROR no field or method p */ } + +// crash 4 +type Numeric4 interface{t4 /* ERROR not a type */ } +func t4[T Numeric4](s[]T){if( /* ERROR non-boolean */ 0){*s /* ERROR cannot indirect */ [0]}} + +// crash 7 +type foo7 interface { bar() } +type x7[A any] struct{ foo7 } +func main7() { var _ foo7 = x7[int]{} } + +// crash 8 +type foo8[A any] interface { type A } +func bar8[A foo8[A]](a A) {} +func main8() {} + +// crash 9 +type foo9[A any] interface { type foo9 /* ERROR interface contains type constraints */ [A] } +func _() { var _ = new(foo9 /* ERROR interface contains type constraints */ [int]) } + +// crash 12 +var u /* ERROR cycle */ , i [func /* ERROR used as value */ /* ERROR used as value */ (u, c /* ERROR undeclared */ /* ERROR undeclared */ ) {}(0, len /* ERROR must be called */ /* ERROR must be called */ )]c /* ERROR undeclared */ /* ERROR undeclared */ + +// crash 15 +func y15() { var a /* ERROR declared but not used */ interface{ p() } = G15[string]{} } +type G15[X any] s /* ERROR undeclared name */ +func (G15 /* ERROR generic type .* without instantiation */ ) p() + +// crash 16 +type Foo16[T any] r16 /* ERROR not a type */ +func r16[T any]() Foo16[Foo16[T]] + +// crash 17 +type Y17 interface{ c() } +type Z17 interface { + c() Y17 + Y17 /* ERROR duplicate method */ +} +func F17[T Z17](T) + +// crash 18 +type o18[T any] []func(_ o18[[]_ /* ERROR cannot use _ */ ]) + +// crash 19 +type Z19 [][[]Z19{}[0][0]]c19 /* ERROR undeclared */ + +// crash 20 +type Z20 /* ERROR illegal cycle */ interface{ Z20 } +func F20[t Z20]() { F20(t /* ERROR invalid composite literal type */ {}) } + +// crash 21 +type Z21 /* ERROR illegal cycle */ interface{ Z21 } +func F21[T Z21]() { ( /* ERROR not used */ F21[Z21]) } + +// crash 24 +type T24[P any] P +func (r T24[P]) m() { T24 /* ERROR without instantiation */ .m() } + +// crash 25 +type T25[A any] int +func (t T25[A]) m1() {} +var x T25 /* ERROR without instantiation */ .m1 + +// crash 26 +type T26 = interface{ F26[ /* ERROR methods cannot have type parameters */ Z any]() } +func F26[Z any]() T26 { return F26[] /* ERROR operand */ } + +// crash 27 +func e27[T any]() interface{ x27 /* ERROR not a type */ } +func x27() { e27 /* ERROR cannot infer T */ () } diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39664.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39664.go2 new file mode 100644 index 0000000..3b3ec56 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue39664.go2 @@ -0,0 +1,15 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[_ any] struct {} + +func (T /* ERROR instantiation */ ) m() + +func _() { + var x interface { m() } + x = T[int]{} + _ = x +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39680.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39680.go2 new file mode 100644 index 0000000..9bc26f3 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue39680.go2 @@ -0,0 +1,27 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "fmt" + +// Minimal test case. +func _[T interface{type T}](x T) T{ + return x +} + +// Test case from issue. +type constr[T any] interface { + type T +} + +func Print[T constr[T]](s []T) { + for _, v := range s { + fmt.Print(v) + } +} + +func f() { + Print([]string{"Hello, ", "playground\n"}) +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39693.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39693.go2 new file mode 100644 index 0000000..316ab19 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue39693.go2 @@ -0,0 +1,14 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type Number interface { + int /* ERROR int is not an interface */ + float64 /* ERROR float64 is not an interface */ +} + +func Add[T Number](a, b T) T { + return a /* ERROR not defined */ + b +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39699.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39699.go2 new file mode 100644 index 0000000..75491e7 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue39699.go2 @@ -0,0 +1,29 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T0 interface{ +} + +type T1 interface{ + type int +} + +type T2 interface{ + comparable +} + +type T3 interface { + T0 + T1 + T2 +} + +func _() { + _ = T0(0) + _ = T1 /* ERROR cannot use interface T1 in conversion */ (1) + _ = T2 /* ERROR cannot use interface T2 in conversion */ (2) + _ = T3 /* ERROR cannot use interface T3 in conversion */ (3) +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39711.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39711.go2 new file mode 100644 index 0000000..df621a4 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue39711.go2 @@ -0,0 +1,11 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +// Do not report a duplicate type error for this type list. +// (Check types after interfaces have been completed.) +type _ interface { + type interface{ Error() string }, interface{ String() string } +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39723.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39723.go2 new file mode 100644 index 0000000..55464e6 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue39723.go2 @@ -0,0 +1,9 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +// A constraint must be an interface; it cannot +// be a type parameter, for instance. +func _[A interface{ type interface{} }, B A /* ERROR not an interface */ ]() diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39725.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39725.go2 new file mode 100644 index 0000000..e19b677 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue39725.go2 @@ -0,0 +1,16 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f1[T1, T2 any](T1, T2, struct{a T1; b T2}) +func _() { + f1(42, string("foo"), struct /* ERROR does not match inferred type struct\{a int; b string\} */ {a, b int}{}) +} + +// simplified test case from issue +func f2[T any](_ []T, _ func(T)) +func _() { + f2([]string{}, func /* ERROR does not match inferred type func\(string\) */ (f []byte) {}) +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39754.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39754.go2 new file mode 100644 index 0000000..b2ba9de --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue39754.go2 @@ -0,0 +1,24 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type Optional[T any] struct {} + +func (_ Optional[T]) Val() (T, bool) + +type Box[T any] interface { + Val() (T, bool) +} + +func f[V interface{}, A, B Box[V]]() {} + +func _() { + f[int, Optional[int], Optional[int]]() + _ = f[int, Optional[int], Optional /* ERROR does not satisfy Box */ [string]] + // TODO(gri) Provide better position information here. + // See TODO in call.go, Checker.arguments. + // TODO(rFindley) Reconcile this error position with types2. + f /* ERROR does not satisfy Box */ [int, Optional[int], Optional[string]]() +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39755.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39755.go2 new file mode 100644 index 0000000..b7ab688 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue39755.go2 @@ -0,0 +1,23 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _[T interface{type map[string]int}](x T) { + _ = x == nil +} + +// simplified test case from issue + +type PathParamsConstraint interface { + type map[string]string, []struct{key, value string} +} + +type PathParams[T PathParamsConstraint] struct { + t T +} + +func (pp *PathParams[T]) IsNil() bool { + return pp.t == nil // this must succeed +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39768.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39768.go2 new file mode 100644 index 0000000..abac141 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue39768.go2 @@ -0,0 +1,20 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[P any] P +type A = T +var x A[int] +var _ A /* ERROR cannot use generic type */ + +type B = T[int] +var y B = x +var _ B /* ERROR not a generic type */ [int] + +// test case from issue + +type Vector[T any] []T +type VectorAlias = Vector +var v Vector[int] diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39938.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39938.go2 new file mode 100644 index 0000000..76e7e36 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue39938.go2 @@ -0,0 +1,50 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Check "infinite expansion" cycle errors across instantiated types. + +package p + +type E0[P any] P +type E1[P any] *P +type E2[P any] struct{ P } +type E3[P any] struct{ *P } + +type T0 /* ERROR illegal cycle */ struct { + _ E0[T0] +} + +type T0_ /* ERROR illegal cycle */ struct { + E0[T0_] +} + +type T1 struct { + _ E1[T1] +} + +type T2 /* ERROR illegal cycle */ struct { + _ E2[T2] +} + +type T3 struct { + _ E3[T3] +} + +// some more complex cases + +type T4 /* ERROR illegal cycle */ struct { + _ E0[E2[T4]] +} + +type T5 struct { + _ E0[E2[E0[E1[E2[[10]T5]]]]] +} + +type T6 /* ERROR illegal cycle */ struct { + _ E0[[10]E2[E0[E2[E2[T6]]]]] +} + +type T7 struct { + _ E0[[]E2[E0[E2[E2[T6]]]]] +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39948.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39948.go2 new file mode 100644 index 0000000..c2b4609 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue39948.go2 @@ -0,0 +1,9 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[P any] interface{ + P // ERROR P is a type parameter, not an interface +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39976.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39976.go2 new file mode 100644 index 0000000..3db4eae --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue39976.go2 @@ -0,0 +1,16 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type policy[K, V any] interface{} +type LRU[K, V any] struct{} + +func NewCache[K, V any](p policy[K, V]) + +func _() { + var lru LRU[int, string] + NewCache[int, string](&lru) + NewCache(& /* ERROR does not match policy\[K, V\] \(cannot infer K and V\) */ lru) +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue39982.go2 b/libgo/go/go/types/testdata/fixedbugs/issue39982.go2 new file mode 100644 index 0000000..9810b63 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue39982.go2 @@ -0,0 +1,36 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type ( + T[_ any] struct{} + S[_ any] struct { + data T[*T[int]] + } +) + +func _() { + _ = S[int]{ + data: T[*T[int]]{}, + } +} + +// full test case from issue + +type ( + Element[TElem any] struct{} + + entry[K comparable] struct{} + + Cache[K comparable] struct { + data map[K]*Element[*entry[K]] + } +) + +func _() { + _ = Cache[int]{ + data: make(map[int](*Element[*entry[int]])), + } +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue40038.go2 b/libgo/go/go/types/testdata/fixedbugs/issue40038.go2 new file mode 100644 index 0000000..8948d61 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue40038.go2 @@ -0,0 +1,15 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type A[T any] int + +func (A[T]) m(A[T]) + +func f[P interface{m(P)}]() + +func _() { + _ = f[A[int]] +}
\ No newline at end of file diff --git a/libgo/go/go/types/testdata/fixedbugs/issue40056.go2 b/libgo/go/go/types/testdata/fixedbugs/issue40056.go2 new file mode 100644 index 0000000..f587691 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue40056.go2 @@ -0,0 +1,15 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _() { + NewS /* ERROR cannot infer T */ ().M() +} + +type S struct {} + +func NewS[T any]() *S + +func (_ *S /* ERROR S is not a generic type */ [T]) M() diff --git a/libgo/go/go/types/testdata/fixedbugs/issue40057.go2 b/libgo/go/go/types/testdata/fixedbugs/issue40057.go2 new file mode 100644 index 0000000..fdc8fb1 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue40057.go2 @@ -0,0 +1,17 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _() { + var x interface{} + switch t := x.(type) { + case S /* ERROR cannot use generic type */ : + t.m() + } +} + +type S[T any] struct {} + +func (_ S[T]) m() diff --git a/libgo/go/go/types/testdata/fixedbugs/issue40301.go2 b/libgo/go/go/types/testdata/fixedbugs/issue40301.go2 new file mode 100644 index 0000000..5d97855 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue40301.go2 @@ -0,0 +1,12 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "unsafe" + +func _[T any](x T) { + _ = unsafe /* ERROR undefined */ .Alignof(x) + _ = unsafe /* ERROR undefined */ .Sizeof(x) +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue40684.go2 b/libgo/go/go/types/testdata/fixedbugs/issue40684.go2 new file mode 100644 index 0000000..0269c3a --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue40684.go2 @@ -0,0 +1,15 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type T[_ any] int + +func f[_ any]() +func g[_, _ any]() + +func _() { + _ = f[T /* ERROR without instantiation */ ] + _ = g[T /* ERROR without instantiation */ , T /* ERROR without instantiation */ ] +}
\ No newline at end of file diff --git a/libgo/go/go/types/testdata/fixedbugs/issue41124.go2 b/libgo/go/go/types/testdata/fixedbugs/issue41124.go2 new file mode 100644 index 0000000..61f766b --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue41124.go2 @@ -0,0 +1,91 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +// Test case from issue. + +type Nat interface { + type Zero, Succ +} + +type Zero struct{} +type Succ struct{ + Nat // ERROR interface contains type constraints +} + +// Struct tests. + +type I1 interface { + comparable +} + +type I2 interface { + type int +} + +type I3 interface { + I1 + I2 +} + +type _ struct { + f I1 // ERROR interface is .* comparable +} + +type _ struct { + comparable // ERROR interface is .* comparable +} + +type _ struct{ + I1 // ERROR interface is .* comparable +} + +type _ struct{ + I2 // ERROR interface contains type constraints +} + +type _ struct{ + I3 // ERROR interface contains type constraints +} + +// General composite types. + +type ( + _ [10]I1 // ERROR interface is .* comparable + _ [10]I2 // ERROR interface contains type constraints + + _ []I1 // ERROR interface is .* comparable + _ []I2 // ERROR interface contains type constraints + + _ *I3 // ERROR interface contains type constraints + _ map[I1 /* ERROR interface is .* comparable */ ]I2 // ERROR interface contains type constraints + _ chan I3 // ERROR interface contains type constraints + _ func(I1 /* ERROR interface is .* comparable */ ) + _ func() I2 // ERROR interface contains type constraints +) + +// Other cases. + +var _ = [...]I3 /* ERROR interface contains type constraints */ {} + +func _(x interface{}) { + _ = x.(I3 /* ERROR interface contains type constraints */ ) +} + +type T1[_ any] struct{} +type T3[_, _, _ any] struct{} +var _ T1[I2 /* ERROR interface contains type constraints */ ] +var _ T3[int, I2 /* ERROR interface contains type constraints */ , float32] + +func f1[_ any]() int +var _ = f1[I2 /* ERROR interface contains type constraints */ ]() +func f3[_, _, _ any]() int +var _ = f3[int, I2 /* ERROR interface contains type constraints */ , float32]() + +func _(x interface{}) { + switch x.(type) { + case I2 /* ERROR interface contains type constraints */ : + } +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue42695.src b/libgo/go/go/types/testdata/fixedbugs/issue42695.src new file mode 100644 index 0000000..d0d6200 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue42695.src @@ -0,0 +1,17 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue42695 + +const _ = 6e5518446744 // ERROR malformed constant +const _ uint8 = 6e5518446744 // ERROR malformed constant + +var _ = 6e5518446744 // ERROR malformed constant +var _ uint8 = 6e5518446744 // ERROR malformed constant + +func f(x int) int { + return x + 6e5518446744 // ERROR malformed constant +} + +var _ = f(6e5518446744 /* ERROR malformed constant */ ) diff --git a/libgo/go/go/types/testdata/fixedbugs/issue42758.go2 b/libgo/go/go/types/testdata/fixedbugs/issue42758.go2 new file mode 100644 index 0000000..698cb8a --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue42758.go2 @@ -0,0 +1,33 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _[T any](x interface{}){ + switch x.(type) { + case T: // ok to use a type parameter + case int: + } + + switch x.(type) { + case T: + case T /* ERROR duplicate case */ : + } +} + +type constraint interface { + type int +} + +func _[T constraint](x interface{}){ + switch x.(type) { + case T: // ok to use a type parameter even if type list contains int + case int: + } +} + +func _(x constraint /* ERROR contains type constraints */ ) { + switch x /* ERROR contains type constraints */ .(type) { + } +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue42987.src b/libgo/go/go/types/testdata/fixedbugs/issue42987.src new file mode 100644 index 0000000..6060ec8 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue42987.src @@ -0,0 +1,10 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Check that there is only one error (no follow-on errors). + +package p +// TODO(rFindley) This is a parser error, but in types2 it is a type checking +// error. We could probably do without this check in the parser. +var _ = [... /* ERROR expected array length, found '...' */ ]byte("foo") diff --git a/libgo/go/go/types/testdata/fixedbugs/issue43087.src b/libgo/go/go/types/testdata/fixedbugs/issue43087.src new file mode 100644 index 0000000..ef37b4a --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue43087.src @@ -0,0 +1,43 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _() { + a, b, b /* ERROR b repeated on left side of := */ := 1, 2, 3 + _ = a + _ = b +} + +func _() { + a, _, _ := 1, 2, 3 // multiple _'s ok + _ = a +} + +func _() { + var b int + a, b, b /* ERROR b repeated on left side of := */ := 1, 2, 3 + _ = a + _ = b +} + +func _() { + var a []int + a /* ERROR expected identifier */ /* ERROR non-name .* on left side of := */ [0], b := 1, 2 + _ = a + _ = b +} + +func _() { + var a int + a, a /* ERROR a repeated on left side of := */ := 1, 2 + _ = a +} + +func _() { + var a, b int + a, b := /* ERROR no new variables on left side of := */ 1, 2 + _ = a + _ = b +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue43110.src b/libgo/go/go/types/testdata/fixedbugs/issue43110.src new file mode 100644 index 0000000..4a46945 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue43110.src @@ -0,0 +1,43 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type P *struct{} + +func _() { + // want an error even if the switch is empty + var a struct{ _ func() } + switch a /* ERROR cannot switch on a */ { + } + + switch a /* ERROR cannot switch on a */ { + case a: // no follow-on error here + } + + // this is ok because f can be compared to nil + var f func() + switch f { + } + + switch f { + case nil: + } + + switch (func())(nil) { + case nil: + } + + switch (func())(nil) { + case f /* ERROR cannot compare */ : + } + + switch nil /* ERROR use of untyped nil in switch expression */ { + } + + // this is ok + switch P(nil) { + case P(nil): + } +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue43124.src b/libgo/go/go/types/testdata/fixedbugs/issue43124.src new file mode 100644 index 0000000..f429f74 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue43124.src @@ -0,0 +1,16 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +var _ = int(0 /* ERROR invalid use of \.\.\. in conversion to int */ ...) + +// test case from issue + +type M []string + +var ( + x = []string{"a", "b"} + _ = M(x /* ERROR invalid use of \.\.\. in conversion to M */ ...) +) diff --git a/libgo/go/go/types/testdata/fixedbugs/issue43125.src b/libgo/go/go/types/testdata/fixedbugs/issue43125.src new file mode 100644 index 0000000..456888d --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue43125.src @@ -0,0 +1,8 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +var _ = new(- /* ERROR not a type */ 1) +var _ = new(1 /* ERROR not a type */ + 1) diff --git a/libgo/go/go/types/testdata/fixedbugs/issue43190.src b/libgo/go/go/types/testdata/fixedbugs/issue43190.src new file mode 100644 index 0000000..96acb3a --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue43190.src @@ -0,0 +1,22 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Most of the errors below are actually produced by the parser, but we check +// them here for consistency with the types2 tests. + +package p + +import ; /* ERROR invalid import path */ /* ERROR expected 'STRING' */ +import // ERROR expected ';' +var _ int +import /* ERROR expected declaration */ .; + +import () +import (.) +import ( + "fmt" + . +) + +var _ = fmt /* ERROR "undeclared name" */ .Println diff --git a/libgo/go/go/types/testdata/fixedbugs/issue44688.go2 b/libgo/go/go/types/testdata/fixedbugs/issue44688.go2 new file mode 100644 index 0000000..512bfcc --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue44688.go2 @@ -0,0 +1,83 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package P + +type A1[T any] struct{} + +func (*A1[T]) m1(T) {} + +type A2[T any] interface { + m2(T) +} + +type B1[T any] struct { + filler int + *A1[T] + A2[T] +} + +type B2[T any] interface { + A2[T] +} + +type C[T any] struct { + filler1 int + filler2 int + B1[T] +} + +type D[T any] struct { + filler1 int + filler2 int + filler3 int + C[T] +} + +func _() { + // calling embedded methods + var b1 B1[string] + + b1.A1.m1("") + b1.m1("") + + b1.A2.m2("") + b1.m2("") + + var b2 B2[string] + b2.m2("") + + // a deeper nesting + var d D[string] + d.m1("") + d.m2("") + + // calling method expressions + m1x := B1[string].m1 + m1x(b1, "") + m2x := B2[string].m2 + m2x(b2, "") + + // calling method values + m1v := b1.m1 + m1v("") + m2v := b1.m2 + m2v("") + b2v := b2.m2 + b2v("") +} + +// actual test case from issue + +type A[T any] struct{} + +func (*A[T]) f(T) {} + +type B[T any] struct{ A[T] } + +func _() { + var b B[string] + b.A.f("") + b.f("") +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue44799.go2 b/libgo/go/go/types/testdata/fixedbugs/issue44799.go2 new file mode 100644 index 0000000..9e528a7 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue44799.go2 @@ -0,0 +1,19 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func Map[F, T any](s []F, f func(F) T) []T { return nil } + +func Reduce[Elem1, Elem2 any](s []Elem1, initializer Elem2, f func(Elem2, Elem1) Elem2) Elem2 { var x Elem2; return x } + +func main() { + var s []int + var f1 func(int) float64 + var f2 func(float64, int) float64 + _ = Map[int](s, f1) + _ = Map(s, f1) + _ = Reduce[int](s, 0, f2) + _ = Reduce(s, 0, f2) +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue45548.go2 b/libgo/go/go/types/testdata/fixedbugs/issue45548.go2 new file mode 100644 index 0000000..b1e4249 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue45548.go2 @@ -0,0 +1,13 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f[F interface{type *Q}, G interface{type *R}, Q, R any](q Q, r R) {} + +func _() { + f[*float64, *int](1, 2) + f[*float64](1, 2) + f(1, 2) +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue45635.go2 b/libgo/go/go/types/testdata/fixedbugs/issue45635.go2 new file mode 100644 index 0000000..3e2ccec --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue45635.go2 @@ -0,0 +1,32 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func main() { + some /* ERROR "undeclared name" */ [int, int]() +} + +type N[T any] struct{} + +var _ N /* ERROR "0 arguments but 1 type parameters" */ [] + +type I interface { + type map[int]int, []int +} + +func _[T I](i, j int) { + var m map[int]int + _ = m[i, j /* ERROR "more than one index" */ ] + + var a [3]int + _ = a[i, j /* ERROR "more than one index" */ ] + + var s []int + _ = s[i, j /* ERROR "more than one index" */ ] + + var t T + // TODO(rFindley) Fix the duplicate error below. + _ = t[i, j /* ERROR "more than one index" */ /* ERROR "more than one index" */ ] +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue45985.go2 b/libgo/go/go/types/testdata/fixedbugs/issue45985.go2 new file mode 100644 index 0000000..550b9c6 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue45985.go2 @@ -0,0 +1,14 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue45985 + +// TODO(rFindley): this error should be on app[int] below. +func app[S /* ERROR "type S = S does not match" */ interface{ type []T }, T any](s S, e T) S { + return append(s, e) +} + +func _() { + _ = app[int] +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue46403.src b/libgo/go/go/types/testdata/fixedbugs/issue46403.src new file mode 100644 index 0000000..9d47522 --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue46403.src @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue46403 + +func _() { + // a should be used, despite the parser error below. + var a []int + var _ = a[] // ERROR expected operand +} diff --git a/libgo/go/go/types/testdata/fixedbugs/issue46404.go1 b/libgo/go/go/types/testdata/fixedbugs/issue46404.go1 new file mode 100644 index 0000000..db604bc --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue46404.go1 @@ -0,0 +1,8 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue46404 + +// Check that we don't type check t[_] as an instantiation. +type t [t /* ERROR not a type */ [_]]_ // ERROR cannot use diff --git a/libgo/go/go/types/testdata/fixedbugs/issue6977.src b/libgo/go/go/types/testdata/fixedbugs/issue6977.src new file mode 100644 index 0000000..8f4e9ba --- /dev/null +++ b/libgo/go/go/types/testdata/fixedbugs/issue6977.src @@ -0,0 +1,82 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "io" + +// Alan's initial report. + +type I interface { f(); String() string } +type J interface { g(); String() string } + +type IJ1 = interface { I; J } +type IJ2 = interface { f(); g(); String() string } + +var _ = (*IJ1)(nil) == (*IJ2)(nil) // static assert that IJ1 and IJ2 are identical types + +// The canonical example. + +type ReadWriteCloser interface { io.ReadCloser; io.WriteCloser } + +// Some more cases. + +type M interface { m() } +type M32 interface { m() int32 } +type M64 interface { m() int64 } + +type U1 interface { m() } +type U2 interface { m(); M } +type U3 interface { M; m() } +type U4 interface { M; M; M } +type U5 interface { U1; U2; U3; U4 } + +type U6 interface { m(); m /* ERROR duplicate method */ () } +type U7 interface { M32 /* ERROR duplicate method */ ; m() } +type U8 interface { m(); M32 /* ERROR duplicate method */ } +type U9 interface { M32; M64 /* ERROR duplicate method */ } + +// Verify that repeated embedding of the same interface(s) +// eliminates duplicate methods early (rather than at the +// end) to prevent exponential memory and time use. +// Without early elimination, computing T29 may take dozens +// of minutes. +type ( + T0 interface { m() } + T1 interface { T0; T0 } + T2 interface { T1; T1 } + T3 interface { T2; T2 } + T4 interface { T3; T3 } + T5 interface { T4; T4 } + T6 interface { T5; T5 } + T7 interface { T6; T6 } + T8 interface { T7; T7 } + T9 interface { T8; T8 } + + T10 interface { T9; T9 } + T11 interface { T10; T10 } + T12 interface { T11; T11 } + T13 interface { T12; T12 } + T14 interface { T13; T13 } + T15 interface { T14; T14 } + T16 interface { T15; T15 } + T17 interface { T16; T16 } + T18 interface { T17; T17 } + T19 interface { T18; T18 } + + T20 interface { T19; T19 } + T21 interface { T20; T20 } + T22 interface { T21; T21 } + T23 interface { T22; T22 } + T24 interface { T23; T23 } + T25 interface { T24; T24 } + T26 interface { T25; T25 } + T27 interface { T26; T26 } + T28 interface { T27; T27 } + T29 interface { T28; T28 } +) + +// Verify that m is present. +var x T29 +var _ = x.m diff --git a/libgo/go/go/types/type.go b/libgo/go/go/types/type.go index 087cda4..2660ce4 100644 --- a/libgo/go/go/types/type.go +++ b/libgo/go/go/types/type.go @@ -4,12 +4,18 @@ package types -import "sort" +import ( + "fmt" + "go/token" + "sync/atomic" +) // A Type represents a type of Go. // All types implement the Type interface. type Type interface { - // Underlying returns the underlying type of a type. + // Underlying returns the underlying type of a type + // w/o following forwarding chains. Only used by + // client packages (here for backward-compatibility). Underlying() Type // String returns a string representation of a type. @@ -98,7 +104,7 @@ type Array struct { // NewArray returns a new array type for the given element type and length. // A negative length indicates an unknown length. -func NewArray(elem Type, len int64) *Array { return &Array{len, elem} } +func NewArray(elem Type, len int64) *Array { return &Array{len: len, elem: elem} } // Len returns the length of array a. // A negative result indicates an unknown length. @@ -113,7 +119,7 @@ type Slice struct { } // NewSlice returns a new slice type for the given element type. -func NewSlice(elem Type) *Slice { return &Slice{elem} } +func NewSlice(elem Type) *Slice { return &Slice{elem: elem} } // Elem returns the element type of slice s. func (s *Slice) Elem() Type { return s.elem } @@ -176,8 +182,10 @@ type Tuple struct { // NewTuple returns a new tuple for the given variables. func NewTuple(x ...*Var) *Tuple { if len(x) > 0 { - return &Tuple{x} + return &Tuple{vars: x} } + // TODO(gri) Don't represent empty tuples with a (*Tuple)(nil) pointer; + // it's too subtle and causes problems. return nil } @@ -199,11 +207,13 @@ type Signature struct { // and store it in the Func Object) because when type-checking a function // literal we call the general type checker which returns a general Type. // We then unpack the *Signature and use the scope for the literal body. - scope *Scope // function scope, present for package-local signatures - recv *Var // nil if not a method - params *Tuple // (incoming) parameters from left to right; or nil - results *Tuple // (outgoing) results from left to right; or nil - variadic bool // true if the last parameter's type is of the form ...T (or string, for append built-in only) + rparams []*TypeName // receiver type parameters from left to right, or nil + tparams []*TypeName // type parameters from left to right, or nil + scope *Scope // function scope, present for package-local signatures + recv *Var // nil if not a method + params *Tuple // (incoming) parameters from left to right; or nil + results *Tuple // (outgoing) results from left to right; or nil + variadic bool // true if the last parameter's type is of the form ...T (or string, for append built-in only) } // NewSignature returns a new function type for the given receiver, parameters, @@ -220,7 +230,7 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { panic("types.NewSignature: variadic parameter must be of unnamed slice type") } } - return &Signature{nil, recv, params, results, variadic} + return &Signature{recv: recv, params: params, results: results, variadic: variadic} } // Recv returns the receiver of signature s (if a method), or nil if a @@ -231,6 +241,12 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { // contain methods whose receiver type is a different interface. func (s *Signature) Recv() *Var { return s.recv } +// _TParams returns the type parameters of signature s, or nil. +func (s *Signature) _TParams() []*TypeName { return s.tparams } + +// _SetTParams sets the type parameters of signature s. +func (s *Signature) _SetTParams(tparams []*TypeName) { s.tparams = tparams } + // Params returns the parameters of signature s, or nil. func (s *Signature) Params() *Tuple { return s.params } @@ -240,12 +256,88 @@ func (s *Signature) Results() *Tuple { return s.results } // Variadic reports whether the signature s is variadic. func (s *Signature) Variadic() bool { return s.variadic } +// A _Sum represents a set of possible types. +// Sums are currently used to represent type lists of interfaces +// and thus the underlying types of type parameters; they are not +// first class types of Go. +type _Sum struct { + types []Type // types are unique +} + +// _NewSum returns a new Sum type consisting of the provided +// types if there are more than one. If there is exactly one +// type, it returns that type. If the list of types is empty +// the result is nil. +func _NewSum(types []Type) Type { + if len(types) == 0 { + return nil + } + + // What should happen if types contains a sum type? + // Do we flatten the types list? For now we check + // and panic. This should not be possible for the + // current use case of type lists. + // TODO(gri) Come up with the rules for sum types. + for _, t := range types { + if _, ok := t.(*_Sum); ok { + panic("sum type contains sum type - unimplemented") + } + } + + if len(types) == 1 { + return types[0] + } + return &_Sum{types: types} +} + +// is reports whether all types in t satisfy pred. +func (s *_Sum) is(pred func(Type) bool) bool { + if s == nil { + return false + } + for _, t := range s.types { + if !pred(t) { + return false + } + } + return true +} + // An Interface represents an interface type. type Interface struct { methods []*Func // ordered list of explicitly declared methods + types Type // (possibly a Sum) type declared with a type list (TODO(gri) need better field name) embeddeds []Type // ordered list of explicitly embedded types allMethods []*Func // ordered list of methods declared with or embedded in this interface (TODO(gri): replace with mset) + allTypes Type // intersection of all embedded and locally declared types (TODO(gri) need better field name) + + obj Object // type declaration defining this interface; or nil (for better error messages) +} + +// unpack unpacks a type into a list of types. +// TODO(gri) Try to eliminate the need for this function. +func unpackType(typ Type) []Type { + if typ == nil { + return nil + } + if sum := asSum(typ); sum != nil { + return sum.types + } + return []Type{typ} +} + +// is reports whether interface t represents types that all satisfy pred. +func (t *Interface) is(pred func(Type) bool) bool { + if t.allTypes == nil { + return false // we must have at least one type! (was bug) + } + for _, t := range unpackType(t.allTypes) { + if !pred(t) { + return false + } + } + return true } // emptyInterface represents the empty (completed) interface @@ -301,8 +393,8 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { } // sort for API stability - sort.Sort(byUniqueMethodName(methods)) - sort.Stable(byUniqueTypeName(embeddeds)) + sortMethods(methods) + sortTypes(embeddeds) typ.methods = methods typ.embeddeds = embeddeds @@ -344,8 +436,101 @@ func (t *Interface) assertCompleteness() { func (t *Interface) Method(i int) *Func { t.assertCompleteness(); return t.allMethods[i] } // Empty reports whether t is the empty interface. -// The interface must have been completed. -func (t *Interface) Empty() bool { t.assertCompleteness(); return len(t.allMethods) == 0 } +func (t *Interface) Empty() bool { + if t.allMethods != nil { + // interface is complete - quick test + // A non-nil allTypes may still be empty and represents the bottom type. + return len(t.allMethods) == 0 && t.allTypes == nil + } + return !t.iterate(func(t *Interface) bool { + return len(t.methods) > 0 || t.types != nil + }, nil) +} + +// _HasTypeList reports whether interface t has a type list, possibly from an embedded type. +func (t *Interface) _HasTypeList() bool { + if t.allMethods != nil { + // interface is complete - quick test + return t.allTypes != nil + } + + return t.iterate(func(t *Interface) bool { + return t.types != nil + }, nil) +} + +// _IsComparable reports whether interface t is or embeds the predeclared interface "comparable". +func (t *Interface) _IsComparable() bool { + if t.allMethods != nil { + // interface is complete - quick test + _, m := lookupMethod(t.allMethods, nil, "==") + return m != nil + } + + return t.iterate(func(t *Interface) bool { + _, m := lookupMethod(t.methods, nil, "==") + return m != nil + }, nil) +} + +// _IsConstraint reports t.HasTypeList() || t.IsComparable(). +func (t *Interface) _IsConstraint() bool { + if t.allMethods != nil { + // interface is complete - quick test + if t.allTypes != nil { + return true + } + _, m := lookupMethod(t.allMethods, nil, "==") + return m != nil + } + + return t.iterate(func(t *Interface) bool { + if t.types != nil { + return true + } + _, m := lookupMethod(t.methods, nil, "==") + return m != nil + }, nil) +} + +// iterate calls f with t and then with any embedded interface of t, recursively, until f returns true. +// iterate reports whether any call to f returned true. +func (t *Interface) iterate(f func(*Interface) bool, seen map[*Interface]bool) bool { + if f(t) { + return true + } + for _, e := range t.embeddeds { + // e should be an interface but be careful (it may be invalid) + if e := asInterface(e); e != nil { + // Cyclic interfaces such as "type E interface { E }" are not permitted + // but they are still constructed and we need to detect such cycles. + if seen[e] { + continue + } + if seen == nil { + seen = make(map[*Interface]bool) + } + seen[e] = true + if e.iterate(f, seen) { + return true + } + } + } + return false +} + +// isSatisfiedBy reports whether interface t's type list is satisfied by the type typ. +// If the type list is empty (absent), typ trivially satisfies the interface. +// TODO(gri) This is not a great name. Eventually, we should have a more comprehensive +// "implements" predicate. +func (t *Interface) isSatisfiedBy(typ Type) bool { + t.Complete() + if t.allTypes == nil { + return true + } + types := unpackType(t.allTypes) + return includes(types, typ) || includes(types, under(typ)) +} // Complete computes the interface's method set. It must be called by users of // NewInterfaceType and NewInterface after the interface's embedded types are @@ -379,12 +564,22 @@ func (t *Interface) Complete() *Interface { addMethod(m, true) } + allTypes := t.types + for _, typ := range t.embeddeds { - typ := typ.Underlying().(*Interface) - typ.Complete() - for _, m := range typ.allMethods { + utyp := under(typ) + etyp := asInterface(utyp) + if etyp == nil { + if utyp != Typ[Invalid] { + panic(fmt.Sprintf("%s is not an interface", typ)) + } + continue + } + etyp.Complete() + for _, m := range etyp.allMethods { addMethod(m, false) } + allTypes = intersect(allTypes, etyp.allTypes) } for i := 0; i < len(todo); i += 2 { @@ -396,9 +591,10 @@ func (t *Interface) Complete() *Interface { } if methods != nil { - sort.Sort(byUniqueMethodName(methods)) + sortMethods(methods) t.allMethods = methods } + t.allTypes = allTypes return t } @@ -410,7 +606,7 @@ type Map struct { // NewMap returns a new map for the given key and element types. func NewMap(key, elem Type) *Map { - return &Map{key, elem} + return &Map{key: key, elem: elem} } // Key returns the key type of map m. @@ -437,7 +633,7 @@ const ( // NewChan returns a new channel type for the given direction and element type. func NewChan(dir ChanDir, elem Type) *Chan { - return &Chan{dir, elem} + return &Chan{dir: dir, elem: elem} } // Dir returns the direction of channel c. @@ -446,13 +642,16 @@ func (c *Chan) Dir() ChanDir { return c.dir } // Elem returns the element type of channel c. func (c *Chan) Elem() Type { return c.elem } -// A Named represents a named type. +// A Named represents a named (defined) type. type Named struct { - info typeInfo // for cycle detection - obj *TypeName // corresponding declared object - orig Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting) - underlying Type // possibly a *Named during setup; never a *Named once set up completely - methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily + check *Checker // for Named.under implementation; nilled once under has been called + info typeInfo // for cycle detection + obj *TypeName // corresponding declared object + orig Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting) + underlying Type // possibly a *Named during setup; never a *Named once set up completely + tparams []*TypeName // type parameters, or nil + targs []Type // type arguments (after instantiation), or nil + methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily } // NewNamed returns a new named type for the given type name, underlying type, and associated methods. @@ -462,16 +661,50 @@ func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { if _, ok := underlying.(*Named); ok { panic("types.NewNamed: underlying type must not be *Named") } - typ := &Named{obj: obj, orig: underlying, underlying: underlying, methods: methods} + return (*Checker)(nil).newNamed(obj, underlying, methods) +} + +func (check *Checker) newNamed(obj *TypeName, underlying Type, methods []*Func) *Named { + typ := &Named{check: check, obj: obj, orig: underlying, underlying: underlying, methods: methods} if obj.typ == nil { obj.typ = typ } + // Ensure that typ is always expanded, at which point the check field can be + // nilled out. + // + // Note that currently we cannot nil out check inside typ.under(), because + // it's possible that typ is expanded multiple times. + // + // TODO(rFindley): clean this up so that under is the only function mutating + // named types. + if check != nil { + check.later(func() { + switch typ.under().(type) { + case *Named, *instance: + panic("internal error: unexpanded underlying type") + } + typ.check = nil + }) + } return typ } // Obj returns the type name for the named type t. func (t *Named) Obj() *TypeName { return t.obj } +// TODO(gri) Come up with a better representation and API to distinguish +// between parameterized instantiated and non-instantiated types. + +// _TParams returns the type parameters of the named type t, or nil. +// The result is non-nil for an (originally) parameterized type even if it is instantiated. +func (t *Named) _TParams() []*TypeName { return t.tparams } + +// _TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. +func (t *Named) _TArgs() []Type { return t.targs } + +// _SetTArgs sets the type arguments of Named. +func (t *Named) _SetTArgs(args []Type) { t.targs = args } + // NumMethods returns the number of explicit methods whose receiver is named type t. func (t *Named) NumMethods() int { return len(t.methods) } @@ -496,28 +729,258 @@ func (t *Named) AddMethod(m *Func) { } } -// Implementations for Type methods. - -func (b *Basic) Underlying() Type { return b } -func (a *Array) Underlying() Type { return a } -func (s *Slice) Underlying() Type { return s } -func (s *Struct) Underlying() Type { return s } -func (p *Pointer) Underlying() Type { return p } -func (t *Tuple) Underlying() Type { return t } -func (s *Signature) Underlying() Type { return s } -func (t *Interface) Underlying() Type { return t } -func (m *Map) Underlying() Type { return m } -func (c *Chan) Underlying() Type { return c } -func (t *Named) Underlying() Type { return t.underlying } - -func (b *Basic) String() string { return TypeString(b, nil) } -func (a *Array) String() string { return TypeString(a, nil) } -func (s *Slice) String() string { return TypeString(s, nil) } -func (s *Struct) String() string { return TypeString(s, nil) } -func (p *Pointer) String() string { return TypeString(p, nil) } -func (t *Tuple) String() string { return TypeString(t, nil) } -func (s *Signature) String() string { return TypeString(s, nil) } -func (t *Interface) String() string { return TypeString(t, nil) } -func (m *Map) String() string { return TypeString(m, nil) } -func (c *Chan) String() string { return TypeString(c, nil) } -func (t *Named) String() string { return TypeString(t, nil) } +// Note: This is a uint32 rather than a uint64 because the +// respective 64 bit atomic instructions are not available +// on all platforms. +var lastId uint32 + +// nextId returns a value increasing monotonically by 1 with +// each call, starting with 1. It may be called concurrently. +func nextId() uint64 { return uint64(atomic.AddUint32(&lastId, 1)) } + +// A _TypeParam represents a type parameter type. +type _TypeParam struct { + check *Checker // for lazy type bound completion + id uint64 // unique id + obj *TypeName // corresponding type name + index int // parameter index + bound Type // *Named or *Interface; underlying type is always *Interface +} + +// newTypeParam returns a new TypeParam. +func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *_TypeParam { + assert(bound != nil) + typ := &_TypeParam{check: check, id: nextId(), obj: obj, index: index, bound: bound} + if obj.typ == nil { + obj.typ = typ + } + return typ +} + +func (t *_TypeParam) Bound() *Interface { + iface := asInterface(t.bound) + // use the type bound position if we have one + pos := token.NoPos + if n, _ := t.bound.(*Named); n != nil { + pos = n.obj.pos + } + // TODO(rFindley) switch this to an unexported method on Checker. + t.check.completeInterface(pos, iface) + return iface +} + +// optype returns a type's operational type. Except for +// type parameters, the operational type is the same +// as the underlying type (as returned by under). For +// Type parameters, the operational type is determined +// by the corresponding type bound's type list. The +// result may be the bottom or top type, but it is never +// the incoming type parameter. +func optype(typ Type) Type { + if t := asTypeParam(typ); t != nil { + // If the optype is typ, return the top type as we have + // no information. It also prevents infinite recursion + // via the asTypeParam converter function. This can happen + // for a type parameter list of the form: + // (type T interface { type T }). + // See also issue #39680. + if u := t.Bound().allTypes; u != nil && u != typ { + // u != typ and u is a type parameter => under(u) != typ, so this is ok + return under(u) + } + return theTop + } + return under(typ) +} + +// An instance represents an instantiated generic type syntactically +// (without expanding the instantiation). Type instances appear only +// during type-checking and are replaced by their fully instantiated +// (expanded) types before the end of type-checking. +type instance struct { + check *Checker // for lazy instantiation + pos token.Pos // position of type instantiation; for error reporting only + base *Named // parameterized type to be instantiated + targs []Type // type arguments + poslist []token.Pos // position of each targ; for error reporting only + value Type // base(targs...) after instantiation or Typ[Invalid]; nil if not yet set +} + +// expand returns the instantiated (= expanded) type of t. +// The result is either an instantiated *Named type, or +// Typ[Invalid] if there was an error. +func (t *instance) expand() Type { + v := t.value + if v == nil { + v = t.check.instantiate(t.pos, t.base, t.targs, t.poslist) + if v == nil { + v = Typ[Invalid] + } + t.value = v + } + // After instantiation we must have an invalid or a *Named type. + if debug && v != Typ[Invalid] { + _ = v.(*Named) + } + return v +} + +// expand expands a type instance into its instantiated +// type and leaves all other types alone. expand does +// not recurse. +func expand(typ Type) Type { + if t, _ := typ.(*instance); t != nil { + return t.expand() + } + return typ +} + +// expandf is set to expand. +// Call expandf when calling expand causes compile-time cycle error. +var expandf func(Type) Type + +func init() { expandf = expand } + +// bottom represents the bottom of the type lattice. +// It is the underlying type of a type parameter that +// cannot be satisfied by any type, usually because +// the intersection of type constraints left nothing). +type bottom struct{} + +// theBottom is the singleton bottom type. +var theBottom = &bottom{} + +// top represents the top of the type lattice. +// It is the underlying type of a type parameter that +// can be satisfied by any type (ignoring methods), +// usually because the type constraint has no type +// list. +type top struct{} + +// theTop is the singleton top type. +var theTop = &top{} + +// Type-specific implementations of Underlying. +func (t *Basic) Underlying() Type { return t } +func (t *Array) Underlying() Type { return t } +func (t *Slice) Underlying() Type { return t } +func (t *Struct) Underlying() Type { return t } +func (t *Pointer) Underlying() Type { return t } +func (t *Tuple) Underlying() Type { return t } +func (t *Signature) Underlying() Type { return t } +func (t *_Sum) Underlying() Type { return t } +func (t *Interface) Underlying() Type { return t } +func (t *Map) Underlying() Type { return t } +func (t *Chan) Underlying() Type { return t } +func (t *Named) Underlying() Type { return t.underlying } +func (t *_TypeParam) Underlying() Type { return t } +func (t *instance) Underlying() Type { return t } +func (t *bottom) Underlying() Type { return t } +func (t *top) Underlying() Type { return t } + +// Type-specific implementations of String. +func (t *Basic) String() string { return TypeString(t, nil) } +func (t *Array) String() string { return TypeString(t, nil) } +func (t *Slice) String() string { return TypeString(t, nil) } +func (t *Struct) String() string { return TypeString(t, nil) } +func (t *Pointer) String() string { return TypeString(t, nil) } +func (t *Tuple) String() string { return TypeString(t, nil) } +func (t *Signature) String() string { return TypeString(t, nil) } +func (t *_Sum) String() string { return TypeString(t, nil) } +func (t *Interface) String() string { return TypeString(t, nil) } +func (t *Map) String() string { return TypeString(t, nil) } +func (t *Chan) String() string { return TypeString(t, nil) } +func (t *Named) String() string { return TypeString(t, nil) } +func (t *_TypeParam) String() string { return TypeString(t, nil) } +func (t *instance) String() string { return TypeString(t, nil) } +func (t *bottom) String() string { return TypeString(t, nil) } +func (t *top) String() string { return TypeString(t, nil) } + +// under returns the true expanded underlying type. +// If it doesn't exist, the result is Typ[Invalid]. +// under must only be called when a type is known +// to be fully set up. +func under(t Type) Type { + // TODO(gri) is this correct for *Sum? + if n := asNamed(t); n != nil { + return n.under() + } + return t +} + +// Converters +// +// A converter must only be called when a type is +// known to be fully set up. A converter returns +// a type's operational type (see comment for optype) +// or nil if the type argument is not of the +// respective type. + +func asBasic(t Type) *Basic { + op, _ := optype(t).(*Basic) + return op +} + +func asArray(t Type) *Array { + op, _ := optype(t).(*Array) + return op +} + +func asSlice(t Type) *Slice { + op, _ := optype(t).(*Slice) + return op +} + +func asStruct(t Type) *Struct { + op, _ := optype(t).(*Struct) + return op +} + +func asPointer(t Type) *Pointer { + op, _ := optype(t).(*Pointer) + return op +} + +func asTuple(t Type) *Tuple { + op, _ := optype(t).(*Tuple) + return op +} + +func asSignature(t Type) *Signature { + op, _ := optype(t).(*Signature) + return op +} + +func asSum(t Type) *_Sum { + op, _ := optype(t).(*_Sum) + return op +} + +func asInterface(t Type) *Interface { + op, _ := optype(t).(*Interface) + return op +} + +func asMap(t Type) *Map { + op, _ := optype(t).(*Map) + return op +} + +func asChan(t Type) *Chan { + op, _ := optype(t).(*Chan) + return op +} + +// If the argument to asNamed and asTypeParam is of the respective types +// (possibly after expanding an instance type), these methods return that type. +// Otherwise the result is nil. + +func asNamed(t Type) *Named { + e, _ := expand(t).(*Named) + return e +} + +func asTypeParam(t Type) *_TypeParam { + u, _ := under(t).(*_TypeParam) + return u +} diff --git a/libgo/go/go/types/types_test.go b/libgo/go/go/types/types_test.go new file mode 100644 index 0000000..25cd996 --- /dev/null +++ b/libgo/go/go/types/types_test.go @@ -0,0 +1,19 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import "sync/atomic" + +// Upon calling ResetId, nextId starts with 1 again. +// It may be called concurrently. This is only needed +// for tests where we may want to have a consistent +// numbering for each individual test case. +func ResetId() { atomic.StoreUint32(&lastId, 0) } + +// SetGoVersion sets the unexported goVersion field on config, so that tests +// which assert on behavior for older Go versions can set it. +func SetGoVersion(config *Config, goVersion string) { + config.goVersion = goVersion +} diff --git a/libgo/go/go/types/typestring.go b/libgo/go/go/types/typestring.go index 31c572f..fe27f0f 100644 --- a/libgo/go/go/types/typestring.go +++ b/libgo/go/go/types/typestring.go @@ -9,6 +9,8 @@ package types import ( "bytes" "fmt" + "go/token" + "unicode/utf8" ) // A Qualifier controls how named package-level objects are printed in @@ -75,6 +77,10 @@ func WriteType(buf *bytes.Buffer, typ Type, qf Qualifier) { writeType(buf, typ, qf, make([]Type, 0, 8)) } +// instanceMarker is the prefix for an instantiated type +// in "non-evaluated" instance form. +const instanceMarker = '#' + func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { // Theoretically, this is a quadratic lookup algorithm, but in // practice deeply nested composite types with unnamed component @@ -82,7 +88,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { // using a map. for _, t := range visited { if t == typ { - fmt.Fprintf(buf, "○%T", typ) // cycle to typ + fmt.Fprintf(buf, "○%T", goTypeName(typ)) // cycle to typ return } } @@ -93,9 +99,15 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { buf.WriteString("<nil>") case *Basic: - if t.kind == UnsafePointer { - buf.WriteString("unsafe.") + // exported basic types go into package unsafe + // (currently this is just unsafe.Pointer) + if token.IsExported(t.name) { + if obj, _ := Unsafe.scope.Lookup(t.name).(*TypeName); obj != nil { + writeTypeName(buf, obj, qf) + break + } } + if gcCompatibilityMode { // forget the alias names switch t.kind { @@ -121,6 +133,9 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { if i > 0 { buf.WriteString("; ") } + // This doesn't do the right thing for embedded type + // aliases where we should print the alias name, not + // the aliased type (see issue #44410). if !f.embedded { buf.WriteString(f.name) buf.WriteByte(' ') @@ -143,6 +158,14 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { buf.WriteString("func") writeSignature(buf, t, qf, visited) + case *_Sum: + for i, t := range t.types { + if i > 0 { + buf.WriteString(", ") + } + writeType(buf, t, qf, visited) + } + case *Interface: // We write the source-level methods and embedded types rather // than the actual method set since resolved method signatures @@ -168,6 +191,13 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeSignature(buf, m.typ.(*Signature), qf, visited) empty = false } + if !empty && t.allTypes != nil { + buf.WriteString("; ") + } + if t.allTypes != nil { + buf.WriteString("type ") + writeType(buf, t.allTypes, qf, visited) + } } else { // print explicit interface methods and embedded types for i, m := range t.methods { @@ -178,8 +208,19 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { writeSignature(buf, m.typ.(*Signature), qf, visited) empty = false } + if !empty && t.types != nil { + buf.WriteString("; ") + } + if t.types != nil { + buf.WriteString("type ") + writeType(buf, t.types, qf, visited) + empty = false + } + if !empty && len(t.embeddeds) > 0 { + buf.WriteString("; ") + } for i, typ := range t.embeddeds { - if i > 0 || len(t.methods) > 0 { + if i > 0 { buf.WriteString("; ") } writeType(buf, typ, qf, visited) @@ -227,17 +268,36 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { } case *Named: - s := "<Named w/o object>" - if obj := t.obj; obj != nil { - if obj.pkg != nil { - writePackage(buf, obj.pkg, qf) - } - // TODO(gri): function-local named types should be displayed - // differently from named types at package level to avoid - // ambiguity. - s = obj.name + writeTypeName(buf, t.obj, qf) + if t.targs != nil { + // instantiated type + buf.WriteByte('[') + writeTypeList(buf, t.targs, qf, visited) + buf.WriteByte(']') + } else if t.tparams != nil { + // parameterized type + writeTParamList(buf, t.tparams, qf, visited) } - buf.WriteString(s) + + case *_TypeParam: + s := "?" + if t.obj != nil { + s = t.obj.name + } + buf.WriteString(s + subscript(t.id)) + + case *instance: + buf.WriteByte(instanceMarker) // indicate "non-evaluated" syntactic instance + writeTypeName(buf, t.base.obj, qf) + buf.WriteByte('[') + writeTypeList(buf, t.targs, qf, visited) + buf.WriteByte(']') + + case *bottom: + buf.WriteString("⊥") + + case *top: + buf.WriteString("⊤") default: // For externally defined implementations of Type. @@ -245,6 +305,62 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) { } } +func writeTypeList(buf *bytes.Buffer, list []Type, qf Qualifier, visited []Type) { + for i, typ := range list { + if i > 0 { + buf.WriteString(", ") + } + writeType(buf, typ, qf, visited) + } +} + +func writeTParamList(buf *bytes.Buffer, list []*TypeName, qf Qualifier, visited []Type) { + // TODO(rFindley) compare this with the corresponding implementation in types2 + buf.WriteString("[") + var prev Type + for i, p := range list { + // TODO(rFindley) support 'any' sugar here. + var b Type = &emptyInterface + if t, _ := p.typ.(*_TypeParam); t != nil && t.bound != nil { + b = t.bound + } + if i > 0 { + if b != prev { + // type bound changed - write previous one before advancing + buf.WriteByte(' ') + writeType(buf, prev, qf, visited) + } + buf.WriteString(", ") + } + prev = b + + if t, _ := p.typ.(*_TypeParam); t != nil { + writeType(buf, t, qf, visited) + } else { + buf.WriteString(p.name) + } + } + if prev != nil { + buf.WriteByte(' ') + writeType(buf, prev, qf, visited) + } + buf.WriteByte(']') +} + +func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) { + s := "<Named w/o object>" + if obj != nil { + if obj.pkg != nil { + writePackage(buf, obj.pkg, qf) + } + // TODO(gri): function-local named types should be displayed + // differently from named types at package level to avoid + // ambiguity. + s = obj.name + } + buf.WriteString(s) +} + func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visited []Type) { buf.WriteByte('(') if tup != nil { @@ -264,7 +380,7 @@ func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visi } else { // special case: // append(s, "foo"...) leads to signature func([]byte, string...) - if t, ok := typ.Underlying().(*Basic); !ok || t.kind != String { + if t := asBasic(typ); t == nil || t.kind != String { panic("internal error: string type expected") } writeType(buf, typ, qf, visited) @@ -287,6 +403,10 @@ func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) { } func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) { + if sig.tparams != nil { + writeTParamList(buf, sig.tparams, qf, visited) + } + writeTuple(buf, sig.params, sig.variadic, qf, visited) n := sig.results.Len() @@ -305,3 +425,19 @@ func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []T // multiple or named result(s) writeTuple(buf, sig.results, false, qf, visited) } + +// subscript returns the decimal (utf8) representation of x using subscript digits. +func subscript(x uint64) string { + const w = len("₀") // all digits 0...9 have the same utf8 width + var buf [32 * w]byte + i := len(buf) + for { + i -= w + utf8.EncodeRune(buf[i:], '₀'+rune(x%10)) // '₀' == U+2080 + x /= 10 + if x == 0 { + break + } + } + return string(buf[i:]) +} diff --git a/libgo/go/go/types/typestring_test.go b/libgo/go/go/types/typestring_test.go index a2241ca..07ed735 100644 --- a/libgo/go/go/types/typestring_test.go +++ b/libgo/go/go/types/typestring_test.go @@ -96,6 +96,10 @@ var independentTestTypes = []testEntry{ dup("interface{m()}"), dup(`interface{String() string; m(int) float32}`), + // TODO(rFindley) uncomment this once this AST is accepted, and add more test + // cases. + // dup(`interface{type int, float32, complex128}`), + // maps dup("map[string]int"), {"map[struct{x, y int}][]byte", "map[struct{x int; y int}][]byte"}, diff --git a/libgo/go/go/types/typexpr.go b/libgo/go/go/types/typexpr.go index 2b398010..1738d86 100644 --- a/libgo/go/go/types/typexpr.go +++ b/libgo/go/go/types/typexpr.go @@ -7,11 +7,14 @@ package types import ( + "fmt" "go/ast" "go/constant" + "go/internal/typeparams" "go/token" "sort" "strconv" + "strings" ) // ident type-checks identifier e and initializes x with the value or type of e. @@ -51,12 +54,12 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) } assert(typ != nil) - // The object may be dot-imported: If so, remove its package from - // the map of unused dot imports for the respective file scope. + // The object may have been dot-imported. + // If so, mark the respective package as used. // (This code is only needed for dot-imports. Without them, // we only have to mark variables, see *Var case below). - if pkg := obj.Pkg(); pkg != check.pkg && pkg != nil { - delete(check.unusedDotImports[scope], pkg) + if pkgName := check.dotImportMap[dotImportKey{scope, obj}]; pkgName != nil { + pkgName.used = true } switch obj := obj.(type) { @@ -116,41 +119,220 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) } // typ type-checks the type expression e and returns its type, or Typ[Invalid]. +// The type must not be an (uninstantiated) generic type. func (check *Checker) typ(e ast.Expr) Type { return check.definedType(e, nil) } +// varType type-checks the type expression e and returns its type, or Typ[Invalid]. +// The type must not be an (uninstantiated) generic type and it must be ordinary +// (see ordinaryType). +func (check *Checker) varType(e ast.Expr) Type { + typ := check.definedType(e, nil) + check.ordinaryType(e, typ) + return typ +} + +// ordinaryType reports an error if typ is an interface type containing +// type lists or is (or embeds) the predeclared type comparable. +func (check *Checker) ordinaryType(pos positioner, typ Type) { + // We don't want to call under() (via asInterface) or complete interfaces + // while we are in the middle of type-checking parameter declarations that + // might belong to interface methods. Delay this check to the end of + // type-checking. + check.later(func() { + if t := asInterface(typ); t != nil { + check.completeInterface(pos.Pos(), t) // TODO(gri) is this the correct position? + if t.allTypes != nil { + check.softErrorf(pos, _Todo, "interface contains type constraints (%s)", t.allTypes) + return + } + if t._IsComparable() { + check.softErrorf(pos, _Todo, "interface is (or embeds) comparable") + } + } + }) +} + +// anyType type-checks the type expression e and returns its type, or Typ[Invalid]. +// The type may be generic or instantiated. +func (check *Checker) anyType(e ast.Expr) Type { + typ := check.typInternal(e, nil) + assert(isTyped(typ)) + check.recordTypeAndValue(e, typexpr, typ, nil) + return typ +} + // definedType is like typ but also accepts a type name def. // If def != nil, e is the type specification for the defined type def, declared // in a type declaration, and def.underlying will be set to the type of e before // any components of e are type-checked. // -func (check *Checker) definedType(e ast.Expr, def *Named) (T Type) { - if trace { - check.trace(e.Pos(), "%s", e) - check.indent++ - defer func() { - check.indent-- - check.trace(e.Pos(), "=> %s", T) - }() +func (check *Checker) definedType(e ast.Expr, def *Named) Type { + typ := check.typInternal(e, def) + assert(isTyped(typ)) + if isGeneric(typ) { + check.errorf(e, _Todo, "cannot use generic type %s without instantiation", typ) + typ = Typ[Invalid] } + check.recordTypeAndValue(e, typexpr, typ, nil) + return typ +} - T = check.typInternal(e, def) - assert(isTyped(T)) - check.recordTypeAndValue(e, typexpr, T, nil) +// genericType is like typ but the type must be an (uninstantiated) generic type. +func (check *Checker) genericType(e ast.Expr, reportErr bool) Type { + typ := check.typInternal(e, nil) + assert(isTyped(typ)) + if typ != Typ[Invalid] && !isGeneric(typ) { + if reportErr { + check.errorf(e, _Todo, "%s is not a generic type", typ) + } + typ = Typ[Invalid] + } + // TODO(gri) what is the correct call below? + check.recordTypeAndValue(e, typexpr, typ, nil) + return typ +} - return +// isubst returns an x with identifiers substituted per the substitution map smap. +// isubst only handles the case of (valid) method receiver type expressions correctly. +func isubst(x ast.Expr, smap map[*ast.Ident]*ast.Ident) ast.Expr { + switch n := x.(type) { + case *ast.Ident: + if alt := smap[n]; alt != nil { + return alt + } + case *ast.StarExpr: + X := isubst(n.X, smap) + if X != n.X { + new := *n + new.X = X + return &new + } + case *ast.IndexExpr: + elems := typeparams.UnpackExpr(n.Index) + var newElems []ast.Expr + for i, elem := range elems { + new := isubst(elem, smap) + if new != elem { + if newElems == nil { + newElems = make([]ast.Expr, len(elems)) + copy(newElems, elems) + } + newElems[i] = new + } + } + if newElems != nil { + index := typeparams.PackExpr(newElems) + new := *n + new.Index = index + return &new + } + case *ast.ParenExpr: + return isubst(n.X, smap) // no need to keep parentheses + default: + // Other receiver type expressions are invalid. + // It's fine to ignore those here as they will + // be checked elsewhere. + } + return x } // funcType type-checks a function or method type. func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast.FuncType) { - scope := NewScope(check.scope, token.NoPos, token.NoPos, "function") - scope.isFunc = true - check.recordScope(ftyp, scope) + check.openScope(ftyp, "function") + check.scope.isFunc = true + check.recordScope(ftyp, check.scope) + sig.scope = check.scope + defer check.closeScope() + + var recvTyp ast.Expr // rewritten receiver type; valid if != nil + if recvPar != nil && len(recvPar.List) > 0 { + // collect generic receiver type parameters, if any + // - a receiver type parameter is like any other type parameter, except that it is declared implicitly + // - the receiver specification acts as local declaration for its type parameters, which may be blank + _, rname, rparams := check.unpackRecv(recvPar.List[0].Type, true) + if len(rparams) > 0 { + // Blank identifiers don't get declared and regular type-checking of the instantiated + // parameterized receiver type expression fails in Checker.collectParams of receiver. + // Identify blank type parameters and substitute each with a unique new identifier named + // "n_" (where n is the parameter index) and which cannot conflict with any user-defined + // name. + var smap map[*ast.Ident]*ast.Ident // substitution map from "_" to "n_" identifiers + for i, p := range rparams { + if p.Name == "_" { + new := *p + new.Name = fmt.Sprintf("%d_", i) + rparams[i] = &new // use n_ identifier instead of _ so it can be looked up + if smap == nil { + smap = make(map[*ast.Ident]*ast.Ident) + } + smap[p] = &new + } + } + if smap != nil { + // blank identifiers were found => use rewritten receiver type + recvTyp = isubst(recvPar.List[0].Type, smap) + } + sig.rparams = check.declareTypeParams(nil, rparams) + // determine receiver type to get its type parameters + // and the respective type parameter bounds + var recvTParams []*TypeName + if rname != nil { + // recv should be a Named type (otherwise an error is reported elsewhere) + // Also: Don't report an error via genericType since it will be reported + // again when we type-check the signature. + // TODO(gri) maybe the receiver should be marked as invalid instead? + if recv := asNamed(check.genericType(rname, false)); recv != nil { + recvTParams = recv.tparams + } + } + // provide type parameter bounds + // - only do this if we have the right number (otherwise an error is reported elsewhere) + if len(sig.rparams) == len(recvTParams) { + // We have a list of *TypeNames but we need a list of Types. + list := make([]Type, len(sig.rparams)) + for i, t := range sig.rparams { + list[i] = t.typ + } + smap := makeSubstMap(recvTParams, list) + for i, tname := range sig.rparams { + bound := recvTParams[i].typ.(*_TypeParam).bound + // bound is (possibly) parameterized in the context of the + // receiver type declaration. Substitute parameters for the + // current context. + // TODO(gri) should we assume now that bounds always exist? + // (no bound == empty interface) + if bound != nil { + bound = check.subst(tname.pos, bound, smap) + tname.typ.(*_TypeParam).bound = bound + } + } + } + } + } - recvList, _ := check.collectParams(scope, recvPar, false) - params, variadic := check.collectParams(scope, ftyp.Params, true) - results, _ := check.collectParams(scope, ftyp.Results, false) + if tparams := typeparams.Get(ftyp); tparams != nil { + sig.tparams = check.collectTypeParams(tparams) + // Always type-check method type parameters but complain that they are not allowed. + // (A separate check is needed when type-checking interface method signatures because + // they don't have a receiver specification.) + if recvPar != nil { + check.errorf(tparams, _Todo, "methods cannot have type parameters") + } + } + + // Value (non-type) parameters' scope starts in the function body. Use a temporary scope for their + // declarations and then squash that scope into the parent scope (and report any redeclarations at + // that time). + scope := NewScope(check.scope, token.NoPos, token.NoPos, "function body (temp. scope)") + recvList, _ := check.collectParams(scope, recvPar, recvTyp, false) // use rewritten receiver type, if any + params, variadic := check.collectParams(scope, ftyp.Params, nil, true) + results, _ := check.collectParams(scope, ftyp.Results, nil, false) + scope.squash(func(obj, alt Object) { + check.errorf(obj, _DuplicateDecl, "%s redeclared in this block", obj.Name()) + check.reportAltDecl(alt) + }) if recvPar != nil { // recv parameter list present (may be empty) @@ -159,7 +341,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast var recv *Var switch len(recvList) { case 0: - check.error(recvPar, _BadRecv, "method is missing receiver") + // error reported by resolver recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below default: // more than one receiver @@ -168,19 +350,24 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast case 1: recv = recvList[0] } + + // TODO(gri) We should delay rtyp expansion to when we actually need the + // receiver; thus all checks here should be delayed to later. + rtyp, _ := deref(recv.typ) + rtyp = expand(rtyp) + // spec: "The receiver type must be of the form T or *T where T is a type name." // (ignore invalid types - error was reported before) - if t, _ := deref(recv.typ); t != Typ[Invalid] { + if t := rtyp; t != Typ[Invalid] { var err string - if T, _ := t.(*Named); T != nil { + if T := asNamed(t); T != nil { // spec: "The type denoted by T is called the receiver base type; it must not // be a pointer or interface type and it must be declared in the same package // as the method." if T.obj.pkg != check.pkg { err = "type not defined in this package" } else { - // TODO(gri) This is not correct if the underlying type is unknown yet. - switch u := T.underlying.(type) { + switch u := optype(T).(type) { case *Basic: // unsafe.Pointer is treated like a regular pointer if u.kind == UnsafePointer { @@ -201,17 +388,43 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast sig.recv = recv } - sig.scope = scope sig.params = NewTuple(params...) sig.results = NewTuple(results...) sig.variadic = variadic } +// goTypeName returns the Go type name for typ and +// removes any occurrences of "types." from that name. +func goTypeName(typ Type) string { + return strings.ReplaceAll(fmt.Sprintf("%T", typ), "types.", "") +} + // typInternal drives type checking of types. -// Must only be called by definedType. +// Must only be called by definedType or genericType. // -func (check *Checker) typInternal(e ast.Expr, def *Named) Type { - switch e := e.(type) { +func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { + if trace { + check.trace(e0.Pos(), "type %s", e0) + check.indent++ + defer func() { + check.indent-- + var under Type + if T != nil { + // Calling under() here may lead to endless instantiations. + // Test case: type T[P any] *T[P] + // TODO(gri) investigate if that's a bug or to be expected + // (see also analogous comment in Checker.instantiate). + under = T.Underlying() + } + if T == under { + check.trace(e0.Pos(), "=> %s // %s", T, goTypeName(T)) + } else { + check.trace(e0.Pos(), "=> %s (under = %s) // %s", T, under, goTypeName(T)) + } + }() + } + + switch e := e0.(type) { case *ast.BadExpr: // ignore - error reported before @@ -249,7 +462,17 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type { check.errorf(&x, _NotAType, "%s is not a type", &x) } + case *ast.IndexExpr: + if typeparams.Enabled { + exprs := typeparams.UnpackExpr(e.Index) + return check.instantiatedType(e.X, exprs, def) + } + check.errorf(e0, _NotAType, "%s is not a type", e0) + check.use(e.X) + case *ast.ParenExpr: + // Generic types must be instantiated before they can be used in any form. + // Consequently, generic types cannot be parenthesized. return check.definedType(e.X, def) case *ast.ArrayType: @@ -257,16 +480,21 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type { typ := new(Array) def.setUnderlying(typ) typ.len = check.arrayLength(e.Len) - typ.elem = check.typ(e.Elt) - return typ - - } else { - typ := new(Slice) - def.setUnderlying(typ) - typ.elem = check.typ(e.Elt) + typ.elem = check.varType(e.Elt) return typ } + typ := new(Slice) + def.setUnderlying(typ) + typ.elem = check.varType(e.Elt) + return typ + + case *ast.Ellipsis: + // dots are handled explicitly where they are legal + // (array composite literals and parameter lists) + check.error(e, _InvalidDotDotDot, "invalid use of '...'") + check.use(e.Elt) + case *ast.StructType: typ := new(Struct) def.setUnderlying(typ) @@ -276,7 +504,7 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type { case *ast.StarExpr: typ := new(Pointer) def.setUnderlying(typ) - typ.base = check.typ(e.X) + typ.base = check.varType(e.X) return typ case *ast.FuncType: @@ -288,6 +516,9 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type { case *ast.InterfaceType: typ := new(Interface) def.setUnderlying(typ) + if def != nil { + typ.obj = def.obj + } check.interfaceType(typ, e, def) return typ @@ -295,8 +526,8 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type { typ := new(Map) def.setUnderlying(typ) - typ.key = check.typ(e.Key) - typ.elem = check.typ(e.Value) + typ.key = check.varType(e.Key) + typ.elem = check.varType(e.Value) // spec: "The comparison operators == and != must be fully defined // for operands of the key type; thus the key type must not be a @@ -304,9 +535,13 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type { // // Delay this check because it requires fully setup types; // it is safe to continue in any case (was issue 6667). - check.atEnd(func() { + check.later(func() { if !Comparable(typ.key) { - check.errorf(e.Key, _IncomparableMapKey, "incomparable map key type %s", typ.key) + var why string + if asTypeParam(typ.key) != nil { + why = " (missing comparable constraint)" + } + check.errorf(e.Key, _IncomparableMapKey, "incomparable map key type %s%s", typ.key, why) } }) @@ -330,11 +565,11 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type { } typ.dir = dir - typ.elem = check.typ(e.Value) + typ.elem = check.varType(e.Value) return typ default: - check.errorf(e, _NotAType, "%s is not a type", e) + check.errorf(e0, _NotAType, "%s is not a type", e0) } typ := Typ[Invalid] @@ -343,10 +578,11 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type { } // typeOrNil type-checks the type expression (or nil value) e -// and returns the typ of e, or nil. -// If e is neither a type nor nil, typOrNil returns Typ[Invalid]. -// -func (check *Checker) typOrNil(e ast.Expr) Type { +// and returns the type of e, or nil. If e is a type, it must +// not be an (uninstantiated) generic type. +// If e is neither a type nor nil, typeOrNil returns Typ[Invalid]. +// TODO(gri) should we also disallow non-var types? +func (check *Checker) typeOrNil(e ast.Expr) Type { var x operand check.rawExpr(&x, e, nil) switch x.mode { @@ -355,6 +591,7 @@ func (check *Checker) typOrNil(e ast.Expr) Type { case novalue: check.errorf(&x, _NotAType, "%s used as type", &x) case typexpr: + check.instantiatedOperand(&x) return x.typ case value: if x.isNil() { @@ -367,6 +604,49 @@ func (check *Checker) typOrNil(e ast.Expr) Type { return Typ[Invalid] } +func (check *Checker) instantiatedType(x ast.Expr, targs []ast.Expr, def *Named) Type { + b := check.genericType(x, true) // TODO(gri) what about cycles? + if b == Typ[Invalid] { + return b // error already reported + } + base := asNamed(b) + if base == nil { + unreachable() // should have been caught by genericType + } + + // create a new type instance rather than instantiate the type + // TODO(gri) should do argument number check here rather than + // when instantiating the type? + typ := new(instance) + def.setUnderlying(typ) + + typ.check = check + typ.pos = x.Pos() + typ.base = base + + // evaluate arguments (always) + typ.targs = check.typeList(targs) + if typ.targs == nil { + def.setUnderlying(Typ[Invalid]) // avoid later errors due to lazy instantiation + return Typ[Invalid] + } + + // determine argument positions (for error reporting) + typ.poslist = make([]token.Pos, len(targs)) + for i, arg := range targs { + typ.poslist[i] = arg.Pos() + } + + // make sure we check instantiation works at least once + // and that the resulting type is valid + check.later(func() { + t := typ.expand() + check.validType(t, nil) + }) + + return typ +} + // arrayLength type-checks the array length expression e // and returns the constant length >= 0, or a value < 0 // to indicate an error (and thus an unknown length). @@ -394,7 +674,25 @@ func (check *Checker) arrayLength(e ast.Expr) int64 { return -1 } -func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, variadic bool) { +// typeList provides the list of types corresponding to the incoming expression list. +// If an error occurred, the result is nil, but all list elements were type-checked. +func (check *Checker) typeList(list []ast.Expr) []Type { + res := make([]Type, len(list)) // res != nil even if len(list) == 0 + for i, x := range list { + t := check.varType(x) + if t == Typ[Invalid] { + res = nil + } + if res != nil { + res[i] = t + } + } + return res +} + +// collectParams declares the parameters of list in scope and returns the corresponding +// variable list. If type0 != nil, it is used instead of the first type in list. +func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, type0 ast.Expr, variadicOk bool) (params []*Var, variadic bool) { if list == nil { return } @@ -402,6 +700,9 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicO var named, anonymous bool for i, field := range list.List { ftype := field.Type + if i == 0 && type0 != nil { + ftype = type0 + } if t, _ := ftype.(*ast.Ellipsis); t != nil { ftype = t.Elt if variadicOk && i == len(list.List)-1 && len(field.Names) <= 1 { @@ -411,7 +712,7 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicO // ignore ... and continue } } - typ := check.typ(ftype) + typ := check.varType(ftype) // The parser ensures that f.Tag is nil and we don't // care if a constructed AST contains a non-nil tag. if len(field.Names) > 0 { @@ -462,9 +763,12 @@ func (check *Checker) declareInSet(oset *objset, pos token.Pos, obj Object) bool } func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) { + var tlist *ast.Ident // "type" name of first entry in a type list declaration + var types []ast.Expr for _, f := range iface.Methods.List { if len(f.Names) > 0 { - // We have a method with name f.Names[0]. + // We have a method with name f.Names[0], or a type + // of a type list (name.Name == "type"). // (The parser ensures that there's only one method // and we don't care if a constructed AST has more.) name := f.Names[0] @@ -473,6 +777,18 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d continue // ignore } + if name.Name == "type" { + // Always collect all type list entries, even from + // different type lists, under the assumption that + // the author intended to include all types. + types = append(types, f.Type) + if tlist != nil && tlist != name { + check.errorf(name, _Todo, "cannot have multiple type lists in an interface") + } + tlist = name + continue + } + typ := check.typ(f.Type) sig, _ := typ.(*Signature) if sig == nil { @@ -482,6 +798,17 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d continue // ignore } + // Always type-check method type parameters but complain if they are not enabled. + // (This extra check is needed here because interface method signatures don't have + // a receiver specification.) + if sig.tparams != nil { + var at positioner = f.Type + if tparams := typeparams.Get(f.Type); tparams != nil { + at = tparams + } + check.errorf(at, _Todo, "methods cannot have type parameters") + } + // use named receiver type if available (for better error messages) var recvTyp Type = ityp if def != nil { @@ -493,38 +820,30 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d check.recordDef(name, m) ityp.methods = append(ityp.methods, m) } else { - // We have an embedded interface and f.Type is its - // (possibly qualified) embedded type name. Collect - // it if it's a valid interface. - typ := check.typ(f.Type) - - utyp := check.underlying(typ) - if _, ok := utyp.(*Interface); !ok { - if utyp != Typ[Invalid] { - check.errorf(f.Type, _InvalidIfaceEmbed, "%s is not an interface", typ) - } - continue - } - - ityp.embeddeds = append(ityp.embeddeds, typ) + // We have an embedded type. completeInterface will + // eventually verify that we have an interface. + ityp.embeddeds = append(ityp.embeddeds, check.typ(f.Type)) check.posMap[ityp] = append(check.posMap[ityp], f.Type.Pos()) } } - if len(ityp.methods) == 0 && len(ityp.embeddeds) == 0 { + // type constraints + ityp.types = _NewSum(check.collectTypeConstraints(iface.Pos(), types)) + + if len(ityp.methods) == 0 && ityp.types == nil && len(ityp.embeddeds) == 0 { // empty interface ityp.allMethods = markComplete return } // sort for API stability - sort.Sort(byUniqueMethodName(ityp.methods)) - sort.Stable(byUniqueTypeName(ityp.embeddeds)) + sortMethods(ityp.methods) + sortTypes(ityp.embeddeds) - check.later(func() { check.completeInterface(ityp) }) + check.later(func() { check.completeInterface(iface.Pos(), ityp) }) } -func (check *Checker) completeInterface(ityp *Interface) { +func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) { if ityp.allMethods != nil { return } @@ -538,11 +857,18 @@ func (check *Checker) completeInterface(ityp *Interface) { } if trace { - check.trace(token.NoPos, "complete %s", ityp) + // Types don't generally have position information. + // If we don't have a valid pos provided, try to use + // one close enough. + if !pos.IsValid() && len(ityp.methods) > 0 { + pos = ityp.methods[0].pos + } + + check.trace(pos, "complete %s", ityp) check.indent++ defer func() { check.indent-- - check.trace(token.NoPos, "=> %s", ityp) + check.trace(pos, "=> %s (methods = %v, types = %v)", ityp, ityp.allMethods, ityp.allTypes) }() } @@ -578,9 +904,13 @@ func (check *Checker) completeInterface(ityp *Interface) { check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented default: - // check method signatures after all types are computed (issue #33656) - check.atEnd(func() { - if !check.identical(m.typ, other.Type()) { + // We have a duplicate method name in an embedded (not explicitly declared) method. + // Check method signatures after all types are computed (issue #33656). + // If we're pre-go1.14 (overlapping embeddings are not permitted), report that + // error here as well (even though we could do it eagerly) because it's the same + // error message. + check.later(func() { + if !check.allowVersion(m.pkg, 1, 14) || !check.identical(m.typ, other.Type()) { check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented } @@ -592,25 +922,81 @@ func (check *Checker) completeInterface(ityp *Interface) { addMethod(m.pos, m, true) } + // collect types + allTypes := ityp.types + posList := check.posMap[ityp] for i, typ := range ityp.embeddeds { pos := posList[i] // embedding position - typ, ok := check.underlying(typ).(*Interface) - if !ok { - // An error was reported when collecting the embedded types. - // Ignore it. + utyp := under(typ) + etyp := asInterface(utyp) + if etyp == nil { + if utyp != Typ[Invalid] { + var format string + if _, ok := utyp.(*_TypeParam); ok { + format = "%s is a type parameter, not an interface" + } else { + format = "%s is not an interface" + } + // TODO: correct error code. + check.errorf(atPos(pos), _InvalidIfaceEmbed, format, typ) + } continue } - check.completeInterface(typ) - for _, m := range typ.allMethods { + check.completeInterface(pos, etyp) + for _, m := range etyp.allMethods { addMethod(pos, m, false) // use embedding position pos rather than m.pos } + allTypes = intersect(allTypes, etyp.allTypes) } if methods != nil { sort.Sort(byUniqueMethodName(methods)) ityp.allMethods = methods } + ityp.allTypes = allTypes +} + +// intersect computes the intersection of the types x and y. +// Note: A incomming nil type stands for the top type. A top +// type result is returned as nil. +func intersect(x, y Type) (r Type) { + defer func() { + if r == theTop { + r = nil + } + }() + + switch { + case x == theBottom || y == theBottom: + return theBottom + case x == nil || x == theTop: + return y + case y == nil || x == theTop: + return x + } + + xtypes := unpackType(x) + ytypes := unpackType(y) + // Compute the list rtypes which includes only + // types that are in both xtypes and ytypes. + // Quadratic algorithm, but good enough for now. + // TODO(gri) fix this + var rtypes []Type + for _, x := range xtypes { + if includes(ytypes, x) { + rtypes = append(rtypes, x) + } + } + + if rtypes == nil { + return theBottom + } + return _NewSum(rtypes) +} + +func sortTypes(list []Type) { + sort.Stable(byUniqueTypeName(list)) } // byUniqueTypeName named type lists can be sorted by their unique type names. @@ -621,12 +1007,25 @@ func (a byUniqueTypeName) Less(i, j int) bool { return sortName(a[i]) < sortName func (a byUniqueTypeName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func sortName(t Type) string { - if named, _ := t.(*Named); named != nil { + if named := asNamed(t); named != nil { return named.obj.Id() } return "" } +func sortMethods(list []*Func) { + sort.Sort(byUniqueMethodName(list)) +} + +func assertSortedMethods(list []*Func) { + if !debug { + panic("internal error: assertSortedMethods called outside debug mode") + } + if !sort.IsSorted(byUniqueMethodName(list)) { + panic("internal error: methods not sorted") + } +} + // byUniqueMethodName method lists can be sorted by their unique method names. type byUniqueMethodName []*Func @@ -690,7 +1089,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) { } for _, f := range list.List { - typ = check.typ(f.Type) + typ = check.varType(f.Type) tag = check.tag(f.Tag) if len(f.Names) > 0 { // named fields @@ -699,48 +1098,51 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) { } } else { // embedded field - // spec: "An embedded type must be specified as a type name T or as a pointer - // to a non-interface type name *T, and T itself may not be a pointer type." + // spec: "An embedded type must be specified as a type name T or as a + // pointer to a non-interface type name *T, and T itself may not be a + // pointer type." pos := f.Type.Pos() name := embeddedFieldIdent(f.Type) if name == nil { - check.invalidAST(f.Type, "embedded field type %s has no name", f.Type) + // TODO(rFindley): using invalidAST here causes test failures (all + // errors should have codes). Clean this up. + check.errorf(f.Type, _Todo, "invalid AST: embedded field type %s has no name", f.Type) name = ast.NewIdent("_") name.NamePos = pos addInvalid(name, pos) continue } - t, isPtr := deref(typ) + add(name, true, pos) + // Because we have a name, typ must be of the form T or *T, where T is the name // of a (named or alias) type, and t (= deref(typ)) must be the type of T. - switch t := t.Underlying().(type) { - case *Basic: - if t == Typ[Invalid] { - // error was reported before - addInvalid(name, pos) - continue - } - - // unsafe.Pointer is treated like a regular pointer - if t.kind == UnsafePointer { - check.errorf(f.Type, _InvalidPtrEmbed, "embedded field type cannot be unsafe.Pointer") - addInvalid(name, pos) - continue - } - - case *Pointer: - check.errorf(f.Type, _InvalidPtrEmbed, "embedded field type cannot be a pointer") - addInvalid(name, pos) - continue - - case *Interface: - if isPtr { - check.errorf(f.Type, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface") - addInvalid(name, pos) - continue + // We must delay this check to the end because we don't want to instantiate + // (via under(t)) a possibly incomplete type. + + // for use in the closure below + embeddedTyp := typ + embeddedPos := f.Type + + check.later(func() { + t, isPtr := deref(embeddedTyp) + switch t := optype(t).(type) { + case *Basic: + if t == Typ[Invalid] { + // error was reported before + return + } + // unsafe.Pointer is treated like a regular pointer + if t.kind == UnsafePointer { + check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be unsafe.Pointer") + } + case *Pointer: + check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer") + case *Interface: + if isPtr { + check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface") + } } - } - add(name, true, pos) + }) } } @@ -759,6 +1161,46 @@ func embeddedFieldIdent(e ast.Expr) *ast.Ident { } case *ast.SelectorExpr: return e.Sel + case *ast.IndexExpr: + return embeddedFieldIdent(e.X) } return nil // invalid embedded field } + +func (check *Checker) collectTypeConstraints(pos token.Pos, types []ast.Expr) []Type { + list := make([]Type, 0, len(types)) // assume all types are correct + for _, texpr := range types { + if texpr == nil { + check.invalidAST(atPos(pos), "missing type constraint") + continue + } + list = append(list, check.varType(texpr)) + } + + // Ensure that each type is only present once in the type list. Types may be + // interfaces, which may not be complete yet. It's ok to do this check at the + // end because it's not a requirement for correctness of the code. + // Note: This is a quadratic algorithm, but type lists tend to be short. + check.later(func() { + for i, t := range list { + if t := asInterface(t); t != nil { + check.completeInterface(types[i].Pos(), t) + } + if includes(list[:i], t) { + check.softErrorf(types[i], _Todo, "duplicate type %s in type list", t) + } + } + }) + + return list +} + +// includes reports whether typ is in list. +func includes(list []Type, typ Type) bool { + for _, e := range list { + if Identical(typ, e) { + return true + } + } + return false +} diff --git a/libgo/go/go/types/unify.go b/libgo/go/go/types/unify.go new file mode 100644 index 0000000..db06e21 --- /dev/null +++ b/libgo/go/go/types/unify.go @@ -0,0 +1,469 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file implements type unification. + +package types + +import ( + "bytes" + "go/token" + "sort" +) + +// The unifier maintains two separate sets of type parameters x and y +// which are used to resolve type parameters in the x and y arguments +// provided to the unify call. For unidirectional unification, only +// one of these sets (say x) is provided, and then type parameters are +// only resolved for the x argument passed to unify, not the y argument +// (even if that also contains possibly the same type parameters). This +// is crucial to infer the type parameters of self-recursive calls: +// +// func f[P any](a P) { f(a) } +// +// For the call f(a) we want to infer that the type argument for P is P. +// During unification, the parameter type P must be resolved to the type +// parameter P ("x" side), but the argument type P must be left alone so +// that unification resolves the type parameter P to P. +// +// For bidirection unification, both sets are provided. This enables +// unification to go from argument to parameter type and vice versa. +// For constraint type inference, we use bidirectional unification +// where both the x and y type parameters are identical. This is done +// by setting up one of them (using init) and then assigning its value +// to the other. + +// A unifier maintains the current type parameters for x and y +// and the respective types inferred for each type parameter. +// A unifier is created by calling newUnifier. +type unifier struct { + check *Checker + exact bool + x, y tparamsList // x and y must initialized via tparamsList.init + types []Type // inferred types, shared by x and y +} + +// newUnifier returns a new unifier. +// If exact is set, unification requires unified types to match +// exactly. If exact is not set, a named type's underlying type +// is considered if unification would fail otherwise, and the +// direction of channels is ignored. +func newUnifier(check *Checker, exact bool) *unifier { + u := &unifier{check: check, exact: exact} + u.x.unifier = u + u.y.unifier = u + return u +} + +// unify attempts to unify x and y and reports whether it succeeded. +func (u *unifier) unify(x, y Type) bool { + return u.nify(x, y, nil) +} + +// A tparamsList describes a list of type parameters and the types inferred for them. +type tparamsList struct { + unifier *unifier + tparams []*TypeName + // For each tparams element, there is a corresponding type slot index in indices. + // index < 0: unifier.types[-index-1] == nil + // index == 0: no type slot allocated yet + // index > 0: unifier.types[index-1] == typ + // Joined tparams elements share the same type slot and thus have the same index. + // By using a negative index for nil types we don't need to check unifier.types + // to see if we have a type or not. + indices []int // len(d.indices) == len(d.tparams) +} + +// String returns a string representation for a tparamsList. For debugging. +func (d *tparamsList) String() string { + var buf bytes.Buffer + buf.WriteByte('[') + for i, tname := range d.tparams { + if i > 0 { + buf.WriteString(", ") + } + writeType(&buf, tname.typ, nil, nil) + buf.WriteString(": ") + writeType(&buf, d.at(i), nil, nil) + } + buf.WriteByte(']') + return buf.String() +} + +// init initializes d with the given type parameters. +// The type parameters must be in the order in which they appear in their declaration +// (this ensures that the tparams indices match the respective type parameter index). +func (d *tparamsList) init(tparams []*TypeName) { + if len(tparams) == 0 { + return + } + if debug { + for i, tpar := range tparams { + assert(i == tpar.typ.(*_TypeParam).index) + } + } + d.tparams = tparams + d.indices = make([]int, len(tparams)) +} + +// join unifies the i'th type parameter of x with the j'th type parameter of y. +// If both type parameters already have a type associated with them and they are +// not joined, join fails and return false. +func (u *unifier) join(i, j int) bool { + ti := u.x.indices[i] + tj := u.y.indices[j] + switch { + case ti == 0 && tj == 0: + // Neither type parameter has a type slot associated with them. + // Allocate a new joined nil type slot (negative index). + u.types = append(u.types, nil) + u.x.indices[i] = -len(u.types) + u.y.indices[j] = -len(u.types) + case ti == 0: + // The type parameter for x has no type slot yet. Use slot of y. + u.x.indices[i] = tj + case tj == 0: + // The type parameter for y has no type slot yet. Use slot of x. + u.y.indices[j] = ti + + // Both type parameters have a slot: ti != 0 && tj != 0. + case ti == tj: + // Both type parameters already share the same slot. Nothing to do. + break + case ti > 0 && tj > 0: + // Both type parameters have (possibly different) inferred types. Cannot join. + return false + case ti > 0: + // Only the type parameter for x has an inferred type. Use x slot for y. + u.y.setIndex(j, ti) + default: + // Either the type parameter for y has an inferred type, or neither type + // parameter has an inferred type. In either case, use y slot for x. + u.x.setIndex(i, tj) + } + return true +} + +// If typ is a type parameter of d, index returns the type parameter index. +// Otherwise, the result is < 0. +func (d *tparamsList) index(typ Type) int { + if t, ok := typ.(*_TypeParam); ok { + if i := t.index; i < len(d.tparams) && d.tparams[i].typ == t { + return i + } + } + return -1 +} + +// setIndex sets the type slot index for the i'th type parameter +// (and all its joined parameters) to tj. The type parameter +// must have a (possibly nil) type slot associated with it. +func (d *tparamsList) setIndex(i, tj int) { + ti := d.indices[i] + assert(ti != 0 && tj != 0) + for k, tk := range d.indices { + if tk == ti { + d.indices[k] = tj + } + } +} + +// at returns the type set for the i'th type parameter; or nil. +func (d *tparamsList) at(i int) Type { + if ti := d.indices[i]; ti > 0 { + return d.unifier.types[ti-1] + } + return nil +} + +// set sets the type typ for the i'th type parameter; +// typ must not be nil and it must not have been set before. +func (d *tparamsList) set(i int, typ Type) { + assert(typ != nil) + u := d.unifier + switch ti := d.indices[i]; { + case ti < 0: + u.types[-ti-1] = typ + d.setIndex(i, -ti) + case ti == 0: + u.types = append(u.types, typ) + d.indices[i] = len(u.types) + default: + panic("type already set") + } +} + +// types returns the list of inferred types (via unification) for the type parameters +// described by d, and an index. If all types were inferred, the returned index is < 0. +// Otherwise, it is the index of the first type parameter which couldn't be inferred; +// i.e., for which list[index] is nil. +func (d *tparamsList) types() (list []Type, index int) { + list = make([]Type, len(d.tparams)) + index = -1 + for i := range d.tparams { + t := d.at(i) + list[i] = t + if index < 0 && t == nil { + index = i + } + } + return +} + +func (u *unifier) nifyEq(x, y Type, p *ifacePair) bool { + return x == y || u.nify(x, y, p) +} + +// nify implements the core unification algorithm which is an +// adapted version of Checker.identical0. For changes to that +// code the corresponding changes should be made here. +// Must not be called directly from outside the unifier. +func (u *unifier) nify(x, y Type, p *ifacePair) bool { + // types must be expanded for comparison + x = expand(x) + y = expand(y) + + if !u.exact { + // If exact unification is known to fail because we attempt to + // match a type name against an unnamed type literal, consider + // the underlying type of the named type. + // (Subtle: We use isNamed to include any type with a name (incl. + // basic types and type parameters. We use asNamed() because we only + // want *Named types.) + switch { + case !isNamed(x) && y != nil && asNamed(y) != nil: + return u.nify(x, under(y), p) + case x != nil && asNamed(x) != nil && !isNamed(y): + return u.nify(under(x), y, p) + } + } + + // Cases where at least one of x or y is a type parameter. + switch i, j := u.x.index(x), u.y.index(y); { + case i >= 0 && j >= 0: + // both x and y are type parameters + if u.join(i, j) { + return true + } + // both x and y have an inferred type - they must match + return u.nifyEq(u.x.at(i), u.y.at(j), p) + + case i >= 0: + // x is a type parameter, y is not + if tx := u.x.at(i); tx != nil { + return u.nifyEq(tx, y, p) + } + // otherwise, infer type from y + u.x.set(i, y) + return true + + case j >= 0: + // y is a type parameter, x is not + if ty := u.y.at(j); ty != nil { + return u.nifyEq(x, ty, p) + } + // otherwise, infer type from x + u.y.set(j, x) + return true + } + + // For type unification, do not shortcut (x == y) for identical + // types. Instead keep comparing them element-wise to unify the + // matching (and equal type parameter types). A simple test case + // where this matters is: func f[P any](a P) { f(a) } . + + switch x := x.(type) { + case *Basic: + // Basic types are singletons except for the rune and byte + // aliases, thus we cannot solely rely on the x == y check + // above. See also comment in TypeName.IsAlias. + if y, ok := y.(*Basic); ok { + return x.kind == y.kind + } + + case *Array: + // Two array types are identical if they have identical element types + // and the same array length. + if y, ok := y.(*Array); ok { + // If one or both array lengths are unknown (< 0) due to some error, + // assume they are the same to avoid spurious follow-on errors. + return (x.len < 0 || y.len < 0 || x.len == y.len) && u.nify(x.elem, y.elem, p) + } + + case *Slice: + // Two slice types are identical if they have identical element types. + if y, ok := y.(*Slice); ok { + return u.nify(x.elem, y.elem, p) + } + + case *Struct: + // Two struct types are identical if they have the same sequence of fields, + // and if corresponding fields have the same names, and identical types, + // and identical tags. Two embedded fields are considered to have the same + // name. Lower-case field names from different packages are always different. + if y, ok := y.(*Struct); ok { + if x.NumFields() == y.NumFields() { + for i, f := range x.fields { + g := y.fields[i] + if f.embedded != g.embedded || + x.Tag(i) != y.Tag(i) || + !f.sameId(g.pkg, g.name) || + !u.nify(f.typ, g.typ, p) { + return false + } + } + return true + } + } + + case *Pointer: + // Two pointer types are identical if they have identical base types. + if y, ok := y.(*Pointer); ok { + return u.nify(x.base, y.base, p) + } + + case *Tuple: + // Two tuples types are identical if they have the same number of elements + // and corresponding elements have identical types. + if y, ok := y.(*Tuple); ok { + if x.Len() == y.Len() { + if x != nil { + for i, v := range x.vars { + w := y.vars[i] + if !u.nify(v.typ, w.typ, p) { + return false + } + } + } + return true + } + } + + case *Signature: + // Two function types are identical if they have the same number of parameters + // and result values, corresponding parameter and result types are identical, + // and either both functions are variadic or neither is. Parameter and result + // names are not required to match. + // TODO(gri) handle type parameters or document why we can ignore them. + if y, ok := y.(*Signature); ok { + return x.variadic == y.variadic && + u.nify(x.params, y.params, p) && + u.nify(x.results, y.results, p) + } + + case *_Sum: + // This should not happen with the current internal use of sum types. + panic("type inference across sum types not implemented") + + case *Interface: + // Two interface types are identical if they have the same set of methods with + // the same names and identical function types. Lower-case method names from + // different packages are always different. The order of the methods is irrelevant. + if y, ok := y.(*Interface); ok { + // If identical0 is called (indirectly) via an external API entry point + // (such as Identical, IdenticalIgnoreTags, etc.), check is nil. But in + // that case, interfaces are expected to be complete and lazy completion + // here is not needed. + if u.check != nil { + u.check.completeInterface(token.NoPos, x) + u.check.completeInterface(token.NoPos, y) + } + a := x.allMethods + b := y.allMethods + if len(a) == len(b) { + // Interface types are the only types where cycles can occur + // that are not "terminated" via named types; and such cycles + // can only be created via method parameter types that are + // anonymous interfaces (directly or indirectly) embedding + // the current interface. Example: + // + // type T interface { + // m() interface{T} + // } + // + // If two such (differently named) interfaces are compared, + // endless recursion occurs if the cycle is not detected. + // + // If x and y were compared before, they must be equal + // (if they were not, the recursion would have stopped); + // search the ifacePair stack for the same pair. + // + // This is a quadratic algorithm, but in practice these stacks + // are extremely short (bounded by the nesting depth of interface + // type declarations that recur via parameter types, an extremely + // rare occurrence). An alternative implementation might use a + // "visited" map, but that is probably less efficient overall. + q := &ifacePair{x, y, p} + for p != nil { + if p.identical(q) { + return true // same pair was compared before + } + p = p.prev + } + if debug { + assert(sort.IsSorted(byUniqueMethodName(a))) + assert(sort.IsSorted(byUniqueMethodName(b))) + } + for i, f := range a { + g := b[i] + if f.Id() != g.Id() || !u.nify(f.typ, g.typ, q) { + return false + } + } + return true + } + } + + case *Map: + // Two map types are identical if they have identical key and value types. + if y, ok := y.(*Map); ok { + return u.nify(x.key, y.key, p) && u.nify(x.elem, y.elem, p) + } + + case *Chan: + // Two channel types are identical if they have identical value types. + if y, ok := y.(*Chan); ok { + return (!u.exact || x.dir == y.dir) && u.nify(x.elem, y.elem, p) + } + + case *Named: + // Two named types are identical if their type names originate + // in the same type declaration. + // if y, ok := y.(*Named); ok { + // return x.obj == y.obj + // } + if y, ok := y.(*Named); ok { + // TODO(gri) This is not always correct: two types may have the same names + // in the same package if one of them is nested in a function. + // Extremely unlikely but we need an always correct solution. + if x.obj.pkg == y.obj.pkg && x.obj.name == y.obj.name { + assert(len(x.targs) == len(y.targs)) + for i, x := range x.targs { + if !u.nify(x, y.targs[i], p) { + return false + } + } + return true + } + } + + case *_TypeParam: + // Two type parameters (which are not part of the type parameters of the + // enclosing type as those are handled in the beginning of this function) + // are identical if they originate in the same declaration. + return x == y + + // case *instance: + // unreachable since types are expanded + + case nil: + // avoid a crash in case of nil type + + default: + u.check.dump("### u.nify(%s, %s), u.x.tparams = %s", x, y, u.x.tparams) + unreachable() + } + + return false +} diff --git a/libgo/go/go/types/universe.go b/libgo/go/go/types/universe.go index ff5b891..d7feb2c 100644 --- a/libgo/go/go/types/universe.go +++ b/libgo/go/go/types/universe.go @@ -8,6 +8,7 @@ package types import ( "go/constant" + "go/internal/typeparams" "go/token" "strings" ) @@ -24,6 +25,7 @@ var ( universeIota *Const universeByte *Basic // uint8 alias, but has name "byte" universeRune *Basic // int32 alias, but has name "rune" + universeAny *Interface universeError *Named ) @@ -77,13 +79,21 @@ func defPredeclaredTypes() { def(NewTypeName(token.NoPos, nil, t.name, t)) } + // any + // (Predeclared and entered into universe scope so we do all the + // usual checks; but removed again from scope later since it's + // only visible as constraint in a type parameter list.) + def(NewTypeName(token.NoPos, nil, "any", &emptyInterface)) + // Error has a nil package in its qualified name since it is in no package - res := NewVar(token.NoPos, nil, "", Typ[String]) - sig := &Signature{results: NewTuple(res)} - err := NewFunc(token.NoPos, nil, "Error", sig) - typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil).Complete()} - sig.recv = NewVar(token.NoPos, nil, "", typ) - def(NewTypeName(token.NoPos, nil, "error", typ)) + { + res := NewVar(token.NoPos, nil, "", Typ[String]) + sig := &Signature{results: NewTuple(res)} + err := NewFunc(token.NoPos, nil, "Error", sig) + typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil).Complete()} + sig.recv = NewVar(token.NoPos, nil, "", typ) + def(NewTypeName(token.NoPos, nil, "error", typ)) + } } var predeclaredConsts = [...]struct { @@ -128,9 +138,11 @@ const ( _Recover // package unsafe + _Add _Alignof _Offsetof _Sizeof + _Slice // testing support _Assert @@ -159,9 +171,11 @@ var predeclaredFuncs = [...]struct { _Real: {"real", 1, false, expression}, _Recover: {"recover", 0, false, statement}, + _Add: {"Add", 2, false, expression}, _Alignof: {"Alignof", 1, false, expression}, _Offsetof: {"Offsetof", 1, false, expression}, _Sizeof: {"Sizeof", 1, false, expression}, + _Slice: {"Slice", 2, false, expression}, _Assert: {"assert", 1, false, statement}, _Trace: {"trace", 0, true, statement}, @@ -188,6 +202,33 @@ func DefPredeclaredTestFuncs() { def(newBuiltin(_Trace)) } +func defPredeclaredComparable() { + // The "comparable" interface can be imagined as defined like + // + // type comparable interface { + // == () untyped bool + // != () untyped bool + // } + // + // == and != cannot be user-declared but we can declare + // a magic method == and check for its presence when needed. + + // Define interface { == () }. We don't care about the signature + // for == so leave it empty except for the receiver, which is + // set up later to match the usual interface method assumptions. + sig := new(Signature) + eql := NewFunc(token.NoPos, nil, "==", sig) + iface := NewInterfaceType([]*Func{eql}, nil).Complete() + + // set up the defined type for the interface + obj := NewTypeName(token.NoPos, nil, "comparable", nil) + named := NewNamed(obj, iface, nil) + obj.color_ = black + sig.recv = NewVar(token.NoPos, nil, "", named) // complete == signature + + def(obj) +} + func init() { Universe = NewScope(nil, token.NoPos, token.NoPos, "universe") Unsafe = NewPackage("unsafe", "unsafe") @@ -197,11 +238,18 @@ func init() { defPredeclaredConsts() defPredeclaredNil() defPredeclaredFuncs() + if typeparams.Enabled { + defPredeclaredComparable() + } universeIota = Universe.Lookup("iota").(*Const) universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic) universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic) + universeAny = Universe.Lookup("any").(*TypeName).typ.(*Interface) universeError = Universe.Lookup("error").(*TypeName).typ.(*Named) + + // "any" is only visible as constraint in a type parameter list + delete(Universe.elems, "any") } // Objects with names containing blanks are internal and not entered into @@ -215,7 +263,7 @@ func def(obj Object) { return // nothing to do } // fix Obj link for named types - if typ, ok := obj.Type().(*Named); ok { + if typ := asNamed(obj.Type()); typ != nil { typ.obj = obj.(*TypeName) } // exported identifiers go into package unsafe diff --git a/libgo/go/go/types/version.go b/libgo/go/go/types/version.go new file mode 100644 index 0000000..1546941 --- /dev/null +++ b/libgo/go/go/types/version.go @@ -0,0 +1,82 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types + +import ( + "fmt" + "go/ast" + "go/token" + "regexp" + "strconv" + "strings" +) + +// langCompat reports an error if the representation of a numeric +// literal is not compatible with the current language version. +func (check *Checker) langCompat(lit *ast.BasicLit) { + s := lit.Value + if len(s) <= 2 || check.allowVersion(check.pkg, 1, 13) { + return + } + // len(s) > 2 + if strings.Contains(s, "_") { + check.errorf(lit, _InvalidLit, "underscores in numeric literals requires go1.13 or later") + return + } + if s[0] != '0' { + return + } + radix := s[1] + if radix == 'b' || radix == 'B' { + check.errorf(lit, _InvalidLit, "binary literals requires go1.13 or later") + return + } + if radix == 'o' || radix == 'O' { + check.errorf(lit, _InvalidLit, "0o/0O-style octal literals requires go1.13 or later") + return + } + if lit.Kind != token.INT && (radix == 'x' || radix == 'X') { + check.errorf(lit, _InvalidLit, "hexadecimal floating-point literals requires go1.13 or later") + } +} + +// allowVersion reports whether the given package +// is allowed to use version major.minor. +func (check *Checker) allowVersion(pkg *Package, major, minor int) bool { + // We assume that imported packages have all been checked, + // so we only have to check for the local package. + if pkg != check.pkg { + return true + } + ma, mi := check.version.major, check.version.minor + return ma == 0 && mi == 0 || ma > major || ma == major && mi >= minor +} + +type version struct { + major, minor int +} + +// parseGoVersion parses a Go version string (such as "go1.12") +// and returns the version, or an error. If s is the empty +// string, the version is 0.0. +func parseGoVersion(s string) (v version, err error) { + if s == "" { + return + } + matches := goVersionRx.FindStringSubmatch(s) + if matches == nil { + err = fmt.Errorf(`should be something like "go1.12"`) + return + } + v.major, err = strconv.Atoi(matches[1]) + if err != nil { + return + } + v.minor, err = strconv.Atoi(matches[2]) + return +} + +// goVersionRx matches a Go version string, e.g. "go1.12". +var goVersionRx = regexp.MustCompile(`^go([1-9][0-9]*)\.(0|[1-9][0-9]*)$`) diff --git a/libgo/go/golang.org/x/crypto/chacha20/chacha_arm64.go b/libgo/go/golang.org/x/crypto/chacha20/chacha_arm64.go index b799e44..94c71ac 100644 --- a/libgo/go/golang.org/x/crypto/chacha20/chacha_arm64.go +++ b/libgo/go/golang.org/x/crypto/chacha20/chacha_arm64.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build go1.11,!gccgo,!purego +//go:build go1.11 && gc && !purego +// +build go1.11,gc,!purego package chacha20 diff --git a/libgo/go/golang.org/x/crypto/chacha20/chacha_noasm.go b/libgo/go/golang.org/x/crypto/chacha20/chacha_noasm.go index 4635307..025b498 100644 --- a/libgo/go/golang.org/x/crypto/chacha20/chacha_noasm.go +++ b/libgo/go/golang.org/x/crypto/chacha20/chacha_noasm.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !arm64,!s390x,!ppc64le arm64,!go1.11 gccgo purego +//go:build (!arm64 && !s390x && !ppc64le) || (arm64 && !go1.11) || !gc || purego +// +build !arm64,!s390x,!ppc64le arm64,!go1.11 !gc purego package chacha20 diff --git a/libgo/go/golang.org/x/crypto/chacha20/chacha_ppc64le.go b/libgo/go/golang.org/x/crypto/chacha20/chacha_ppc64le.go index b799330..da420b2 100644 --- a/libgo/go/golang.org/x/crypto/chacha20/chacha_ppc64le.go +++ b/libgo/go/golang.org/x/crypto/chacha20/chacha_ppc64le.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo,!purego +//go:build gc && !purego +// +build gc,!purego package chacha20 diff --git a/libgo/go/golang.org/x/crypto/chacha20/chacha_s390x.go b/libgo/go/golang.org/x/crypto/chacha20/chacha_s390x.go index a9244bd..c5898db 100644 --- a/libgo/go/golang.org/x/crypto/chacha20/chacha_s390x.go +++ b/libgo/go/golang.org/x/crypto/chacha20/chacha_s390x.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo,!purego +//go:build gc && !purego +// +build gc,!purego package chacha20 diff --git a/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go b/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go index cda7781..25959b9a 100644 --- a/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go +++ b/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo,!purego +//go:build gc && !purego +// +build gc,!purego package chacha20poly1305 diff --git a/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go b/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go index 9ce4aa9..f832b33 100644 --- a/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go +++ b/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64 gccgo purego +//go:build !amd64 || !gc || purego +// +build !amd64 !gc purego package chacha20poly1305 diff --git a/libgo/go/golang.org/x/crypto/cryptobyte/asn1.go b/libgo/go/golang.org/x/crypto/cryptobyte/asn1.go index d3596ee..83c776d 100644 --- a/libgo/go/golang.org/x/crypto/cryptobyte/asn1.go +++ b/libgo/go/golang.org/x/crypto/cryptobyte/asn1.go @@ -117,6 +117,19 @@ func (b *Builder) AddASN1GeneralizedTime(t time.Time) { }) } +// AddASN1UTCTime appends a DER-encoded ASN.1 UTCTime. +func (b *Builder) AddASN1UTCTime(t time.Time) { + b.AddASN1(asn1.UTCTime, func(c *Builder) { + // As utilized by the X.509 profile, UTCTime can only + // represent the years 1950 through 2049. + if t.Year() < 1950 || t.Year() >= 2050 { + b.err = fmt.Errorf("cryptobyte: cannot represent %v as a UTCTime", t) + return + } + c.AddBytes([]byte(t.Format(defaultUTCTimeFormatStr))) + }) +} + // AddASN1BitString appends a DER-encoded ASN.1 BIT STRING. This does not // support BIT STRINGs that are not a whole number of bytes. func (b *Builder) AddASN1BitString(data []byte) { @@ -466,6 +479,45 @@ func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool { return true } +const defaultUTCTimeFormatStr = "060102150405Z0700" + +// ReadASN1UTCTime decodes an ASN.1 UTCTime into out and advances. +// It reports whether the read was successful. +func (s *String) ReadASN1UTCTime(out *time.Time) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.UTCTime) { + return false + } + t := string(bytes) + + formatStr := defaultUTCTimeFormatStr + var err error + res, err := time.Parse(formatStr, t) + if err != nil { + // Fallback to minute precision if we can't parse second + // precision. If we are following X.509 or X.690 we shouldn't + // support this, but we do. + formatStr = "0601021504Z0700" + res, err = time.Parse(formatStr, t) + } + if err != nil { + return false + } + + if serialized := res.Format(formatStr); serialized != t { + return false + } + + if res.Year() >= 2050 { + // UTCTime interprets the low order digits 50-99 as 1950-99. + // This only applies to its use in the X.509 profile. + // See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 + res = res.AddDate(-100, 0, 0) + } + *out = res + return true +} + // ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. // It reports whether the read was successful. func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { diff --git a/libgo/go/golang.org/x/crypto/curve25519/curve25519_amd64.go b/libgo/go/golang.org/x/crypto/curve25519/curve25519_amd64.go index 5120b77..8485848 100644 --- a/libgo/go/golang.org/x/crypto/curve25519/curve25519_amd64.go +++ b/libgo/go/golang.org/x/crypto/curve25519/curve25519_amd64.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64,!gccgo,!appengine,!purego +//go:build amd64 && gc && !purego +// +build amd64,gc,!purego package curve25519 diff --git a/libgo/go/golang.org/x/crypto/curve25519/curve25519_noasm.go b/libgo/go/golang.org/x/crypto/curve25519/curve25519_noasm.go index 047d49a..259728a 100644 --- a/libgo/go/golang.org/x/crypto/curve25519/curve25519_noasm.go +++ b/libgo/go/golang.org/x/crypto/curve25519/curve25519_noasm.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64 gccgo appengine purego +//go:build !amd64 || !gc || purego +// +build !amd64 !gc purego package curve25519 diff --git a/libgo/go/golang.org/x/crypto/internal/subtle/aliasing.go b/libgo/go/golang.org/x/crypto/internal/subtle/aliasing.go index f38797b..4fad24f 100644 --- a/libgo/go/golang.org/x/crypto/internal/subtle/aliasing.go +++ b/libgo/go/golang.org/x/crypto/internal/subtle/aliasing.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !appengine +//go:build !purego +// +build !purego // Package subtle implements functions that are often useful in cryptographic // code but require careful thought to use correctly. diff --git a/libgo/go/golang.org/x/crypto/internal/subtle/aliasing_purego.go b/libgo/go/golang.org/x/crypto/internal/subtle/aliasing_purego.go new file mode 100644 index 0000000..80ccbed --- /dev/null +++ b/libgo/go/golang.org/x/crypto/internal/subtle/aliasing_purego.go @@ -0,0 +1,36 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build purego +// +build purego + +// Package subtle implements functions that are often useful in cryptographic +// code but require careful thought to use correctly. +package subtle // import "golang.org/x/crypto/internal/subtle" + +// This is the Google App Engine standard variant based on reflect +// because the unsafe package and cgo are disallowed. + +import "reflect" + +// AnyOverlap reports whether x and y share memory at any (not necessarily +// corresponding) index. The memory beyond the slice length is ignored. +func AnyOverlap(x, y []byte) bool { + return len(x) > 0 && len(y) > 0 && + reflect.ValueOf(&x[0]).Pointer() <= reflect.ValueOf(&y[len(y)-1]).Pointer() && + reflect.ValueOf(&y[0]).Pointer() <= reflect.ValueOf(&x[len(x)-1]).Pointer() +} + +// InexactOverlap reports whether x and y share memory at any non-corresponding +// index. The memory beyond the slice length is ignored. Note that x and y can +// have different lengths and still not have any inexact overlap. +// +// InexactOverlap can be used to implement the requirements of the crypto/cipher +// AEAD, Block, BlockMode and Stream interfaces. +func InexactOverlap(x, y []byte) bool { + if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { + return false + } + return AnyOverlap(x, y) +} diff --git a/libgo/go/golang.org/x/crypto/poly1305/bits_compat.go b/libgo/go/golang.org/x/crypto/poly1305/bits_compat.go index 157a69f..45b5c966 100644 --- a/libgo/go/golang.org/x/crypto/poly1305/bits_compat.go +++ b/libgo/go/golang.org/x/crypto/poly1305/bits_compat.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !go1.13 // +build !go1.13 package poly1305 diff --git a/libgo/go/golang.org/x/crypto/poly1305/bits_go1.13.go b/libgo/go/golang.org/x/crypto/poly1305/bits_go1.13.go index a0a185f..ed52b34 100644 --- a/libgo/go/golang.org/x/crypto/poly1305/bits_go1.13.go +++ b/libgo/go/golang.org/x/crypto/poly1305/bits_go1.13.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build go1.13 // +build go1.13 package poly1305 diff --git a/libgo/go/golang.org/x/crypto/poly1305/mac_noasm.go b/libgo/go/golang.org/x/crypto/poly1305/mac_noasm.go index d118f30..f184b67 100644 --- a/libgo/go/golang.org/x/crypto/poly1305/mac_noasm.go +++ b/libgo/go/golang.org/x/crypto/poly1305/mac_noasm.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64,!ppc64le,!s390x gccgo purego +//go:build (!amd64 && !ppc64le && !s390x) || !gc || purego +// +build !amd64,!ppc64le,!s390x !gc purego package poly1305 diff --git a/libgo/go/golang.org/x/crypto/poly1305/sum_amd64.go b/libgo/go/golang.org/x/crypto/poly1305/sum_amd64.go index 99e5a1d..6d52233 100644 --- a/libgo/go/golang.org/x/crypto/poly1305/sum_amd64.go +++ b/libgo/go/golang.org/x/crypto/poly1305/sum_amd64.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo,!purego +//go:build gc && !purego +// +build gc,!purego package poly1305 diff --git a/libgo/go/golang.org/x/crypto/poly1305/sum_ppc64le.go b/libgo/go/golang.org/x/crypto/poly1305/sum_ppc64le.go index 2e7a120..4a06994 100644 --- a/libgo/go/golang.org/x/crypto/poly1305/sum_ppc64le.go +++ b/libgo/go/golang.org/x/crypto/poly1305/sum_ppc64le.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo,!purego +//go:build gc && !purego +// +build gc,!purego package poly1305 diff --git a/libgo/go/golang.org/x/crypto/poly1305/sum_s390x.go b/libgo/go/golang.org/x/crypto/poly1305/sum_s390x.go index 958fedc..62cc9f8 100644 --- a/libgo/go/golang.org/x/crypto/poly1305/sum_s390x.go +++ b/libgo/go/golang.org/x/crypto/poly1305/sum_s390x.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo,!purego +//go:build gc && !purego +// +build gc,!purego package poly1305 diff --git a/libgo/go/golang.org/x/mod/modfile/read.go b/libgo/go/golang.org/x/mod/modfile/read.go index 2a961ca..956f30c 100644 --- a/libgo/go/golang.org/x/mod/modfile/read.go +++ b/libgo/go/golang.org/x/mod/modfile/read.go @@ -194,12 +194,15 @@ func (x *FileSyntax) updateLine(line *Line, tokens ...string) { line.Token = tokens } -func (x *FileSyntax) removeLine(line *Line) { +// markRemoved modifies line so that it (and its end-of-line comment, if any) +// will be dropped by (*FileSyntax).Cleanup. +func (line *Line) markRemoved() { line.Token = nil + line.Comments.Suffix = nil } // Cleanup cleans up the file syntax x after any edit operations. -// To avoid quadratic behavior, removeLine marks the line as dead +// To avoid quadratic behavior, (*Line).markRemoved marks the line as dead // by setting line.Token = nil but does not remove it from the slice // in which it appears. After edits have all been indicated, // calling Cleanup cleans out the dead lines. diff --git a/libgo/go/golang.org/x/mod/modfile/rule.go b/libgo/go/golang.org/x/mod/modfile/rule.go index f8c9384..78f83fa 100644 --- a/libgo/go/golang.org/x/mod/modfile/rule.go +++ b/libgo/go/golang.org/x/mod/modfile/rule.go @@ -47,8 +47,9 @@ type File struct { // A Module is the module statement. type Module struct { - Mod module.Version - Syntax *Line + Mod module.Version + Deprecated string + Syntax *Line } // A Go is the go statement. @@ -57,13 +58,6 @@ type Go struct { Syntax *Line } -// A Require is a single require statement. -type Require struct { - Mod module.Version - Indirect bool // has "// indirect" comment - Syntax *Line -} - // An Exclude is a single exclude statement. type Exclude struct { Mod module.Version @@ -92,6 +86,93 @@ type VersionInterval struct { Low, High string } +// A Require is a single require statement. +type Require struct { + Mod module.Version + Indirect bool // has "// indirect" comment + Syntax *Line +} + +func (r *Require) markRemoved() { + r.Syntax.markRemoved() + *r = Require{} +} + +func (r *Require) setVersion(v string) { + r.Mod.Version = v + + if line := r.Syntax; len(line.Token) > 0 { + if line.InBlock { + // If the line is preceded by an empty line, remove it; see + // https://golang.org/issue/33779. + if len(line.Comments.Before) == 1 && len(line.Comments.Before[0].Token) == 0 { + line.Comments.Before = line.Comments.Before[:0] + } + if len(line.Token) >= 2 { // example.com v1.2.3 + line.Token[1] = v + } + } else { + if len(line.Token) >= 3 { // require example.com v1.2.3 + line.Token[2] = v + } + } + } +} + +// setIndirect sets line to have (or not have) a "// indirect" comment. +func (r *Require) setIndirect(indirect bool) { + r.Indirect = indirect + line := r.Syntax + if isIndirect(line) == indirect { + return + } + if indirect { + // Adding comment. + if len(line.Suffix) == 0 { + // New comment. + line.Suffix = []Comment{{Token: "// indirect", Suffix: true}} + return + } + + com := &line.Suffix[0] + text := strings.TrimSpace(strings.TrimPrefix(com.Token, string(slashSlash))) + if text == "" { + // Empty comment. + com.Token = "// indirect" + return + } + + // Insert at beginning of existing comment. + com.Token = "// indirect; " + text + return + } + + // Removing comment. + f := strings.TrimSpace(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash))) + if f == "indirect" { + // Remove whole comment. + line.Suffix = nil + return + } + + // Remove comment prefix. + com := &line.Suffix[0] + i := strings.Index(com.Token, "indirect;") + com.Token = "//" + com.Token[i+len("indirect;"):] +} + +// isIndirect reports whether line has a "// indirect" comment, +// meaning it is in go.mod only for its effect on indirect dependencies, +// so that it can be dropped entirely once the effective version of the +// indirect dependency reaches the given minimum version. +func isIndirect(line *Line) bool { + if len(line.Suffix) == 0 { + return false + } + f := strings.Fields(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash))) + return (len(f) == 1 && f[0] == "indirect" || len(f) > 1 && f[0] == "indirect;") +} + func (f *File) AddModuleStmt(path string) error { if f.Syntax == nil { f.Syntax = new(FileSyntax) @@ -131,8 +212,15 @@ var dontFixRetract VersionFixer = func(_, vers string) (string, error) { return vers, nil } -// Parse parses the data, reported in errors as being from file, -// into a File struct. It applies fix, if non-nil, to canonicalize all module versions found. +// Parse parses and returns a go.mod file. +// +// file is the name of the file, used in positions and errors. +// +// data is the content of the file. +// +// fix is an optional function that canonicalizes module versions. +// If fix is nil, all module versions must be canonical (module.CanonicalVersion +// must return the same string). func Parse(file string, data []byte, fix VersionFixer) (*File, error) { return parseToFile(file, data, fix, true) } @@ -209,6 +297,7 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (parse } var GoVersionRE = lazyregexp.New(`^([1-9][0-9]*)\.(0|[1-9][0-9]*)$`) +var laxGoVersionRE = lazyregexp.New(`^v?(([1-9][0-9]*)\.(0|[1-9][0-9]*))([^0-9].*)$`) func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, args []string, fix VersionFixer, strict bool) { // If strict is false, this module is a dependency. @@ -259,8 +348,17 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a errorf("go directive expects exactly one argument") return } else if !GoVersionRE.MatchString(args[0]) { - errorf("invalid go version '%s': must match format 1.23", args[0]) - return + fixed := false + if !strict { + if m := laxGoVersionRE.FindStringSubmatch(args[0]); m != nil { + args[0] = m[1] + fixed = true + } + } + if !fixed { + errorf("invalid go version '%s': must match format 1.23", args[0]) + return + } } f.Go = &Go{Syntax: line} @@ -271,7 +369,11 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a errorf("repeated module statement") return } - f.Module = &Module{Syntax: line} + deprecated := parseDeprecation(block, line) + f.Module = &Module{ + Syntax: line, + Deprecated: deprecated, + } if len(args) != 1 { errorf("usage: module module/path") return @@ -385,7 +487,7 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a }) case "retract": - rationale := parseRetractRationale(block, line) + rationale := parseDirectiveComment(block, line) vi, err := parseVersionInterval(verb, "", &args, dontFixRetract) if err != nil { if strict { @@ -454,58 +556,6 @@ func (f *File) fixRetract(fix VersionFixer, errs *ErrorList) { } } -// isIndirect reports whether line has a "// indirect" comment, -// meaning it is in go.mod only for its effect on indirect dependencies, -// so that it can be dropped entirely once the effective version of the -// indirect dependency reaches the given minimum version. -func isIndirect(line *Line) bool { - if len(line.Suffix) == 0 { - return false - } - f := strings.Fields(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash))) - return (len(f) == 1 && f[0] == "indirect" || len(f) > 1 && f[0] == "indirect;") -} - -// setIndirect sets line to have (or not have) a "// indirect" comment. -func setIndirect(line *Line, indirect bool) { - if isIndirect(line) == indirect { - return - } - if indirect { - // Adding comment. - if len(line.Suffix) == 0 { - // New comment. - line.Suffix = []Comment{{Token: "// indirect", Suffix: true}} - return - } - - com := &line.Suffix[0] - text := strings.TrimSpace(strings.TrimPrefix(com.Token, string(slashSlash))) - if text == "" { - // Empty comment. - com.Token = "// indirect" - return - } - - // Insert at beginning of existing comment. - com.Token = "// indirect; " + text - return - } - - // Removing comment. - f := strings.Fields(line.Suffix[0].Token) - if len(f) == 2 { - // Remove whole comment. - line.Suffix = nil - return - } - - // Remove comment prefix. - com := &line.Suffix[0] - i := strings.Index(com.Token, "indirect;") - com.Token = "//" + com.Token[i+len("indirect;"):] -} - // IsDirectoryPath reports whether the given path should be interpreted // as a directory path. Just like on the go command line, relative paths // and rooted paths are directory paths; the rest are module paths. @@ -612,10 +662,29 @@ func parseString(s *string) (string, error) { return t, nil } -// parseRetractRationale extracts the rationale for a retract directive from the -// surrounding comments. If the line does not have comments and is part of a -// block that does have comments, the block's comments are used. -func parseRetractRationale(block *LineBlock, line *Line) string { +var deprecatedRE = lazyregexp.New(`(?s)(?:^|\n\n)Deprecated: *(.*?)(?:$|\n\n)`) + +// parseDeprecation extracts the text of comments on a "module" directive and +// extracts a deprecation message from that. +// +// A deprecation message is contained in a paragraph within a block of comments +// that starts with "Deprecated:" (case sensitive). The message runs until the +// end of the paragraph and does not include the "Deprecated:" prefix. If the +// comment block has multiple paragraphs that start with "Deprecated:", +// parseDeprecation returns the message from the first. +func parseDeprecation(block *LineBlock, line *Line) string { + text := parseDirectiveComment(block, line) + m := deprecatedRE.FindStringSubmatch(text) + if m == nil { + return "" + } + return m[1] +} + +// parseDirectiveComment extracts the text of comments on a directive. +// If the directive's line does not have comments and is part of a block that +// does have comments, the block's comments are used. +func parseDirectiveComment(block *LineBlock, line *Line) string { comments := line.Comment() if block != nil && len(comments.Before) == 0 && len(comments.Suffix) == 0 { comments = block.Comment() @@ -794,6 +863,12 @@ func (f *File) AddGoStmt(version string) error { return nil } +// AddRequire sets the first require line for path to version vers, +// preserving any existing comments for that line and removing all +// other lines for path. +// +// If no line currently exists for path, AddRequire adds a new line +// at the end of the last require block. func (f *File) AddRequire(path, vers string) error { need := true for _, r := range f.Require { @@ -803,7 +878,7 @@ func (f *File) AddRequire(path, vers string) error { f.Syntax.updateLine(r.Syntax, "require", AutoQuote(path), vers) need = false } else { - f.Syntax.removeLine(r.Syntax) + r.Syntax.markRemoved() *r = Require{} } } @@ -815,69 +890,235 @@ func (f *File) AddRequire(path, vers string) error { return nil } +// AddNewRequire adds a new require line for path at version vers at the end of +// the last require block, regardless of any existing require lines for path. func (f *File) AddNewRequire(path, vers string, indirect bool) { line := f.Syntax.addLine(nil, "require", AutoQuote(path), vers) - setIndirect(line, indirect) - f.Require = append(f.Require, &Require{module.Version{Path: path, Version: vers}, indirect, line}) + r := &Require{ + Mod: module.Version{Path: path, Version: vers}, + Syntax: line, + } + r.setIndirect(indirect) + f.Require = append(f.Require, r) } +// SetRequire updates the requirements of f to contain exactly req, preserving +// the existing block structure and line comment contents (except for 'indirect' +// markings) for the first requirement on each named module path. +// +// The Syntax field is ignored for the requirements in req. +// +// Any requirements not already present in the file are added to the block +// containing the last require line. +// +// The requirements in req must specify at most one distinct version for each +// module path. +// +// If any existing requirements may be removed, the caller should call Cleanup +// after all edits are complete. func (f *File) SetRequire(req []*Require) { - need := make(map[string]string) - indirect := make(map[string]bool) + type elem struct { + version string + indirect bool + } + need := make(map[string]elem) for _, r := range req { - need[r.Mod.Path] = r.Mod.Version - indirect[r.Mod.Path] = r.Indirect + if prev, dup := need[r.Mod.Path]; dup && prev.version != r.Mod.Version { + panic(fmt.Errorf("SetRequire called with conflicting versions for path %s (%s and %s)", r.Mod.Path, prev.version, r.Mod.Version)) + } + need[r.Mod.Path] = elem{r.Mod.Version, r.Indirect} } + // Update or delete the existing Require entries to preserve + // only the first for each module path in req. for _, r := range f.Require { - if v, ok := need[r.Mod.Path]; ok { - r.Mod.Version = v - r.Indirect = indirect[r.Mod.Path] + e, ok := need[r.Mod.Path] + if ok { + r.setVersion(e.version) + r.setIndirect(e.indirect) } else { - *r = Require{} + r.markRemoved() + } + delete(need, r.Mod.Path) + } + + // Add new entries in the last block of the file for any paths that weren't + // already present. + // + // This step is nondeterministic, but the final result will be deterministic + // because we will sort the block. + for path, e := range need { + f.AddNewRequire(path, e.version, e.indirect) + } + + f.SortBlocks() +} + +// SetRequireSeparateIndirect updates the requirements of f to contain the given +// requirements. Comment contents (except for 'indirect' markings) are retained +// from the first existing requirement for each module path, and block structure +// is maintained as long as the indirect markings match. +// +// Any requirements on paths not already present in the file are added. Direct +// requirements are added to the last block containing *any* other direct +// requirement. Indirect requirements are added to the last block containing +// *only* other indirect requirements. If no suitable block exists, a new one is +// added, with the last block containing a direct dependency (if any) +// immediately before the first block containing only indirect dependencies. +// +// The Syntax field is ignored for requirements in the given blocks. +func (f *File) SetRequireSeparateIndirect(req []*Require) { + type modKey struct { + path string + indirect bool + } + need := make(map[modKey]string) + for _, r := range req { + need[modKey{r.Mod.Path, r.Indirect}] = r.Mod.Version + } + + comments := make(map[string]Comments) + for _, r := range f.Require { + v, ok := need[modKey{r.Mod.Path, r.Indirect}] + if !ok { + if _, ok := need[modKey{r.Mod.Path, !r.Indirect}]; ok { + if _, dup := comments[r.Mod.Path]; !dup { + comments[r.Mod.Path] = r.Syntax.Comments + } + } + r.markRemoved() + continue } + r.setVersion(v) + delete(need, modKey{r.Mod.Path, r.Indirect}) } - var newStmts []Expr + var ( + lastDirectOrMixedBlock Expr + firstIndirectOnlyBlock Expr + lastIndirectOnlyBlock Expr + ) for _, stmt := range f.Syntax.Stmt { switch stmt := stmt.(type) { + case *Line: + if len(stmt.Token) == 0 || stmt.Token[0] != "require" { + continue + } + if isIndirect(stmt) { + lastIndirectOnlyBlock = stmt + } else { + lastDirectOrMixedBlock = stmt + } case *LineBlock: - if len(stmt.Token) > 0 && stmt.Token[0] == "require" { - var newLines []*Line + if len(stmt.Token) == 0 || stmt.Token[0] != "require" { + continue + } + indirectOnly := true + for _, line := range stmt.Line { + if len(line.Token) == 0 { + continue + } + if !isIndirect(line) { + indirectOnly = false + break + } + } + if indirectOnly { + lastIndirectOnlyBlock = stmt + if firstIndirectOnlyBlock == nil { + firstIndirectOnlyBlock = stmt + } + } else { + lastDirectOrMixedBlock = stmt + } + } + } + + isOrContainsStmt := func(stmt Expr, target Expr) bool { + if stmt == target { + return true + } + if stmt, ok := stmt.(*LineBlock); ok { + if target, ok := target.(*Line); ok { for _, line := range stmt.Line { - if p, err := parseString(&line.Token[0]); err == nil && need[p] != "" { - if len(line.Comments.Before) == 1 && len(line.Comments.Before[0].Token) == 0 { - line.Comments.Before = line.Comments.Before[:0] - } - line.Token[1] = need[p] - delete(need, p) - setIndirect(line, indirect[p]) - newLines = append(newLines, line) + if line == target { + return true } } - if len(newLines) == 0 { - continue // drop stmt - } - stmt.Line = newLines } + } + return false + } - case *Line: - if len(stmt.Token) > 0 && stmt.Token[0] == "require" { - if p, err := parseString(&stmt.Token[1]); err == nil && need[p] != "" { - stmt.Token[2] = need[p] - delete(need, p) - setIndirect(stmt, indirect[p]) + addRequire := func(path, vers string, indirect bool, comments Comments) { + var line *Line + if indirect { + if lastIndirectOnlyBlock != nil { + line = f.Syntax.addLine(lastIndirectOnlyBlock, "require", path, vers) + } else { + // Add a new require block after the last direct-only or mixed "require" + // block (if any). + // + // (f.Syntax.addLine would add the line to an existing "require" block if + // present, but here the existing "require" blocks are all direct-only, so + // we know we need to add a new block instead.) + line = &Line{Token: []string{"require", path, vers}} + lastIndirectOnlyBlock = line + firstIndirectOnlyBlock = line // only block implies first block + if lastDirectOrMixedBlock == nil { + f.Syntax.Stmt = append(f.Syntax.Stmt, line) } else { - continue // drop stmt + for i, stmt := range f.Syntax.Stmt { + if isOrContainsStmt(stmt, lastDirectOrMixedBlock) { + f.Syntax.Stmt = append(f.Syntax.Stmt, nil) // increase size + copy(f.Syntax.Stmt[i+2:], f.Syntax.Stmt[i+1:]) // shuffle elements up + f.Syntax.Stmt[i+1] = line + break + } + } + } + } + } else { + if lastDirectOrMixedBlock != nil { + line = f.Syntax.addLine(lastDirectOrMixedBlock, "require", path, vers) + } else { + // Add a new require block before the first indirect block (if any). + // + // That way if the file initially contains only indirect lines, + // the direct lines still appear before it: we preserve existing + // structure, but only to the extent that that structure already + // reflects the direct/indirect split. + line = &Line{Token: []string{"require", path, vers}} + lastDirectOrMixedBlock = line + if firstIndirectOnlyBlock == nil { + f.Syntax.Stmt = append(f.Syntax.Stmt, line) + } else { + for i, stmt := range f.Syntax.Stmt { + if isOrContainsStmt(stmt, firstIndirectOnlyBlock) { + f.Syntax.Stmt = append(f.Syntax.Stmt, nil) // increase size + copy(f.Syntax.Stmt[i+1:], f.Syntax.Stmt[i:]) // shuffle elements up + f.Syntax.Stmt[i] = line + break + } + } } } } - newStmts = append(newStmts, stmt) + + line.Comments.Before = commentsAdd(line.Comments.Before, comments.Before) + line.Comments.Suffix = commentsAdd(line.Comments.Suffix, comments.Suffix) + + r := &Require{ + Mod: module.Version{Path: path, Version: vers}, + Indirect: indirect, + Syntax: line, + } + r.setIndirect(indirect) + f.Require = append(f.Require, r) } - f.Syntax.Stmt = newStmts - for path, vers := range need { - f.AddNewRequire(path, vers, indirect[path]) + for k, vers := range need { + addRequire(k.path, vers, k.indirect, comments[k.path]) } f.SortBlocks() } @@ -885,7 +1126,7 @@ func (f *File) SetRequire(req []*Require) { func (f *File) DropRequire(path string) error { for _, r := range f.Require { if r.Mod.Path == path { - f.Syntax.removeLine(r.Syntax) + r.Syntax.markRemoved() *r = Require{} } } @@ -916,7 +1157,7 @@ func (f *File) AddExclude(path, vers string) error { func (f *File) DropExclude(path, vers string) error { for _, x := range f.Exclude { if x.Mod.Path == path && x.Mod.Version == vers { - f.Syntax.removeLine(x.Syntax) + x.Syntax.markRemoved() *x = Exclude{} } } @@ -947,7 +1188,7 @@ func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error { continue } // Already added; delete other replacements for same. - f.Syntax.removeLine(r.Syntax) + r.Syntax.markRemoved() *r = Replace{} } if r.Old.Path == oldPath { @@ -963,7 +1204,7 @@ func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error { func (f *File) DropReplace(oldPath, oldVers string) error { for _, r := range f.Replace { if r.Old.Path == oldPath && r.Old.Version == oldVers { - f.Syntax.removeLine(r.Syntax) + r.Syntax.markRemoved() *r = Replace{} } } @@ -1004,7 +1245,7 @@ func (f *File) AddRetract(vi VersionInterval, rationale string) error { func (f *File) DropRetract(vi VersionInterval) error { for _, r := range f.Retract { if r.VersionInterval == vi { - f.Syntax.removeLine(r.Syntax) + r.Syntax.markRemoved() *r = Retract{} } } diff --git a/libgo/go/golang.org/x/mod/module/module.go b/libgo/go/golang.org/x/mod/module/module.go index 0e03014..ba97ac3 100644 --- a/libgo/go/golang.org/x/mod/module/module.go +++ b/libgo/go/golang.org/x/mod/module/module.go @@ -192,6 +192,21 @@ func (e *InvalidVersionError) Error() string { func (e *InvalidVersionError) Unwrap() error { return e.Err } +// An InvalidPathError indicates a module, import, or file path doesn't +// satisfy all naming constraints. See CheckPath, CheckImportPath, +// and CheckFilePath for specific restrictions. +type InvalidPathError struct { + Kind string // "module", "import", or "file" + Path string + Err error +} + +func (e *InvalidPathError) Error() string { + return fmt.Sprintf("malformed %s path %q: %v", e.Kind, e.Path, e.Err) +} + +func (e *InvalidPathError) Unwrap() error { return e.Err } + // Check checks that a given module path, version pair is valid. // In addition to the path being a valid module path // and the version being a valid semantic version, @@ -296,30 +311,36 @@ func fileNameOK(r rune) bool { // this second requirement is replaced by a requirement that the path // follow the gopkg.in server's conventions. // Third, no path element may begin with a dot. -func CheckPath(path string) error { +func CheckPath(path string) (err error) { + defer func() { + if err != nil { + err = &InvalidPathError{Kind: "module", Path: path, Err: err} + } + }() + if err := checkPath(path, modulePath); err != nil { - return fmt.Errorf("malformed module path %q: %v", path, err) + return err } i := strings.Index(path, "/") if i < 0 { i = len(path) } if i == 0 { - return fmt.Errorf("malformed module path %q: leading slash", path) + return fmt.Errorf("leading slash") } if !strings.Contains(path[:i], ".") { - return fmt.Errorf("malformed module path %q: missing dot in first path element", path) + return fmt.Errorf("missing dot in first path element") } if path[0] == '-' { - return fmt.Errorf("malformed module path %q: leading dash in first path element", path) + return fmt.Errorf("leading dash in first path element") } for _, r := range path[:i] { if !firstPathOK(r) { - return fmt.Errorf("malformed module path %q: invalid char %q in first path element", path, r) + return fmt.Errorf("invalid char %q in first path element", r) } } if _, _, ok := SplitPathVersion(path); !ok { - return fmt.Errorf("malformed module path %q: invalid version", path) + return fmt.Errorf("invalid version") } return nil } @@ -343,7 +364,7 @@ func CheckPath(path string) error { // subtleties of Unicode. func CheckImportPath(path string) error { if err := checkPath(path, importPath); err != nil { - return fmt.Errorf("malformed import path %q: %v", path, err) + return &InvalidPathError{Kind: "import", Path: path, Err: err} } return nil } @@ -358,12 +379,13 @@ const ( filePath ) -// checkPath checks that a general path is valid. -// It returns an error describing why but not mentioning path. -// Because these checks apply to both module paths and import paths, -// the caller is expected to add the "malformed ___ path %q: " prefix. -// fileName indicates whether the final element of the path is a file name -// (as opposed to a directory name). +// checkPath checks that a general path is valid. kind indicates what +// specific constraints should be applied. +// +// checkPath returns an error describing why the path is not valid. +// Because these checks apply to module, import, and file paths, +// and because other checks may be applied, the caller is expected to wrap +// this error with InvalidPathError. func checkPath(path string, kind pathKind) error { if !utf8.ValidString(path) { return fmt.Errorf("invalid UTF-8") @@ -371,7 +393,7 @@ func checkPath(path string, kind pathKind) error { if path == "" { return fmt.Errorf("empty string") } - if path[0] == '-' { + if path[0] == '-' && kind != filePath { return fmt.Errorf("leading dash") } if strings.Contains(path, "//") { @@ -477,7 +499,7 @@ func checkElem(elem string, kind pathKind) error { // subtleties of Unicode. func CheckFilePath(path string) error { if err := checkPath(path, filePath); err != nil { - return fmt.Errorf("malformed file path %q: %v", path, err) + return &InvalidPathError{Kind: "file", Path: path, Err: err} } return nil } diff --git a/libgo/go/cmd/go/internal/modfetch/pseudo.go b/libgo/go/golang.org/x/mod/module/pseudo.go index 93eb0fa..f04ad37 100644 --- a/libgo/go/cmd/go/internal/modfetch/pseudo.go +++ b/libgo/go/golang.org/x/mod/module/pseudo.go @@ -32,7 +32,7 @@ // If the most recent tagged version before the target commit is vX.Y.Z-pre or vX.Y.Z-pre+incompatible, // then the pseudo-version uses form (4) or (5), making it a slightly later prerelease. -package modfetch +package module import ( "errors" @@ -40,15 +40,13 @@ import ( "strings" "time" - "internal/lazyregexp" - - "golang.org/x/mod/module" + "golang.org/x/mod/internal/lazyregexp" "golang.org/x/mod/semver" ) var pseudoVersionRE = lazyregexp.New(`^v[0-9]+\.(0\.0-|\d+\.\d+-([^+]*\.)?0\.)\d{14}-[A-Za-z0-9]+(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$`) -const pseudoVersionTimestampFormat = "20060102150405" +const PseudoVersionTimestampFormat = "20060102150405" // PseudoVersion returns a pseudo-version for the given major version ("v1") // preexisting older tagged version ("" or "v1.2.3" or "v1.2.3-pre"), revision time, @@ -57,7 +55,7 @@ func PseudoVersion(major, older string, t time.Time, rev string) string { if major == "" { major = "v0" } - segment := fmt.Sprintf("%s-%s", t.UTC().Format(pseudoVersionTimestampFormat), rev) + segment := fmt.Sprintf("%s-%s", t.UTC().Format(PseudoVersionTimestampFormat), rev) build := semver.Build(older) older = semver.Canonical(older) if older == "" { @@ -142,7 +140,7 @@ func PseudoVersionTime(v string) (time.Time, error) { } t, err := time.Parse("20060102150405", timestamp) if err != nil { - return time.Time{}, &module.InvalidVersionError{ + return time.Time{}, &InvalidVersionError{ Version: v, Pseudo: true, Err: fmt.Errorf("malformed time %q", timestamp), @@ -180,7 +178,7 @@ func PseudoVersionBase(v string) (string, error) { // // There are a few such entries in the index generated by proxy.golang.org, // but we believe those entries were generated by the proxy itself. - return "", &module.InvalidVersionError{ + return "", &InvalidVersionError{ Version: v, Pseudo: true, Err: fmt.Errorf("lacks base version, but has build metadata %q", build), @@ -208,7 +206,7 @@ func PseudoVersionBase(v string) (string, error) { // treat them as equivalent to vX.0.0 (especially since the invalid // pseudo-versions have lower precedence than the real ones). For now, we // reject them. - return "", &module.InvalidVersionError{ + return "", &InvalidVersionError{ Version: v, Pseudo: true, Err: fmt.Errorf("version before %s would have negative patch number", base), @@ -230,7 +228,7 @@ var errPseudoSyntax = errors.New("syntax error") func parsePseudoVersion(v string) (base, timestamp, rev, build string, err error) { if !IsPseudoVersion(v) { - return "", "", "", "", &module.InvalidVersionError{ + return "", "", "", "", &InvalidVersionError{ Version: v, Pseudo: true, Err: errPseudoSyntax, diff --git a/libgo/go/golang.org/x/mod/semver/semver.go b/libgo/go/golang.org/x/mod/semver/semver.go index 4338f35..7be398f 100644 --- a/libgo/go/golang.org/x/mod/semver/semver.go +++ b/libgo/go/golang.org/x/mod/semver/semver.go @@ -22,6 +22,8 @@ // as shorthands for vMAJOR.0.0 and vMAJOR.MINOR.0. package semver +import "sort" + // parsed returns the parsed form of a semantic version string. type parsed struct { major string @@ -150,6 +152,24 @@ func Max(v, w string) string { return w } +// ByVersion implements sort.Interface for sorting semantic version strings. +type ByVersion []string + +func (vs ByVersion) Len() int { return len(vs) } +func (vs ByVersion) Swap(i, j int) { vs[i], vs[j] = vs[j], vs[i] } +func (vs ByVersion) Less(i, j int) bool { + cmp := Compare(vs[i], vs[j]) + if cmp != 0 { + return cmp < 0 + } + return vs[i] < vs[j] +} + +// Sort sorts a list of semantic version strings using ByVersion. +func Sort(list []string) { + sort.Sort(ByVersion(list)) +} + func parse(v string) (p parsed, ok bool) { if v == "" || v[0] != 'v' { p.err = "missing v prefix" diff --git a/libgo/go/golang.org/x/net/dns/dnsmessage/message.go b/libgo/go/golang.org/x/net/dns/dnsmessage/message.go index 654f191..1736fc5 100644 --- a/libgo/go/golang.org/x/net/dns/dnsmessage/message.go +++ b/libgo/go/golang.org/x/net/dns/dnsmessage/message.go @@ -1023,6 +1023,24 @@ func (p *Parser) OPTResource() (OPTResource, error) { return r, nil } +// UnknownResource parses a single UnknownResource. +// +// One of the XXXHeader methods must have been called before calling this +// method. +func (p *Parser) UnknownResource() (UnknownResource, error) { + if !p.resHeaderValid { + return UnknownResource{}, ErrNotStarted + } + r, err := unpackUnknownResource(p.resHeader.Type, p.msg, p.off, p.resHeader.Length) + if err != nil { + return UnknownResource{}, err + } + p.off += int(p.resHeader.Length) + p.resHeaderValid = false + p.index++ + return r, nil +} + // Unpack parses a full Message. func (m *Message) Unpack(msg []byte) error { var p Parser @@ -1557,6 +1575,30 @@ func (b *Builder) OPTResource(h ResourceHeader, r OPTResource) error { return nil } +// UnknownResource adds a single UnknownResource. +func (b *Builder) UnknownResource(h ResourceHeader, r UnknownResource) error { + if err := b.checkResourceSection(); err != nil { + return err + } + h.Type = r.realType() + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) + if err != nil { + return &nestedError{"ResourceHeader", err} + } + preLen := len(msg) + if msg, err = r.pack(msg, b.compression, b.start); err != nil { + return &nestedError{"UnknownResource body", err} + } + if err := h.fixLen(msg, lenOff, preLen); err != nil { + return err + } + if err := b.incrementSectionCount(); err != nil { + return err + } + b.msg = msg + return nil +} + // Finish ends message building and generates a binary message. func (b *Builder) Finish() ([]byte, error) { if b.section < sectionHeader { @@ -2135,13 +2177,15 @@ func unpackResourceBody(msg []byte, off int, hdr ResourceHeader) (ResourceBody, rb, err = unpackOPTResource(msg, off, hdr.Length) r = &rb name = "OPT" + default: + var rb UnknownResource + rb, err = unpackUnknownResource(hdr.Type, msg, off, hdr.Length) + r = &rb + name = "Unknown" } if err != nil { return nil, off, &nestedError{name + " record", err} } - if r == nil { - return nil, off, errors.New("invalid resource type: " + hdr.Type.String()) - } return r, off + int(hdr.Length), nil } @@ -2585,3 +2629,36 @@ func unpackOPTResource(msg []byte, off int, length uint16) (OPTResource, error) } return OPTResource{opts}, nil } + +// An UnknownResource is a catch-all container for unknown record types. +type UnknownResource struct { + Type Type + Data []byte +} + +func (r *UnknownResource) realType() Type { + return r.Type +} + +// pack appends the wire format of the UnknownResource to msg. +func (r *UnknownResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { + return packBytes(msg, r.Data[:]), nil +} + +// GoString implements fmt.GoStringer.GoString. +func (r *UnknownResource) GoString() string { + return "dnsmessage.UnknownResource{" + + "Type: " + r.Type.GoString() + ", " + + "Data: []byte{" + printByteSlice(r.Data) + "}}" +} + +func unpackUnknownResource(recordType Type, msg []byte, off int, length uint16) (UnknownResource, error) { + parsed := UnknownResource{ + Type: recordType, + Data: make([]byte, length), + } + if _, err := unpackBytes(msg, off, parsed.Data); err != nil { + return UnknownResource{}, err + } + return parsed, nil +} diff --git a/libgo/go/golang.org/x/net/idna/idna10.0.0.go b/libgo/go/golang.org/x/net/idna/idna10.0.0.go index a98a31f..5208ba6 100644 --- a/libgo/go/golang.org/x/net/idna/idna10.0.0.go +++ b/libgo/go/golang.org/x/net/idna/idna10.0.0.go @@ -4,6 +4,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build go1.10 // +build go1.10 // Package idna implements IDNA2008 using the compatibility processing @@ -66,15 +67,14 @@ func Transitional(transitional bool) Option { // VerifyDNSLength sets whether a Profile should fail if any of the IDN parts // are longer than allowed by the RFC. +// +// This option corresponds to the VerifyDnsLength flag in UTS #46. func VerifyDNSLength(verify bool) Option { return func(o *options) { o.verifyDNSLength = verify } } // RemoveLeadingDots removes leading label separators. Leading runes that map to // dots, such as U+3002 IDEOGRAPHIC FULL STOP, are removed as well. -// -// This is the behavior suggested by the UTS #46 and is adopted by some -// browsers. func RemoveLeadingDots(remove bool) Option { return func(o *options) { o.removeLeadingDots = remove } } @@ -82,6 +82,8 @@ func RemoveLeadingDots(remove bool) Option { // ValidateLabels sets whether to check the mandatory label validation criteria // as defined in Section 5.4 of RFC 5891. This includes testing for correct use // of hyphens ('-'), normalization, validity of runes, and the context rules. +// In particular, ValidateLabels also sets the CheckHyphens and CheckJoiners flags +// in UTS #46. func ValidateLabels(enable bool) Option { return func(o *options) { // Don't override existing mappings, but set one that at least checks @@ -90,25 +92,48 @@ func ValidateLabels(enable bool) Option { o.mapping = normalize } o.trie = trie - o.validateLabels = enable - o.fromPuny = validateFromPunycode + o.checkJoiners = enable + o.checkHyphens = enable + if enable { + o.fromPuny = validateFromPunycode + } else { + o.fromPuny = nil + } + } +} + +// CheckHyphens sets whether to check for correct use of hyphens ('-') in +// labels. Most web browsers do not have this option set, since labels such as +// "r3---sn-apo3qvuoxuxbt-j5pe" are in common use. +// +// This option corresponds to the CheckHyphens flag in UTS #46. +func CheckHyphens(enable bool) Option { + return func(o *options) { o.checkHyphens = enable } +} + +// CheckJoiners sets whether to check the ContextJ rules as defined in Appendix +// A of RFC 5892, concerning the use of joiner runes. +// +// This option corresponds to the CheckJoiners flag in UTS #46. +func CheckJoiners(enable bool) Option { + return func(o *options) { + o.trie = trie + o.checkJoiners = enable } } // StrictDomainName limits the set of permissible ASCII characters to those // allowed in domain names as defined in RFC 1034 (A-Z, a-z, 0-9 and the -// hyphen). This is set by default for MapForLookup and ValidateForRegistration. +// hyphen). This is set by default for MapForLookup and ValidateForRegistration, +// but is only useful if ValidateLabels is set. // // This option is useful, for instance, for browsers that allow characters // outside this range, for example a '_' (U+005F LOW LINE). See -// http://www.rfc-editor.org/std/std3.txt for more details This option -// corresponds to the UseSTD3ASCIIRules option in UTS #46. +// http://www.rfc-editor.org/std/std3.txt for more details. +// +// This option corresponds to the UseSTD3ASCIIRules flag in UTS #46. func StrictDomainName(use bool) Option { - return func(o *options) { - o.trie = trie - o.useSTD3Rules = use - o.fromPuny = validateFromPunycode - } + return func(o *options) { o.useSTD3Rules = use } } // NOTE: the following options pull in tables. The tables should not be linked @@ -116,6 +141,8 @@ func StrictDomainName(use bool) Option { // BidiRule enables the Bidi rule as defined in RFC 5893. Any application // that relies on proper validation of labels should include this rule. +// +// This option corresponds to the CheckBidi flag in UTS #46. func BidiRule() Option { return func(o *options) { o.bidirule = bidirule.ValidString } } @@ -151,7 +178,8 @@ func MapForLookup() Option { type options struct { transitional bool useSTD3Rules bool - validateLabels bool + checkHyphens bool + checkJoiners bool verifyDNSLength bool removeLeadingDots bool @@ -224,8 +252,11 @@ func (p *Profile) String() string { if p.useSTD3Rules { s += ":UseSTD3Rules" } - if p.validateLabels { - s += ":ValidateLabels" + if p.checkHyphens { + s += ":CheckHyphens" + } + if p.checkJoiners { + s += ":CheckJoiners" } if p.verifyDNSLength { s += ":VerifyDNSLength" @@ -253,26 +284,29 @@ var ( punycode = &Profile{} lookup = &Profile{options{ - transitional: true, - useSTD3Rules: true, - validateLabels: true, - trie: trie, - fromPuny: validateFromPunycode, - mapping: validateAndMap, - bidirule: bidirule.ValidString, + transitional: true, + useSTD3Rules: true, + checkHyphens: true, + checkJoiners: true, + trie: trie, + fromPuny: validateFromPunycode, + mapping: validateAndMap, + bidirule: bidirule.ValidString, }} display = &Profile{options{ - useSTD3Rules: true, - validateLabels: true, - trie: trie, - fromPuny: validateFromPunycode, - mapping: validateAndMap, - bidirule: bidirule.ValidString, + useSTD3Rules: true, + checkHyphens: true, + checkJoiners: true, + trie: trie, + fromPuny: validateFromPunycode, + mapping: validateAndMap, + bidirule: bidirule.ValidString, }} registration = &Profile{options{ useSTD3Rules: true, - validateLabels: true, verifyDNSLength: true, + checkHyphens: true, + checkJoiners: true, trie: trie, fromPuny: validateFromPunycode, mapping: validateRegistration, @@ -339,7 +373,7 @@ func (p *Profile) process(s string, toASCII bool) (string, error) { } isBidi = isBidi || bidirule.DirectionString(u) != bidi.LeftToRight labels.set(u) - if err == nil && p.validateLabels { + if err == nil && p.fromPuny != nil { err = p.fromPuny(p, u) } if err == nil { @@ -680,16 +714,18 @@ func (p *Profile) validateLabel(s string) (err error) { } return nil } - if !p.validateLabels { - return nil - } - trie := p.trie // p.validateLabels is only set if trie is set. - if len(s) > 4 && s[2] == '-' && s[3] == '-' { - return &labelError{s, "V2"} + if p.checkHyphens { + if len(s) > 4 && s[2] == '-' && s[3] == '-' { + return &labelError{s, "V2"} + } + if s[0] == '-' || s[len(s)-1] == '-' { + return &labelError{s, "V3"} + } } - if s[0] == '-' || s[len(s)-1] == '-' { - return &labelError{s, "V3"} + if !p.checkJoiners { + return nil } + trie := p.trie // p.checkJoiners is only set if trie is set. // TODO: merge the use of this in the trie. v, sz := trie.lookupString(s) x := info(v) diff --git a/libgo/go/golang.org/x/net/idna/idna9.0.0.go b/libgo/go/golang.org/x/net/idna/idna9.0.0.go index 8842146..55f718f 100644 --- a/libgo/go/golang.org/x/net/idna/idna9.0.0.go +++ b/libgo/go/golang.org/x/net/idna/idna9.0.0.go @@ -4,6 +4,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !go1.10 // +build !go1.10 // Package idna implements IDNA2008 using the compatibility processing @@ -65,15 +66,14 @@ func Transitional(transitional bool) Option { // VerifyDNSLength sets whether a Profile should fail if any of the IDN parts // are longer than allowed by the RFC. +// +// This option corresponds to the VerifyDnsLength flag in UTS #46. func VerifyDNSLength(verify bool) Option { return func(o *options) { o.verifyDNSLength = verify } } // RemoveLeadingDots removes leading label separators. Leading runes that map to // dots, such as U+3002 IDEOGRAPHIC FULL STOP, are removed as well. -// -// This is the behavior suggested by the UTS #46 and is adopted by some -// browsers. func RemoveLeadingDots(remove bool) Option { return func(o *options) { o.removeLeadingDots = remove } } @@ -81,6 +81,8 @@ func RemoveLeadingDots(remove bool) Option { // ValidateLabels sets whether to check the mandatory label validation criteria // as defined in Section 5.4 of RFC 5891. This includes testing for correct use // of hyphens ('-'), normalization, validity of runes, and the context rules. +// In particular, ValidateLabels also sets the CheckHyphens and CheckJoiners flags +// in UTS #46. func ValidateLabels(enable bool) Option { return func(o *options) { // Don't override existing mappings, but set one that at least checks @@ -89,25 +91,48 @@ func ValidateLabels(enable bool) Option { o.mapping = normalize } o.trie = trie - o.validateLabels = enable - o.fromPuny = validateFromPunycode + o.checkJoiners = enable + o.checkHyphens = enable + if enable { + o.fromPuny = validateFromPunycode + } else { + o.fromPuny = nil + } + } +} + +// CheckHyphens sets whether to check for correct use of hyphens ('-') in +// labels. Most web browsers do not have this option set, since labels such as +// "r3---sn-apo3qvuoxuxbt-j5pe" are in common use. +// +// This option corresponds to the CheckHyphens flag in UTS #46. +func CheckHyphens(enable bool) Option { + return func(o *options) { o.checkHyphens = enable } +} + +// CheckJoiners sets whether to check the ContextJ rules as defined in Appendix +// A of RFC 5892, concerning the use of joiner runes. +// +// This option corresponds to the CheckJoiners flag in UTS #46. +func CheckJoiners(enable bool) Option { + return func(o *options) { + o.trie = trie + o.checkJoiners = enable } } // StrictDomainName limits the set of permissable ASCII characters to those // allowed in domain names as defined in RFC 1034 (A-Z, a-z, 0-9 and the -// hyphen). This is set by default for MapForLookup and ValidateForRegistration. +// hyphen). This is set by default for MapForLookup and ValidateForRegistration, +// but is only useful if ValidateLabels is set. // // This option is useful, for instance, for browsers that allow characters // outside this range, for example a '_' (U+005F LOW LINE). See -// http://www.rfc-editor.org/std/std3.txt for more details This option -// corresponds to the UseSTD3ASCIIRules option in UTS #46. +// http://www.rfc-editor.org/std/std3.txt for more details. +// +// This option corresponds to the UseSTD3ASCIIRules flag in UTS #46. func StrictDomainName(use bool) Option { - return func(o *options) { - o.trie = trie - o.useSTD3Rules = use - o.fromPuny = validateFromPunycode - } + return func(o *options) { o.useSTD3Rules = use } } // NOTE: the following options pull in tables. The tables should not be linked @@ -115,6 +140,8 @@ func StrictDomainName(use bool) Option { // BidiRule enables the Bidi rule as defined in RFC 5893. Any application // that relies on proper validation of labels should include this rule. +// +// This option corresponds to the CheckBidi flag in UTS #46. func BidiRule() Option { return func(o *options) { o.bidirule = bidirule.ValidString } } @@ -151,7 +178,8 @@ func MapForLookup() Option { type options struct { transitional bool useSTD3Rules bool - validateLabels bool + checkHyphens bool + checkJoiners bool verifyDNSLength bool removeLeadingDots bool @@ -224,8 +252,11 @@ func (p *Profile) String() string { if p.useSTD3Rules { s += ":UseSTD3Rules" } - if p.validateLabels { - s += ":ValidateLabels" + if p.checkHyphens { + s += ":CheckHyphens" + } + if p.checkJoiners { + s += ":CheckJoiners" } if p.verifyDNSLength { s += ":VerifyDNSLength" @@ -254,9 +285,10 @@ var ( punycode = &Profile{} lookup = &Profile{options{ transitional: true, - useSTD3Rules: true, - validateLabels: true, removeLeadingDots: true, + useSTD3Rules: true, + checkHyphens: true, + checkJoiners: true, trie: trie, fromPuny: validateFromPunycode, mapping: validateAndMap, @@ -264,8 +296,9 @@ var ( }} display = &Profile{options{ useSTD3Rules: true, - validateLabels: true, removeLeadingDots: true, + checkHyphens: true, + checkJoiners: true, trie: trie, fromPuny: validateFromPunycode, mapping: validateAndMap, @@ -273,8 +306,9 @@ var ( }} registration = &Profile{options{ useSTD3Rules: true, - validateLabels: true, verifyDNSLength: true, + checkHyphens: true, + checkJoiners: true, trie: trie, fromPuny: validateFromPunycode, mapping: validateRegistration, @@ -338,7 +372,7 @@ func (p *Profile) process(s string, toASCII bool) (string, error) { continue } labels.set(u) - if err == nil && p.validateLabels { + if err == nil && p.fromPuny != nil { err = p.fromPuny(p, u) } if err == nil { @@ -628,16 +662,18 @@ func (p *Profile) validateLabel(s string) error { if p.bidirule != nil && !p.bidirule(s) { return &labelError{s, "B"} } - if !p.validateLabels { - return nil - } - trie := p.trie // p.validateLabels is only set if trie is set. - if len(s) > 4 && s[2] == '-' && s[3] == '-' { - return &labelError{s, "V2"} + if p.checkHyphens { + if len(s) > 4 && s[2] == '-' && s[3] == '-' { + return &labelError{s, "V2"} + } + if s[0] == '-' || s[len(s)-1] == '-' { + return &labelError{s, "V3"} + } } - if s[0] == '-' || s[len(s)-1] == '-' { - return &labelError{s, "V3"} + if !p.checkJoiners { + return nil } + trie := p.trie // p.checkJoiners is only set if trie is set. // TODO: merge the use of this in the trie. v, sz := trie.lookupString(s) x := info(v) diff --git a/libgo/go/golang.org/x/net/idna/tables10.0.0.go b/libgo/go/golang.org/x/net/idna/tables10.0.0.go index 54fddb4..d1d62ef 100644 --- a/libgo/go/golang.org/x/net/idna/tables10.0.0.go +++ b/libgo/go/golang.org/x/net/idna/tables10.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build go1.10 && !go1.13 // +build go1.10,!go1.13 package idna diff --git a/libgo/go/golang.org/x/net/idna/tables11.0.0.go b/libgo/go/golang.org/x/net/idna/tables11.0.0.go index 8ce0811..167efba 100644 --- a/libgo/go/golang.org/x/net/idna/tables11.0.0.go +++ b/libgo/go/golang.org/x/net/idna/tables11.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build go1.13 && !go1.14 // +build go1.13,!go1.14 package idna diff --git a/libgo/go/golang.org/x/net/idna/tables12.0.0.go b/libgo/go/golang.org/x/net/idna/tables12.0.0.go index f39f0cb..ab40f7b 100644 --- a/libgo/go/golang.org/x/net/idna/tables12.0.0.go +++ b/libgo/go/golang.org/x/net/idna/tables12.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build go1.14 && !go1.16 // +build go1.14,!go1.16 package idna diff --git a/libgo/go/golang.org/x/net/idna/tables13.0.0.go b/libgo/go/golang.org/x/net/idna/tables13.0.0.go index e8c7a36..390c5e5 100644 --- a/libgo/go/golang.org/x/net/idna/tables13.0.0.go +++ b/libgo/go/golang.org/x/net/idna/tables13.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build go1.16 // +build go1.16 package idna diff --git a/libgo/go/golang.org/x/net/idna/tables9.0.0.go b/libgo/go/golang.org/x/net/idna/tables9.0.0.go index 8b65fa1..4074b53 100644 --- a/libgo/go/golang.org/x/net/idna/tables9.0.0.go +++ b/libgo/go/golang.org/x/net/idna/tables9.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build !go1.10 // +build !go1.10 package idna diff --git a/libgo/go/golang.org/x/net/nettest/nettest_stub.go b/libgo/go/golang.org/x/net/nettest/nettest_stub.go index 22c2461..6e3a931 100644 --- a/libgo/go/golang.org/x/net/nettest/nettest_stub.go +++ b/libgo/go/golang.org/x/net/nettest/nettest_stub.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows && !zos // +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows,!zos package nettest diff --git a/libgo/go/golang.org/x/net/nettest/nettest_unix.go b/libgo/go/golang.org/x/net/nettest/nettest_unix.go index c1b1359..b1cb8b2 100644 --- a/libgo/go/golang.org/x/net/nettest/nettest_unix.go +++ b/libgo/go/golang.org/x/net/nettest/nettest_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos package nettest diff --git a/libgo/go/golang.org/x/net/route/address.go b/libgo/go/golang.org/x/net/route/address.go index 3c2fe15..4f6ad968 100644 --- a/libgo/go/golang.org/x/net/route/address.go +++ b/libgo/go/golang.org/x/net/route/address.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || netbsd || openbsd // +build darwin dragonfly freebsd netbsd openbsd package route diff --git a/libgo/go/golang.org/x/net/route/binary.go b/libgo/go/golang.org/x/net/route/binary.go index 6910520..a5e28f1 100644 --- a/libgo/go/golang.org/x/net/route/binary.go +++ b/libgo/go/golang.org/x/net/route/binary.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || netbsd || openbsd // +build darwin dragonfly freebsd netbsd openbsd package route diff --git a/libgo/go/golang.org/x/net/route/interface.go b/libgo/go/golang.org/x/net/route/interface.go index 05ef2a9..9e94078 100644 --- a/libgo/go/golang.org/x/net/route/interface.go +++ b/libgo/go/golang.org/x/net/route/interface.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || netbsd || openbsd // +build darwin dragonfly freebsd netbsd openbsd package route diff --git a/libgo/go/golang.org/x/net/route/interface_announce.go b/libgo/go/golang.org/x/net/route/interface_announce.go index 520d657..8282bfe 100644 --- a/libgo/go/golang.org/x/net/route/interface_announce.go +++ b/libgo/go/golang.org/x/net/route/interface_announce.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build dragonfly || freebsd || netbsd // +build dragonfly freebsd netbsd package route diff --git a/libgo/go/golang.org/x/net/route/interface_classic.go b/libgo/go/golang.org/x/net/route/interface_classic.go index ac4e7a6..85b7e99 100644 --- a/libgo/go/golang.org/x/net/route/interface_classic.go +++ b/libgo/go/golang.org/x/net/route/interface_classic.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || netbsd // +build darwin dragonfly netbsd package route diff --git a/libgo/go/golang.org/x/net/route/interface_multicast.go b/libgo/go/golang.org/x/net/route/interface_multicast.go index 1e99a9c..dd0b214 100644 --- a/libgo/go/golang.org/x/net/route/interface_multicast.go +++ b/libgo/go/golang.org/x/net/route/interface_multicast.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd // +build darwin dragonfly freebsd package route diff --git a/libgo/go/golang.org/x/net/route/message.go b/libgo/go/golang.org/x/net/route/message.go index 80c482a..d53bb7f 100644 --- a/libgo/go/golang.org/x/net/route/message.go +++ b/libgo/go/golang.org/x/net/route/message.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || netbsd || openbsd // +build darwin dragonfly freebsd netbsd openbsd package route diff --git a/libgo/go/golang.org/x/net/route/route.go b/libgo/go/golang.org/x/net/route/route.go index 4462cf1..fd0019e 100644 --- a/libgo/go/golang.org/x/net/route/route.go +++ b/libgo/go/golang.org/x/net/route/route.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || netbsd || openbsd // +build darwin dragonfly freebsd netbsd openbsd // Package route provides basic functions for the manipulation of @@ -107,17 +108,28 @@ const ( // an interface index or a set of interface flags. In most cases, zero // means a wildcard. func FetchRIB(af int, typ RIBType, arg int) ([]byte, error) { - mib := [6]int32{sysCTL_NET, sysAF_ROUTE, 0, int32(af), int32(typ), int32(arg)} - n := uintptr(0) - if err := sysctl(mib[:], nil, &n, nil, 0); err != nil { - return nil, os.NewSyscallError("sysctl", err) + try := 0 + for { + try++ + mib := [6]int32{sysCTL_NET, sysAF_ROUTE, 0, int32(af), int32(typ), int32(arg)} + n := uintptr(0) + if err := sysctl(mib[:], nil, &n, nil, 0); err != nil { + return nil, os.NewSyscallError("sysctl", err) + } + if n == 0 { + return nil, nil + } + b := make([]byte, n) + if err := sysctl(mib[:], &b[0], &n, nil, 0); err != nil { + // If the sysctl failed because the data got larger + // between the two sysctl calls, try a few times + // before failing. (golang.org/issue/45736). + const maxTries = 3 + if err == syscall.ENOMEM && try < maxTries { + continue + } + return nil, os.NewSyscallError("sysctl", err) + } + return b[:n], nil } - if n == 0 { - return nil, nil - } - b := make([]byte, n) - if err := sysctl(mib[:], &b[0], &n, nil, 0); err != nil { - return nil, os.NewSyscallError("sysctl", err) - } - return b[:n], nil } diff --git a/libgo/go/golang.org/x/net/route/route_classic.go b/libgo/go/golang.org/x/net/route/route_classic.go index b83add6..d6ee42f 100644 --- a/libgo/go/golang.org/x/net/route/route_classic.go +++ b/libgo/go/golang.org/x/net/route/route_classic.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || netbsd // +build darwin dragonfly freebsd netbsd package route diff --git a/libgo/go/golang.org/x/net/route/sys.go b/libgo/go/golang.org/x/net/route/sys.go index a0ab3e9..537484a 100644 --- a/libgo/go/golang.org/x/net/route/sys.go +++ b/libgo/go/golang.org/x/net/route/sys.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || netbsd || openbsd // +build darwin dragonfly freebsd netbsd openbsd package route diff --git a/libgo/go/golang.org/x/net/route/syscall.go b/libgo/go/golang.org/x/net/route/syscall.go index 72431b0..97166dd 100644 --- a/libgo/go/golang.org/x/net/route/syscall.go +++ b/libgo/go/golang.org/x/net/route/syscall.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build dragonfly || freebsd || netbsd || openbsd // +build dragonfly freebsd netbsd openbsd package route diff --git a/libgo/go/golang.org/x/net/route/syscall_go1_12_darwin.go b/libgo/go/golang.org/x/net/route/syscall_go1_12_darwin.go index 7922a68..7a13e4f 100644 --- a/libgo/go/golang.org/x/net/route/syscall_go1_12_darwin.go +++ b/libgo/go/golang.org/x/net/route/syscall_go1_12_darwin.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build go1.12 // +build go1.12 package route diff --git a/libgo/go/golang.org/x/sys/cpu/cpu.go b/libgo/go/golang.org/x/sys/cpu/cpu.go index f77701f..abbec2d 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu.go @@ -154,14 +154,13 @@ var MIPS64X struct { // For ppc64/ppc64le, it is safe to check only for ISA level starting on ISA v3.00, // since there are no optional categories. There are some exceptions that also // require kernel support to work (DARN, SCV), so there are feature bits for -// those as well. The minimum processor requirement is POWER8 (ISA 2.07). -// The struct is padded to avoid false sharing. +// those as well. The struct is padded to avoid false sharing. var PPC64 struct { _ CacheLinePad HasDARN bool // Hardware random number generator (requires kernel enablement) HasSCV bool // Syscall vectored (requires kernel enablement) IsPOWER8 bool // ISA v2.07 (POWER8) - IsPOWER9 bool // ISA v3.00 (POWER9) + IsPOWER9 bool // ISA v3.00 (POWER9), implies IsPOWER8 _ CacheLinePad } diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_aix.go b/libgo/go/golang.org/x/sys/cpu/cpu_aix.go index 464a209..8aaeef5 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_aix.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_aix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix // +build aix package cpu @@ -19,6 +20,7 @@ func archInit() { PPC64.IsPOWER8 = true } if impl&_IMPL_POWER9 != 0 { + PPC64.IsPOWER8 = true PPC64.IsPOWER9 = true } diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_gc_arm64.go b/libgo/go/golang.org/x/sys/cpu/cpu_gc_arm64.go index 7f7f272..ccf542a 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_gc_arm64.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_gc_arm64.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gc // +build gc package cpu diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_gc_s390x.go b/libgo/go/golang.org/x/sys/cpu/cpu_gc_s390x.go index 75a9556..0af2f24 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_gc_s390x.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_gc_s390x.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gc // +build gc package cpu diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_gc_x86.go b/libgo/go/golang.org/x/sys/cpu/cpu_gc_x86.go index 4adb89c..3298a87 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_gc_x86.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_gc_x86.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (386 || amd64 || amd64p32) && gc // +build 386 amd64 amd64p32 // +build gc @@ -14,3 +15,7 @@ func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) // xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler // and in cpu_gccgo.c for gccgo. func xgetbv() (eax, edx uint32) + +// darwinSupportsAVX512 is implemented in cpu_x86.s for gc compiler +// and in cpu_gccgo_x86.go for gccgo. +func darwinSupportsAVX512() bool diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_arm64.go b/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_arm64.go index 53ca8d6..2aff318 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_arm64.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_arm64.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gccgo // +build gccgo package cpu diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_s390x.go b/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_s390x.go index aa986f7..4bfbda6 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_s390x.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_s390x.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gccgo // +build gccgo package cpu diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_x86.go b/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_x86.go index ba49b91..863d415 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_x86.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_x86.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (386 || amd64 || amd64p32) && gccgo // +build 386 amd64 amd64p32 // +build gccgo @@ -24,3 +25,9 @@ func xgetbv() (eax, edx uint32) { gccgoXgetbv(&a, &d) return a, d } + +// gccgo doesn't build on Darwin, per: +// https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/gcc.rb#L76 +func darwinSupportsAVX512() bool { + return false +} diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_linux.go b/libgo/go/golang.org/x/sys/cpu/cpu_linux.go index 6fc874f..159a686 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_linux.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_linux.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !386 && !amd64 && !amd64p32 && !arm64 // +build !386,!amd64,!amd64p32,!arm64 package cpu diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_linux_mips64x.go b/libgo/go/golang.org/x/sys/cpu/cpu_linux_mips64x.go index 5a41890..6000db4 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_linux_mips64x.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_linux_mips64x.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux && (mips64 || mips64le) // +build linux // +build mips64 mips64le diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_linux_noinit.go b/libgo/go/golang.org/x/sys/cpu/cpu_linux_noinit.go index 42b5d33..f4992b1 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_linux_noinit.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_linux_noinit.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x // +build linux,!arm,!arm64,!mips64,!mips64le,!ppc64,!ppc64le,!s390x package cpu diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_linux_ppc64x.go b/libgo/go/golang.org/x/sys/cpu/cpu_linux_ppc64x.go index 99f8a63..021356d 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_linux_ppc64x.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_linux_ppc64x.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux && (ppc64 || ppc64le) // +build linux // +build ppc64 ppc64le diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_mips64x.go b/libgo/go/golang.org/x/sys/cpu/cpu_mips64x.go index eb4e010..d10b980 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_mips64x.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_mips64x.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build mips64 || mips64le // +build mips64 mips64le package cpu diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_mipsx.go b/libgo/go/golang.org/x/sys/cpu/cpu_mipsx.go index f6767b7..e67e88f 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_mipsx.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_mipsx.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build mips || mipsle // +build mips mipsle package cpu diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_other_arm.go b/libgo/go/golang.org/x/sys/cpu/cpu_other_arm.go index b412efc..d7b4fb4 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_other_arm.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_other_arm.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !linux && arm // +build !linux,arm package cpu diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_other_arm64.go b/libgo/go/golang.org/x/sys/cpu/cpu_other_arm64.go index 16c1c40..f8c484f 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_other_arm64.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_other_arm64.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !linux,!netbsd -// +build arm64 +//go:build !linux && !netbsd && arm64 +// +build !linux,!netbsd,arm64 package cpu diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_other_mips64x.go b/libgo/go/golang.org/x/sys/cpu/cpu_other_mips64x.go index f49fad6..0dafe96 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_other_mips64x.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_other_mips64x.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !linux && (mips64 || mips64le) // +build !linux // +build mips64 mips64le diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_ppc64x.go b/libgo/go/golang.org/x/sys/cpu/cpu_ppc64x.go index aedfb17..f2e92c0 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_ppc64x.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_ppc64x.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ppc64 || ppc64le // +build ppc64 ppc64le package cpu diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_riscv64.go b/libgo/go/golang.org/x/sys/cpu/cpu_riscv64.go index 2001b99..edfa5b7 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_riscv64.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_riscv64.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build riscv64 // +build riscv64 package cpu diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_wasm.go b/libgo/go/golang.org/x/sys/cpu/cpu_wasm.go index 60017a6..8d4e8fb 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_wasm.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_wasm.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build wasm // +build wasm package cpu diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_x86.go b/libgo/go/golang.org/x/sys/cpu/cpu_x86.go index 8cc67e6..e50ed98 100644 --- a/libgo/go/golang.org/x/sys/cpu/cpu_x86.go +++ b/libgo/go/golang.org/x/sys/cpu/cpu_x86.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build 386 || amd64 || amd64p32 // +build 386 amd64 amd64p32 package cpu @@ -86,8 +87,14 @@ func archInit() { // Check if XMM and YMM registers have OS support. osSupportsAVX = isSet(1, eax) && isSet(2, eax) - // Check if OPMASK and ZMM registers have OS support. - osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax) + if runtime.GOOS == "darwin" { + // Check darwin commpage for AVX512 support. Necessary because: + // https://github.com/apple/darwin-xnu/blob/0a798f6738bc1db01281fc08ae024145e84df927/osfmk/i386/fpu.c#L175-L201 + osSupportsAVX512 = osSupportsAVX && darwinSupportsAVX512() + } else { + // Check if OPMASK and ZMM registers have OS support. + osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax) + } } X86.HasAVX = isSet(28, ecx1) && osSupportsAVX diff --git a/libgo/go/golang.org/x/sys/cpu/syscall_aix_gccgo.go b/libgo/go/golang.org/x/sys/cpu/syscall_aix_gccgo.go index 76fbe40..a864f24 100644 --- a/libgo/go/golang.org/x/sys/cpu/syscall_aix_gccgo.go +++ b/libgo/go/golang.org/x/sys/cpu/syscall_aix_gccgo.go @@ -8,8 +8,8 @@ // Morever, this file will be used during the building of // gccgo's libgo and thus must not used a CGo method. -// +build aix -// +build gccgo +//go:build aix && gccgo +// +build aix,gccgo package cpu diff --git a/libgo/go/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go b/libgo/go/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go index 5b427d6..904be42 100644 --- a/libgo/go/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go +++ b/libgo/go/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go @@ -6,8 +6,8 @@ // system call on AIX without depending on x/sys/unix. // (See golang.org/issue/32102) -// +build aix,ppc64 -// +build gc +//go:build aix && ppc64 && gc +// +build aix,ppc64,gc package cpu diff --git a/libgo/go/golang.org/x/text/secure/bidirule/bidirule10.0.0.go b/libgo/go/golang.org/x/text/secure/bidirule/bidirule10.0.0.go index e4c6228..8a7392c 100644 --- a/libgo/go/golang.org/x/text/secure/bidirule/bidirule10.0.0.go +++ b/libgo/go/golang.org/x/text/secure/bidirule/bidirule10.0.0.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build go1.10 // +build go1.10 package bidirule diff --git a/libgo/go/golang.org/x/text/secure/bidirule/bidirule9.0.0.go b/libgo/go/golang.org/x/text/secure/bidirule/bidirule9.0.0.go index 02b9e1e..bb0a920 100644 --- a/libgo/go/golang.org/x/text/secure/bidirule/bidirule9.0.0.go +++ b/libgo/go/golang.org/x/text/secure/bidirule/bidirule9.0.0.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !go1.10 // +build !go1.10 package bidirule diff --git a/libgo/go/golang.org/x/text/unicode/bidi/bidi.go b/libgo/go/golang.org/x/text/unicode/bidi/bidi.go index e8edc54..fd05760 100644 --- a/libgo/go/golang.org/x/text/unicode/bidi/bidi.go +++ b/libgo/go/golang.org/x/text/unicode/bidi/bidi.go @@ -12,15 +12,14 @@ // and without notice. package bidi // import "golang.org/x/text/unicode/bidi" -// TODO: -// The following functionality would not be hard to implement, but hinges on -// the definition of a Segmenter interface. For now this is up to the user. -// - Iterate over paragraphs -// - Segmenter to iterate over runs directly from a given text. -// Also: +// TODO // - Transformer for reordering? // - Transformer (validator, really) for Bidi Rule. +import ( + "bytes" +) + // This API tries to avoid dealing with embedding levels for now. Under the hood // these will be computed, but the question is to which extent the user should // know they exist. We should at some point allow the user to specify an @@ -49,7 +48,9 @@ const ( Neutral ) -type options struct{} +type options struct { + defaultDirection Direction +} // An Option is an option for Bidi processing. type Option func(*options) @@ -66,12 +67,62 @@ type Option func(*options) // DefaultDirection sets the default direction for a Paragraph. The direction is // overridden if the text contains directional characters. func DefaultDirection(d Direction) Option { - panic("unimplemented") + return func(opts *options) { + opts.defaultDirection = d + } } // A Paragraph holds a single Paragraph for Bidi processing. type Paragraph struct { - // buffers + p []byte + o Ordering + opts []Option + types []Class + pairTypes []bracketType + pairValues []rune + runes []rune + options options +} + +// Initialize the p.pairTypes, p.pairValues and p.types from the input previously +// set by p.SetBytes() or p.SetString(). Also limit the input up to (and including) a paragraph +// separator (bidi class B). +// +// The function p.Order() needs these values to be set, so this preparation could be postponed. +// But since the SetBytes and SetStrings functions return the length of the input up to the paragraph +// separator, the whole input needs to be processed anyway and should not be done twice. +// +// The function has the same return values as SetBytes() / SetString() +func (p *Paragraph) prepareInput() (n int, err error) { + p.runes = bytes.Runes(p.p) + bytecount := 0 + // clear slices from previous SetString or SetBytes + p.pairTypes = nil + p.pairValues = nil + p.types = nil + + for _, r := range p.runes { + props, i := LookupRune(r) + bytecount += i + cls := props.Class() + if cls == B { + return bytecount, nil + } + p.types = append(p.types, cls) + if props.IsOpeningBracket() { + p.pairTypes = append(p.pairTypes, bpOpen) + p.pairValues = append(p.pairValues, r) + } else if props.IsBracket() { + // this must be a closing bracket, + // since IsOpeningBracket is not true + p.pairTypes = append(p.pairTypes, bpClose) + p.pairValues = append(p.pairValues, r) + } else { + p.pairTypes = append(p.pairTypes, bpNone) + p.pairValues = append(p.pairValues, 0) + } + } + return bytecount, nil } // SetBytes configures p for the given paragraph text. It replaces text @@ -80,70 +131,150 @@ type Paragraph struct { // consumed from b including this separator. Error may be non-nil if options are // given. func (p *Paragraph) SetBytes(b []byte, opts ...Option) (n int, err error) { - panic("unimplemented") + p.p = b + p.opts = opts + return p.prepareInput() } -// SetString configures p for the given paragraph text. It replaces text -// previously set by SetBytes or SetString. If b contains a paragraph separator +// SetString configures s for the given paragraph text. It replaces text +// previously set by SetBytes or SetString. If s contains a paragraph separator // it will only process the first paragraph and report the number of bytes -// consumed from b including this separator. Error may be non-nil if options are +// consumed from s including this separator. Error may be non-nil if options are // given. func (p *Paragraph) SetString(s string, opts ...Option) (n int, err error) { - panic("unimplemented") + p.p = []byte(s) + p.opts = opts + return p.prepareInput() } // IsLeftToRight reports whether the principle direction of rendering for this // paragraphs is left-to-right. If this returns false, the principle direction // of rendering is right-to-left. func (p *Paragraph) IsLeftToRight() bool { - panic("unimplemented") + return p.Direction() == LeftToRight } // Direction returns the direction of the text of this paragraph. // // The direction may be LeftToRight, RightToLeft, Mixed, or Neutral. func (p *Paragraph) Direction() Direction { - panic("unimplemented") + return p.o.Direction() } +// TODO: what happens if the position is > len(input)? This should return an error. + // RunAt reports the Run at the given position of the input text. // // This method can be used for computing line breaks on paragraphs. func (p *Paragraph) RunAt(pos int) Run { - panic("unimplemented") + c := 0 + runNumber := 0 + for i, r := range p.o.runes { + c += len(r) + if pos < c { + runNumber = i + } + } + return p.o.Run(runNumber) +} + +func calculateOrdering(levels []level, runes []rune) Ordering { + var curDir Direction + + prevDir := Neutral + prevI := 0 + + o := Ordering{} + // lvl = 0,2,4,...: left to right + // lvl = 1,3,5,...: right to left + for i, lvl := range levels { + if lvl%2 == 0 { + curDir = LeftToRight + } else { + curDir = RightToLeft + } + if curDir != prevDir { + if i > 0 { + o.runes = append(o.runes, runes[prevI:i]) + o.directions = append(o.directions, prevDir) + o.startpos = append(o.startpos, prevI) + } + prevI = i + prevDir = curDir + } + } + o.runes = append(o.runes, runes[prevI:]) + o.directions = append(o.directions, prevDir) + o.startpos = append(o.startpos, prevI) + return o } // Order computes the visual ordering of all the runs in a Paragraph. func (p *Paragraph) Order() (Ordering, error) { - panic("unimplemented") + if len(p.types) == 0 { + return Ordering{}, nil + } + + for _, fn := range p.opts { + fn(&p.options) + } + lvl := level(-1) + if p.options.defaultDirection == RightToLeft { + lvl = 1 + } + para, err := newParagraph(p.types, p.pairTypes, p.pairValues, lvl) + if err != nil { + return Ordering{}, err + } + + levels := para.getLevels([]int{len(p.types)}) + + p.o = calculateOrdering(levels, p.runes) + return p.o, nil } // Line computes the visual ordering of runs for a single line starting and // ending at the given positions in the original text. func (p *Paragraph) Line(start, end int) (Ordering, error) { - panic("unimplemented") + lineTypes := p.types[start:end] + para, err := newParagraph(lineTypes, p.pairTypes[start:end], p.pairValues[start:end], -1) + if err != nil { + return Ordering{}, err + } + levels := para.getLevels([]int{len(lineTypes)}) + o := calculateOrdering(levels, p.runes[start:end]) + return o, nil } // An Ordering holds the computed visual order of runs of a Paragraph. Calling // SetBytes or SetString on the originating Paragraph invalidates an Ordering. // The methods of an Ordering should only be called by one goroutine at a time. -type Ordering struct{} +type Ordering struct { + runes [][]rune + directions []Direction + startpos []int +} // Direction reports the directionality of the runs. // // The direction may be LeftToRight, RightToLeft, Mixed, or Neutral. func (o *Ordering) Direction() Direction { - panic("unimplemented") + return o.directions[0] } // NumRuns returns the number of runs. func (o *Ordering) NumRuns() int { - panic("unimplemented") + return len(o.runes) } // Run returns the ith run within the ordering. func (o *Ordering) Run(i int) Run { - panic("unimplemented") + r := Run{ + runes: o.runes[i], + direction: o.directions[i], + startpos: o.startpos[i], + } + return r } // TODO: perhaps with options. @@ -155,16 +286,19 @@ func (o *Ordering) Run(i int) Run { // A Run is a continuous sequence of characters of a single direction. type Run struct { + runes []rune + direction Direction + startpos int } // String returns the text of the run in its original order. func (r *Run) String() string { - panic("unimplemented") + return string(r.runes) } // Bytes returns the text of the run in its original order. func (r *Run) Bytes() []byte { - panic("unimplemented") + return []byte(r.String()) } // TODO: methods for @@ -174,25 +308,52 @@ func (r *Run) Bytes() []byte { // Direction reports the direction of the run. func (r *Run) Direction() Direction { - panic("unimplemented") + return r.direction } -// Position of the Run within the text passed to SetBytes or SetString of the +// Pos returns the position of the Run within the text passed to SetBytes or SetString of the // originating Paragraph value. func (r *Run) Pos() (start, end int) { - panic("unimplemented") + return r.startpos, r.startpos + len(r.runes) - 1 } // AppendReverse reverses the order of characters of in, appends them to out, // and returns the result. Modifiers will still follow the runes they modify. // Brackets are replaced with their counterparts. func AppendReverse(out, in []byte) []byte { - panic("unimplemented") + ret := make([]byte, len(in)+len(out)) + copy(ret, out) + inRunes := bytes.Runes(in) + + for i, r := range inRunes { + prop, _ := LookupRune(r) + if prop.IsBracket() { + inRunes[i] = prop.reverseBracket(r) + } + } + + for i, j := 0, len(inRunes)-1; i < j; i, j = i+1, j-1 { + inRunes[i], inRunes[j] = inRunes[j], inRunes[i] + } + copy(ret[len(out):], string(inRunes)) + + return ret } // ReverseString reverses the order of characters in s and returns a new string. // Modifiers will still follow the runes they modify. Brackets are replaced with // their counterparts. func ReverseString(s string) string { - panic("unimplemented") + input := []rune(s) + li := len(input) + ret := make([]rune, li) + for i, r := range input { + prop, _ := LookupRune(r) + if prop.IsBracket() { + ret[li-i-1] = prop.reverseBracket(r) + } else { + ret[li-i-1] = r + } + } + return string(ret) } diff --git a/libgo/go/golang.org/x/text/unicode/bidi/core.go b/libgo/go/golang.org/x/text/unicode/bidi/core.go index 50deb66..e4c0811 100644 --- a/libgo/go/golang.org/x/text/unicode/bidi/core.go +++ b/libgo/go/golang.org/x/text/unicode/bidi/core.go @@ -4,7 +4,10 @@ package bidi -import "log" +import ( + "fmt" + "log" +) // This implementation is a port based on the reference implementation found at: // https://www.unicode.org/Public/PROGRAMS/BidiReferenceJava/ @@ -97,13 +100,20 @@ type paragraph struct { // rune (suggested is the rune of the open bracket for opening and matching // close brackets, after normalization). The embedding levels are optional, but // may be supplied to encode embedding levels of styled text. -// -// TODO: return an error. -func newParagraph(types []Class, pairTypes []bracketType, pairValues []rune, levels level) *paragraph { - validateTypes(types) - validatePbTypes(pairTypes) - validatePbValues(pairValues, pairTypes) - validateParagraphEmbeddingLevel(levels) +func newParagraph(types []Class, pairTypes []bracketType, pairValues []rune, levels level) (*paragraph, error) { + var err error + if err = validateTypes(types); err != nil { + return nil, err + } + if err = validatePbTypes(pairTypes); err != nil { + return nil, err + } + if err = validatePbValues(pairValues, pairTypes); err != nil { + return nil, err + } + if err = validateParagraphEmbeddingLevel(levels); err != nil { + return nil, err + } p := ¶graph{ initialTypes: append([]Class(nil), types...), @@ -115,7 +125,7 @@ func newParagraph(types []Class, pairTypes []bracketType, pairValues []rune, lev resultTypes: append([]Class(nil), types...), } p.run() - return p + return p, nil } func (p *paragraph) Len() int { return len(p.initialTypes) } @@ -1001,58 +1011,61 @@ func typeForLevel(level level) Class { return R } -// TODO: change validation to not panic - -func validateTypes(types []Class) { +func validateTypes(types []Class) error { if len(types) == 0 { - log.Panic("types is null") + return fmt.Errorf("types is null") } for i, t := range types[:len(types)-1] { if t == B { - log.Panicf("B type before end of paragraph at index: %d", i) + return fmt.Errorf("B type before end of paragraph at index: %d", i) } } + return nil } -func validateParagraphEmbeddingLevel(embeddingLevel level) { +func validateParagraphEmbeddingLevel(embeddingLevel level) error { if embeddingLevel != implicitLevel && embeddingLevel != 0 && embeddingLevel != 1 { - log.Panicf("illegal paragraph embedding level: %d", embeddingLevel) + return fmt.Errorf("illegal paragraph embedding level: %d", embeddingLevel) } + return nil } -func validateLineBreaks(linebreaks []int, textLength int) { +func validateLineBreaks(linebreaks []int, textLength int) error { prev := 0 for i, next := range linebreaks { if next <= prev { - log.Panicf("bad linebreak: %d at index: %d", next, i) + return fmt.Errorf("bad linebreak: %d at index: %d", next, i) } prev = next } if prev != textLength { - log.Panicf("last linebreak was %d, want %d", prev, textLength) + return fmt.Errorf("last linebreak was %d, want %d", prev, textLength) } + return nil } -func validatePbTypes(pairTypes []bracketType) { +func validatePbTypes(pairTypes []bracketType) error { if len(pairTypes) == 0 { - log.Panic("pairTypes is null") + return fmt.Errorf("pairTypes is null") } for i, pt := range pairTypes { switch pt { case bpNone, bpOpen, bpClose: default: - log.Panicf("illegal pairType value at %d: %v", i, pairTypes[i]) + return fmt.Errorf("illegal pairType value at %d: %v", i, pairTypes[i]) } } + return nil } -func validatePbValues(pairValues []rune, pairTypes []bracketType) { +func validatePbValues(pairValues []rune, pairTypes []bracketType) error { if pairValues == nil { - log.Panic("pairValues is null") + return fmt.Errorf("pairValues is null") } if len(pairTypes) != len(pairValues) { - log.Panic("pairTypes is different length from pairValues") + return fmt.Errorf("pairTypes is different length from pairValues") } + return nil } diff --git a/libgo/go/golang.org/x/text/unicode/bidi/tables10.0.0.go b/libgo/go/golang.org/x/text/unicode/bidi/tables10.0.0.go index d8c94e1..42fa8d7 100644 --- a/libgo/go/golang.org/x/text/unicode/bidi/tables10.0.0.go +++ b/libgo/go/golang.org/x/text/unicode/bidi/tables10.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build go1.10 && !go1.13 // +build go1.10,!go1.13 package bidi diff --git a/libgo/go/golang.org/x/text/unicode/bidi/tables11.0.0.go b/libgo/go/golang.org/x/text/unicode/bidi/tables11.0.0.go index 16b11db..56a0e1e 100644 --- a/libgo/go/golang.org/x/text/unicode/bidi/tables11.0.0.go +++ b/libgo/go/golang.org/x/text/unicode/bidi/tables11.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build go1.13 && !go1.14 // +build go1.13,!go1.14 package bidi diff --git a/libgo/go/golang.org/x/text/unicode/bidi/tables12.0.0.go b/libgo/go/golang.org/x/text/unicode/bidi/tables12.0.0.go index 647f2d4..baacf32 100644 --- a/libgo/go/golang.org/x/text/unicode/bidi/tables12.0.0.go +++ b/libgo/go/golang.org/x/text/unicode/bidi/tables12.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build go1.14 && !go1.16 // +build go1.14,!go1.16 package bidi diff --git a/libgo/go/golang.org/x/text/unicode/bidi/tables13.0.0.go b/libgo/go/golang.org/x/text/unicode/bidi/tables13.0.0.go index c937d09..f248eff 100644 --- a/libgo/go/golang.org/x/text/unicode/bidi/tables13.0.0.go +++ b/libgo/go/golang.org/x/text/unicode/bidi/tables13.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build go1.16 // +build go1.16 package bidi diff --git a/libgo/go/golang.org/x/text/unicode/bidi/tables9.0.0.go b/libgo/go/golang.org/x/text/unicode/bidi/tables9.0.0.go index 0ca0193..f517fdb 100644 --- a/libgo/go/golang.org/x/text/unicode/bidi/tables9.0.0.go +++ b/libgo/go/golang.org/x/text/unicode/bidi/tables9.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build !go1.10 // +build !go1.10 package bidi diff --git a/libgo/go/golang.org/x/text/unicode/norm/tables10.0.0.go b/libgo/go/golang.org/x/text/unicode/norm/tables10.0.0.go index 26fbd55..f5a0788 100644 --- a/libgo/go/golang.org/x/text/unicode/norm/tables10.0.0.go +++ b/libgo/go/golang.org/x/text/unicode/norm/tables10.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build go1.10 && !go1.13 // +build go1.10,!go1.13 package norm diff --git a/libgo/go/golang.org/x/text/unicode/norm/tables11.0.0.go b/libgo/go/golang.org/x/text/unicode/norm/tables11.0.0.go index 2c58f09..cb7239c 100644 --- a/libgo/go/golang.org/x/text/unicode/norm/tables11.0.0.go +++ b/libgo/go/golang.org/x/text/unicode/norm/tables11.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build go1.13 && !go1.14 // +build go1.13,!go1.14 package norm diff --git a/libgo/go/golang.org/x/text/unicode/norm/tables12.0.0.go b/libgo/go/golang.org/x/text/unicode/norm/tables12.0.0.go index 7e1ae09..11b2733 100644 --- a/libgo/go/golang.org/x/text/unicode/norm/tables12.0.0.go +++ b/libgo/go/golang.org/x/text/unicode/norm/tables12.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build go1.14 && !go1.16 // +build go1.14,!go1.16 package norm diff --git a/libgo/go/golang.org/x/text/unicode/norm/tables13.0.0.go b/libgo/go/golang.org/x/text/unicode/norm/tables13.0.0.go index 9ea1b42..96a130d 100644 --- a/libgo/go/golang.org/x/text/unicode/norm/tables13.0.0.go +++ b/libgo/go/golang.org/x/text/unicode/norm/tables13.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build go1.16 // +build go1.16 package norm diff --git a/libgo/go/golang.org/x/text/unicode/norm/tables9.0.0.go b/libgo/go/golang.org/x/text/unicode/norm/tables9.0.0.go index 9429069..0175eae 100644 --- a/libgo/go/golang.org/x/text/unicode/norm/tables9.0.0.go +++ b/libgo/go/golang.org/x/text/unicode/norm/tables9.0.0.go @@ -1,5 +1,6 @@ // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. +//go:build !go1.10 // +build !go1.10 package norm diff --git a/libgo/go/golang.org/x/tools/cover/profile.go b/libgo/go/golang.org/x/tools/cover/profile.go new file mode 100644 index 0000000..5719577 --- /dev/null +++ b/libgo/go/golang.org/x/tools/cover/profile.go @@ -0,0 +1,261 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cover provides support for parsing coverage profiles +// generated by "go test -coverprofile=cover.out". +package cover // import "golang.org/x/tools/cover" + +import ( + "bufio" + "errors" + "fmt" + "math" + "os" + "sort" + "strconv" + "strings" +) + +// Profile represents the profiling data for a specific file. +type Profile struct { + FileName string + Mode string + Blocks []ProfileBlock +} + +// ProfileBlock represents a single block of profiling data. +type ProfileBlock struct { + StartLine, StartCol int + EndLine, EndCol int + NumStmt, Count int +} + +type byFileName []*Profile + +func (p byFileName) Len() int { return len(p) } +func (p byFileName) Less(i, j int) bool { return p[i].FileName < p[j].FileName } +func (p byFileName) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +// ParseProfiles parses profile data in the specified file and returns a +// Profile for each source file described therein. +func ParseProfiles(fileName string) ([]*Profile, error) { + pf, err := os.Open(fileName) + if err != nil { + return nil, err + } + defer pf.Close() + + files := make(map[string]*Profile) + buf := bufio.NewReader(pf) + // First line is "mode: foo", where foo is "set", "count", or "atomic". + // Rest of file is in the format + // encoding/base64/base64.go:34.44,37.40 3 1 + // where the fields are: name.go:line.column,line.column numberOfStatements count + s := bufio.NewScanner(buf) + mode := "" + for s.Scan() { + line := s.Text() + if mode == "" { + const p = "mode: " + if !strings.HasPrefix(line, p) || line == p { + return nil, fmt.Errorf("bad mode line: %v", line) + } + mode = line[len(p):] + continue + } + fn, b, err := parseLine(line) + if err != nil { + return nil, fmt.Errorf("line %q doesn't match expected format: %v", line, err) + } + p := files[fn] + if p == nil { + p = &Profile{ + FileName: fn, + Mode: mode, + } + files[fn] = p + } + p.Blocks = append(p.Blocks, b) + } + if err := s.Err(); err != nil { + return nil, err + } + for _, p := range files { + sort.Sort(blocksByStart(p.Blocks)) + // Merge samples from the same location. + j := 1 + for i := 1; i < len(p.Blocks); i++ { + b := p.Blocks[i] + last := p.Blocks[j-1] + if b.StartLine == last.StartLine && + b.StartCol == last.StartCol && + b.EndLine == last.EndLine && + b.EndCol == last.EndCol { + if b.NumStmt != last.NumStmt { + return nil, fmt.Errorf("inconsistent NumStmt: changed from %d to %d", last.NumStmt, b.NumStmt) + } + if mode == "set" { + p.Blocks[j-1].Count |= b.Count + } else { + p.Blocks[j-1].Count += b.Count + } + continue + } + p.Blocks[j] = b + j++ + } + p.Blocks = p.Blocks[:j] + } + // Generate a sorted slice. + profiles := make([]*Profile, 0, len(files)) + for _, profile := range files { + profiles = append(profiles, profile) + } + sort.Sort(byFileName(profiles)) + return profiles, nil +} + +// parseLine parses a line from a coverage file. +// It is equivalent to the regex +// ^(.+):([0-9]+)\.([0-9]+),([0-9]+)\.([0-9]+) ([0-9]+) ([0-9]+)$ +// +// However, it is much faster: https://golang.org/cl/179377 +func parseLine(l string) (fileName string, block ProfileBlock, err error) { + end := len(l) + + b := ProfileBlock{} + b.Count, end, err = seekBack(l, ' ', end, "Count") + if err != nil { + return "", b, err + } + b.NumStmt, end, err = seekBack(l, ' ', end, "NumStmt") + if err != nil { + return "", b, err + } + b.EndCol, end, err = seekBack(l, '.', end, "EndCol") + if err != nil { + return "", b, err + } + b.EndLine, end, err = seekBack(l, ',', end, "EndLine") + if err != nil { + return "", b, err + } + b.StartCol, end, err = seekBack(l, '.', end, "StartCol") + if err != nil { + return "", b, err + } + b.StartLine, end, err = seekBack(l, ':', end, "StartLine") + if err != nil { + return "", b, err + } + fn := l[0:end] + if fn == "" { + return "", b, errors.New("a FileName cannot be blank") + } + return fn, b, nil +} + +// seekBack searches backwards from end to find sep in l, then returns the +// value between sep and end as an integer. +// If seekBack fails, the returned error will reference what. +func seekBack(l string, sep byte, end int, what string) (value int, nextSep int, err error) { + // Since we're seeking backwards and we know only ASCII is legal for these values, + // we can ignore the possibility of non-ASCII characters. + for start := end - 1; start >= 0; start-- { + if l[start] == sep { + i, err := strconv.Atoi(l[start+1 : end]) + if err != nil { + return 0, 0, fmt.Errorf("couldn't parse %q: %v", what, err) + } + if i < 0 { + return 0, 0, fmt.Errorf("negative values are not allowed for %s, found %d", what, i) + } + return i, start, nil + } + } + return 0, 0, fmt.Errorf("couldn't find a %s before %s", string(sep), what) +} + +type blocksByStart []ProfileBlock + +func (b blocksByStart) Len() int { return len(b) } +func (b blocksByStart) Swap(i, j int) { b[i], b[j] = b[j], b[i] } +func (b blocksByStart) Less(i, j int) bool { + bi, bj := b[i], b[j] + return bi.StartLine < bj.StartLine || bi.StartLine == bj.StartLine && bi.StartCol < bj.StartCol +} + +// Boundary represents the position in a source file of the beginning or end of a +// block as reported by the coverage profile. In HTML mode, it will correspond to +// the opening or closing of a <span> tag and will be used to colorize the source +type Boundary struct { + Offset int // Location as a byte offset in the source file. + Start bool // Is this the start of a block? + Count int // Event count from the cover profile. + Norm float64 // Count normalized to [0..1]. + Index int // Order in input file. +} + +// Boundaries returns a Profile as a set of Boundary objects within the provided src. +func (p *Profile) Boundaries(src []byte) (boundaries []Boundary) { + // Find maximum count. + max := 0 + for _, b := range p.Blocks { + if b.Count > max { + max = b.Count + } + } + // Divisor for normalization. + divisor := math.Log(float64(max)) + + // boundary returns a Boundary, populating the Norm field with a normalized Count. + index := 0 + boundary := func(offset int, start bool, count int) Boundary { + b := Boundary{Offset: offset, Start: start, Count: count, Index: index} + index++ + if !start || count == 0 { + return b + } + if max <= 1 { + b.Norm = 0.8 // Profile is in"set" mode; we want a heat map. Use cov8 in the CSS. + } else if count > 0 { + b.Norm = math.Log(float64(count)) / divisor + } + return b + } + + line, col := 1, 2 // TODO: Why is this 2? + for si, bi := 0, 0; si < len(src) && bi < len(p.Blocks); { + b := p.Blocks[bi] + if b.StartLine == line && b.StartCol == col { + boundaries = append(boundaries, boundary(si, true, b.Count)) + } + if b.EndLine == line && b.EndCol == col || line > b.EndLine { + boundaries = append(boundaries, boundary(si, false, 0)) + bi++ + continue // Don't advance through src; maybe the next block starts here. + } + if src[si] == '\n' { + line++ + col = 0 + } + col++ + si++ + } + sort.Sort(boundariesByPos(boundaries)) + return +} + +type boundariesByPos []Boundary + +func (b boundariesByPos) Len() int { return len(b) } +func (b boundariesByPos) Swap(i, j int) { b[i], b[j] = b[j], b[i] } +func (b boundariesByPos) Less(i, j int) bool { + if b[i].Offset == b[j].Offset { + // Boundaries at the same offset should be ordered according to + // their original position. + return b[i].Index < b[j].Index + } + return b[i].Offset < b[j].Offset +} diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go b/libgo/go/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go index 841b928..c4407ad 100644 --- a/libgo/go/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go +++ b/libgo/go/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go @@ -2,14 +2,17 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build go1.16 +// +build go1.16 + // Package buildtag defines an Analyzer that checks build tags. package buildtag import ( - "bytes" - "fmt" "go/ast" + "go/build/constraint" "go/parser" + "go/token" "strings" "unicode" @@ -52,118 +55,313 @@ func runBuildTag(pass *analysis.Pass) (interface{}, error) { } func checkGoFile(pass *analysis.Pass, f *ast.File) { - pastCutoff := false + var check checker + check.init(pass) + defer check.finish() + for _, group := range f.Comments { // A +build comment is ignored after or adjoining the package declaration. if group.End()+1 >= f.Package { - pastCutoff = true + check.plusBuildOK = false } - - // "+build" is ignored within or after a /*...*/ comment. - if !strings.HasPrefix(group.List[0].Text, "//") { - pastCutoff = true - continue + // A //go:build comment is ignored after the package declaration + // (but adjoining it is OK, in contrast to +build comments). + if group.Pos() >= f.Package { + check.goBuildOK = false } // Check each line of a //-comment. for _, c := range group.List { - if !strings.Contains(c.Text, "+build") { - continue - } - if err := checkLine(c.Text, pastCutoff); err != nil { - pass.Reportf(c.Pos(), "%s", err) + // "+build" is ignored within or after a /*...*/ comment. + if !strings.HasPrefix(c.Text, "//") { + check.plusBuildOK = false } + check.comment(c.Slash, c.Text) } } } func checkOtherFile(pass *analysis.Pass, filename string) error { + var check checker + check.init(pass) + defer check.finish() + + // We cannot use the Go parser, since this may not be a Go source file. + // Read the raw bytes instead. content, tf, err := analysisutil.ReadFile(pass.Fset, filename) if err != nil { return err } - // We must look at the raw lines, as build tags may appear in non-Go - // files such as assembly files. - lines := bytes.SplitAfter(content, nl) + check.file(token.Pos(tf.Base()), string(content)) + return nil +} + +type checker struct { + pass *analysis.Pass + plusBuildOK bool // "+build" lines still OK + goBuildOK bool // "go:build" lines still OK + crossCheck bool // cross-check go:build and +build lines when done reading file + inStar bool // currently in a /* */ comment + goBuildPos token.Pos // position of first go:build line found + plusBuildPos token.Pos // position of first "+build" line found + goBuild constraint.Expr // go:build constraint found + plusBuild constraint.Expr // AND of +build constraints found +} + +func (check *checker) init(pass *analysis.Pass) { + check.pass = pass + check.goBuildOK = true + check.plusBuildOK = true + check.crossCheck = true +} +func (check *checker) file(pos token.Pos, text string) { // Determine cutpoint where +build comments are no longer valid. // They are valid in leading // comments in the file followed by // a blank line. // // This must be done as a separate pass because of the // requirement that the comment be followed by a blank line. - var cutoff int - for i, line := range lines { - line = bytes.TrimSpace(line) - if !bytes.HasPrefix(line, slashSlash) { - if len(line) > 0 { - break - } - cutoff = i + var plusBuildCutoff int + fullText := text + for text != "" { + i := strings.Index(text, "\n") + if i < 0 { + i = len(text) + } else { + i++ + } + offset := len(fullText) - len(text) + line := text[:i] + text = text[i:] + line = strings.TrimSpace(line) + if !strings.HasPrefix(line, "//") && line != "" { + break + } + if line == "" { + plusBuildCutoff = offset } } - for i, line := range lines { - line = bytes.TrimSpace(line) - if !bytes.HasPrefix(line, slashSlash) { - continue + // Process each line. + // Must stop once we hit goBuildOK == false + text = fullText + check.inStar = false + for text != "" { + i := strings.Index(text, "\n") + if i < 0 { + i = len(text) + } else { + i++ } - if !bytes.Contains(line, []byte("+build")) { + offset := len(fullText) - len(text) + line := text[:i] + text = text[i:] + check.plusBuildOK = offset < plusBuildCutoff + + if strings.HasPrefix(line, "//") { + check.comment(pos+token.Pos(offset), line) continue } - if err := checkLine(string(line), i >= cutoff); err != nil { - pass.Reportf(analysisutil.LineStart(tf, i+1), "%s", err) - continue + + // Keep looking for the point at which //go:build comments + // stop being allowed. Skip over, cut out any /* */ comments. + for { + line = strings.TrimSpace(line) + if check.inStar { + i := strings.Index(line, "*/") + if i < 0 { + line = "" + break + } + line = line[i+len("*/"):] + check.inStar = false + continue + } + if strings.HasPrefix(line, "/*") { + check.inStar = true + line = line[len("/*"):] + continue + } + break + } + if line != "" { + // Found non-comment non-blank line. + // Ends space for valid //go:build comments, + // but also ends the fraction of the file we can + // reliably parse. From this point on we might + // incorrectly flag "comments" inside multiline + // string constants or anything else (this might + // not even be a Go program). So stop. + break } } - return nil } -// checkLine checks a line that starts with "//" and contains "+build". -func checkLine(line string, pastCutoff bool) error { - line = strings.TrimPrefix(line, "//") - line = strings.TrimSpace(line) - - if strings.HasPrefix(line, "+build") { - fields := strings.Fields(line) - if fields[0] != "+build" { - // Comment is something like +buildasdf not +build. - return fmt.Errorf("possible malformed +build comment") +func (check *checker) comment(pos token.Pos, text string) { + if strings.HasPrefix(text, "//") { + if strings.Contains(text, "+build") { + check.plusBuildLine(pos, text) } - if pastCutoff { - return fmt.Errorf("+build comment must appear before package clause and be followed by a blank line") + if strings.Contains(text, "//go:build") { + check.goBuildLine(pos, text) } - if err := checkArguments(fields); err != nil { - return err + } + if strings.HasPrefix(text, "/*") { + if i := strings.Index(text, "\n"); i >= 0 { + // multiline /* */ comment - process interior lines + check.inStar = true + i++ + pos += token.Pos(i) + text = text[i:] + for text != "" { + i := strings.Index(text, "\n") + if i < 0 { + i = len(text) + } else { + i++ + } + line := text[:i] + if strings.HasPrefix(line, "//") { + check.comment(pos, line) + } + pos += token.Pos(i) + text = text[i:] + } + check.inStar = false + } + } +} + +func (check *checker) goBuildLine(pos token.Pos, line string) { + if !constraint.IsGoBuild(line) { + if !strings.HasPrefix(line, "//go:build") && constraint.IsGoBuild("//"+strings.TrimSpace(line[len("//"):])) { + check.pass.Reportf(pos, "malformed //go:build line (space between // and go:build)") } + return + } + if !check.goBuildOK || check.inStar { + check.pass.Reportf(pos, "misplaced //go:build comment") + check.crossCheck = false + return + } + + if check.goBuildPos == token.NoPos { + check.goBuildPos = pos } else { + check.pass.Reportf(pos, "unexpected extra //go:build line") + check.crossCheck = false + } + + // testing hack: stop at // ERROR + if i := strings.Index(line, " // ERROR "); i >= 0 { + line = line[:i] + } + + x, err := constraint.Parse(line) + if err != nil { + check.pass.Reportf(pos, "%v", err) + check.crossCheck = false + return + } + + if check.goBuild == nil { + check.goBuild = x + } +} + +func (check *checker) plusBuildLine(pos token.Pos, line string) { + line = strings.TrimSpace(line) + if !constraint.IsPlusBuild(line) { // Comment with +build but not at beginning. - if !pastCutoff { - return fmt.Errorf("possible malformed +build comment") + // Only report early in file. + if check.plusBuildOK && !strings.HasPrefix(line, "// want") { + check.pass.Reportf(pos, "possible malformed +build comment") } + return + } + if !check.plusBuildOK { // inStar implies !plusBuildOK + check.pass.Reportf(pos, "misplaced +build comment") + check.crossCheck = false } - return nil -} -func checkArguments(fields []string) error { + if check.plusBuildPos == token.NoPos { + check.plusBuildPos = pos + } + + // testing hack: stop at // ERROR + if i := strings.Index(line, " // ERROR "); i >= 0 { + line = line[:i] + } + + fields := strings.Fields(line[len("//"):]) + // IsPlusBuildConstraint check above implies fields[0] == "+build" for _, arg := range fields[1:] { for _, elem := range strings.Split(arg, ",") { if strings.HasPrefix(elem, "!!") { - return fmt.Errorf("invalid double negative in build constraint: %s", arg) + check.pass.Reportf(pos, "invalid double negative in build constraint: %s", arg) + check.crossCheck = false + continue } elem = strings.TrimPrefix(elem, "!") for _, c := range elem { if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' { - return fmt.Errorf("invalid non-alphanumeric build constraint: %s", arg) + check.pass.Reportf(pos, "invalid non-alphanumeric build constraint: %s", arg) + check.crossCheck = false + break } } } } - return nil + + if check.crossCheck { + y, err := constraint.Parse(line) + if err != nil { + // Should never happen - constraint.Parse never rejects a // +build line. + // Also, we just checked the syntax above. + // Even so, report. + check.pass.Reportf(pos, "%v", err) + check.crossCheck = false + return + } + if check.plusBuild == nil { + check.plusBuild = y + } else { + check.plusBuild = &constraint.AndExpr{X: check.plusBuild, Y: y} + } + } } -var ( - nl = []byte("\n") - slashSlash = []byte("//") -) +func (check *checker) finish() { + if !check.crossCheck || check.plusBuildPos == token.NoPos || check.goBuildPos == token.NoPos { + return + } + + // Have both //go:build and // +build, + // with no errors found (crossCheck still true). + // Check they match. + var want constraint.Expr + lines, err := constraint.PlusBuildLines(check.goBuild) + if err != nil { + check.pass.Reportf(check.goBuildPos, "%v", err) + return + } + for _, line := range lines { + y, err := constraint.Parse(line) + if err != nil { + // Definitely should not happen, but not the user's fault. + // Do not report. + return + } + if want == nil { + want = y + } else { + want = &constraint.AndExpr{X: want, Y: y} + } + } + if want.String() != check.plusBuild.String() { + check.pass.Reportf(check.plusBuildPos, "+build lines do not match //go:build condition") + return + } +} diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_old.go b/libgo/go/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_old.go new file mode 100644 index 0000000..e923492 --- /dev/null +++ b/libgo/go/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_old.go @@ -0,0 +1,174 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// TODO(rsc): Delete this file once Go 1.17 comes out and we can retire Go 1.15 support. + +//go:build !go1.16 +// +build !go1.16 + +// Package buildtag defines an Analyzer that checks build tags. +package buildtag + +import ( + "bytes" + "fmt" + "go/ast" + "go/parser" + "strings" + "unicode" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/internal/analysisutil" +) + +const Doc = "check that +build tags are well-formed and correctly located" + +var Analyzer = &analysis.Analyzer{ + Name: "buildtag", + Doc: Doc, + Run: runBuildTag, +} + +func runBuildTag(pass *analysis.Pass) (interface{}, error) { + for _, f := range pass.Files { + checkGoFile(pass, f) + } + for _, name := range pass.OtherFiles { + if err := checkOtherFile(pass, name); err != nil { + return nil, err + } + } + for _, name := range pass.IgnoredFiles { + if strings.HasSuffix(name, ".go") { + f, err := parser.ParseFile(pass.Fset, name, nil, parser.ParseComments) + if err != nil { + // Not valid Go source code - not our job to diagnose, so ignore. + return nil, nil + } + checkGoFile(pass, f) + } else { + if err := checkOtherFile(pass, name); err != nil { + return nil, err + } + } + } + return nil, nil +} + +func checkGoFile(pass *analysis.Pass, f *ast.File) { + pastCutoff := false + for _, group := range f.Comments { + // A +build comment is ignored after or adjoining the package declaration. + if group.End()+1 >= f.Package { + pastCutoff = true + } + + // "+build" is ignored within or after a /*...*/ comment. + if !strings.HasPrefix(group.List[0].Text, "//") { + pastCutoff = true + continue + } + + // Check each line of a //-comment. + for _, c := range group.List { + if !strings.Contains(c.Text, "+build") { + continue + } + if err := checkLine(c.Text, pastCutoff); err != nil { + pass.Reportf(c.Pos(), "%s", err) + } + } + } +} + +func checkOtherFile(pass *analysis.Pass, filename string) error { + content, tf, err := analysisutil.ReadFile(pass.Fset, filename) + if err != nil { + return err + } + + // We must look at the raw lines, as build tags may appear in non-Go + // files such as assembly files. + lines := bytes.SplitAfter(content, nl) + + // Determine cutpoint where +build comments are no longer valid. + // They are valid in leading // comments in the file followed by + // a blank line. + // + // This must be done as a separate pass because of the + // requirement that the comment be followed by a blank line. + var cutoff int + for i, line := range lines { + line = bytes.TrimSpace(line) + if !bytes.HasPrefix(line, slashSlash) { + if len(line) > 0 { + break + } + cutoff = i + } + } + + for i, line := range lines { + line = bytes.TrimSpace(line) + if !bytes.HasPrefix(line, slashSlash) { + continue + } + if !bytes.Contains(line, []byte("+build")) { + continue + } + if err := checkLine(string(line), i >= cutoff); err != nil { + pass.Reportf(analysisutil.LineStart(tf, i+1), "%s", err) + continue + } + } + return nil +} + +// checkLine checks a line that starts with "//" and contains "+build". +func checkLine(line string, pastCutoff bool) error { + line = strings.TrimPrefix(line, "//") + line = strings.TrimSpace(line) + + if strings.HasPrefix(line, "+build") { + fields := strings.Fields(line) + if fields[0] != "+build" { + // Comment is something like +buildasdf not +build. + return fmt.Errorf("possible malformed +build comment") + } + if pastCutoff { + return fmt.Errorf("+build comment must appear before package clause and be followed by a blank line") + } + if err := checkArguments(fields); err != nil { + return err + } + } else { + // Comment with +build but not at beginning. + if !pastCutoff { + return fmt.Errorf("possible malformed +build comment") + } + } + return nil +} + +func checkArguments(fields []string) error { + for _, arg := range fields[1:] { + for _, elem := range strings.Split(arg, ",") { + if strings.HasPrefix(elem, "!!") { + return fmt.Errorf("invalid double negative in build constraint: %s", arg) + } + elem = strings.TrimPrefix(elem, "!") + for _, c := range elem { + if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' { + return fmt.Errorf("invalid non-alphanumeric build constraint: %s", arg) + } + } + } + } + return nil +} + +var ( + nl = []byte("\n") + slashSlash = []byte("//") +) diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/inspect/inspect.go b/libgo/go/golang.org/x/tools/go/analysis/passes/inspect/inspect.go index 2856df1..4bb652a 100644 --- a/libgo/go/golang.org/x/tools/go/analysis/passes/inspect/inspect.go +++ b/libgo/go/golang.org/x/tools/go/analysis/passes/inspect/inspect.go @@ -3,8 +3,8 @@ // license that can be found in the LICENSE file. // Package inspect defines an Analyzer that provides an AST inspector -// (golang.org/x/tools/go/ast/inspect.Inspect) for the syntax trees of a -// package. It is only a building block for other analyzers. +// (golang.org/x/tools/go/ast/inspector.Inspector) for the syntax trees +// of a package. It is only a building block for other analyzers. // // Example of use in another analysis: // diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go b/libgo/go/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go index a14e7eb..3ea9157 100644 --- a/libgo/go/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go +++ b/libgo/go/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go @@ -8,22 +8,14 @@ package loopclosure import ( "go/ast" + "go/types" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" "golang.org/x/tools/go/ast/inspector" + "golang.org/x/tools/go/types/typeutil" ) -// TODO(adonovan): also report an error for the following structure, -// which is often used to ensure that deferred calls do not accumulate -// in a loop: -// -// for i, x := range c { -// func() { -// ...reference to i or x... -// }() -// } - const Doc = `check references to loop variables from within nested functions This analyzer checks for references to loop variables from within a @@ -95,16 +87,19 @@ func run(pass *analysis.Pass) (interface{}, error) { if len(body.List) == 0 { return } - var last *ast.CallExpr + // The function invoked in the last return statement. + var fun ast.Expr switch s := body.List[len(body.List)-1].(type) { case *ast.GoStmt: - last = s.Call + fun = s.Call.Fun case *ast.DeferStmt: - last = s.Call - default: - return + fun = s.Call.Fun + case *ast.ExprStmt: // check for errgroup.Group.Go() + if call, ok := s.X.(*ast.CallExpr); ok { + fun = goInvokes(pass.TypesInfo, call) + } } - lit, ok := last.Fun.(*ast.FuncLit) + lit, ok := fun.(*ast.FuncLit) if !ok { return } @@ -128,3 +123,43 @@ func run(pass *analysis.Pass) (interface{}, error) { }) return nil, nil } + +// goInvokes returns a function expression that would be called asynchronously +// (but not awaited) in another goroutine as a consequence of the call. +// For example, given the g.Go call below, it returns the function literal expression. +// +// import "sync/errgroup" +// var g errgroup.Group +// g.Go(func() error { ... }) +// +// Currently only "golang.org/x/sync/errgroup.Group()" is considered. +func goInvokes(info *types.Info, call *ast.CallExpr) ast.Expr { + f := typeutil.StaticCallee(info, call) + // Note: Currently only supports: golang.org/x/sync/errgroup.Go. + if f == nil || f.Name() != "Go" { + return nil + } + recv := f.Type().(*types.Signature).Recv() + if recv == nil { + return nil + } + rtype, ok := recv.Type().(*types.Pointer) + if !ok { + return nil + } + named, ok := rtype.Elem().(*types.Named) + if !ok { + return nil + } + if named.Obj().Name() != "Group" { + return nil + } + pkg := f.Pkg() + if pkg == nil { + return nil + } + if pkg.Path() != "golang.org/x/sync/errgroup" { + return nil + } + return call.Args[0] +} diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/printf/printf.go b/libgo/go/golang.org/x/tools/go/analysis/passes/printf/printf.go index ddad4c7..822820f 100644 --- a/libgo/go/golang.org/x/tools/go/analysis/passes/printf/printf.go +++ b/libgo/go/golang.org/x/tools/go/analysis/passes/printf/printf.go @@ -590,7 +590,7 @@ func checkPrintf(pass *analysis.Pass, kind Kind, call *ast.CallExpr, fn *types.F } if state.verb == 'w' { if kind != KindErrorf { - pass.Reportf(call.Pos(), "%s call has error-wrapping directive %%w", state.name) + pass.Reportf(call.Pos(), "%s call has error-wrapping directive %%w, which is only supported by Errorf", state.name) return } if anyW { diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/sigchanyzer/sigchanyzer.go b/libgo/go/golang.org/x/tools/go/analysis/passes/sigchanyzer/sigchanyzer.go new file mode 100644 index 0000000..0d6c8eb --- /dev/null +++ b/libgo/go/golang.org/x/tools/go/analysis/passes/sigchanyzer/sigchanyzer.go @@ -0,0 +1,154 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package sigchanyzer defines an Analyzer that detects +// misuse of unbuffered signal as argument to signal.Notify. +package sigchanyzer + +import ( + "bytes" + "go/ast" + "go/format" + "go/token" + "go/types" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" +) + +const Doc = `check for unbuffered channel of os.Signal + +This checker reports call expression of the form signal.Notify(c <-chan os.Signal, sig ...os.Signal), +where c is an unbuffered channel, which can be at risk of missing the signal.` + +// Analyzer describes sigchanyzer analysis function detector. +var Analyzer = &analysis.Analyzer{ + Name: "sigchanyzer", + Doc: Doc, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + Run: run, +} + +func run(pass *analysis.Pass) (interface{}, error) { + inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + + nodeFilter := []ast.Node{ + (*ast.CallExpr)(nil), + } + inspect.Preorder(nodeFilter, func(n ast.Node) { + call := n.(*ast.CallExpr) + if !isSignalNotify(pass.TypesInfo, call) { + return + } + var chanDecl *ast.CallExpr + switch arg := call.Args[0].(type) { + case *ast.Ident: + if decl, ok := findDecl(arg).(*ast.CallExpr); ok { + chanDecl = decl + } + case *ast.CallExpr: + // Only signal.Notify(make(chan os.Signal), os.Interrupt) is safe, + // conservatively treate others as not safe, see golang/go#45043 + if isBuiltinMake(pass.TypesInfo, arg) { + return + } + chanDecl = arg + } + if chanDecl == nil || len(chanDecl.Args) != 1 { + return + } + + // Make a copy of the channel's declaration to avoid + // mutating the AST. See https://golang.org/issue/46129. + chanDeclCopy := &ast.CallExpr{} + *chanDeclCopy = *chanDecl + chanDeclCopy.Args = append([]ast.Expr(nil), chanDecl.Args...) + chanDeclCopy.Args = append(chanDeclCopy.Args, &ast.BasicLit{ + Kind: token.INT, + Value: "1", + }) + + var buf bytes.Buffer + if err := format.Node(&buf, token.NewFileSet(), chanDeclCopy); err != nil { + return + } + pass.Report(analysis.Diagnostic{ + Pos: call.Pos(), + End: call.End(), + Message: "misuse of unbuffered os.Signal channel as argument to signal.Notify", + SuggestedFixes: []analysis.SuggestedFix{{ + Message: "Change to buffer channel", + TextEdits: []analysis.TextEdit{{ + Pos: chanDecl.Pos(), + End: chanDecl.End(), + NewText: buf.Bytes(), + }}, + }}, + }) + }) + return nil, nil +} + +func isSignalNotify(info *types.Info, call *ast.CallExpr) bool { + check := func(id *ast.Ident) bool { + obj := info.ObjectOf(id) + return obj.Name() == "Notify" && obj.Pkg().Path() == "os/signal" + } + switch fun := call.Fun.(type) { + case *ast.SelectorExpr: + return check(fun.Sel) + case *ast.Ident: + if fun, ok := findDecl(fun).(*ast.SelectorExpr); ok { + return check(fun.Sel) + } + return false + default: + return false + } +} + +func findDecl(arg *ast.Ident) ast.Node { + if arg.Obj == nil { + return nil + } + switch as := arg.Obj.Decl.(type) { + case *ast.AssignStmt: + if len(as.Lhs) != len(as.Rhs) { + return nil + } + for i, lhs := range as.Lhs { + lid, ok := lhs.(*ast.Ident) + if !ok { + continue + } + if lid.Obj == arg.Obj { + return as.Rhs[i] + } + } + case *ast.ValueSpec: + if len(as.Names) != len(as.Values) { + return nil + } + for i, name := range as.Names { + if name.Obj == arg.Obj { + return as.Values[i] + } + } + } + return nil +} + +func isBuiltinMake(info *types.Info, call *ast.CallExpr) bool { + typVal := info.Types[call.Fun] + if !typVal.IsBuiltin() { + return false + } + switch fun := call.Fun.(type) { + case *ast.Ident: + return info.ObjectOf(fun).Name() == "make" + default: + return false + } +} diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/stdmethods/stdmethods.go b/libgo/go/golang.org/x/tools/go/analysis/passes/stdmethods/stdmethods.go index 856c6ae..64a28ac 100644 --- a/libgo/go/golang.org/x/tools/go/analysis/passes/stdmethods/stdmethods.go +++ b/libgo/go/golang.org/x/tools/go/analysis/passes/stdmethods/stdmethods.go @@ -61,10 +61,12 @@ var Analyzer = &analysis.Analyzer{ // we let it go. But if it does have a fmt.ScanState, then the // rest has to match. var canonicalMethods = map[string]struct{ args, results []string }{ + "As": {[]string{"interface{}"}, []string{"bool"}}, // errors.As // "Flush": {{}, {"error"}}, // http.Flusher and jpeg.writer conflict "Format": {[]string{"=fmt.State", "rune"}, []string{}}, // fmt.Formatter "GobDecode": {[]string{"[]byte"}, []string{"error"}}, // gob.GobDecoder "GobEncode": {[]string{}, []string{"[]byte", "error"}}, // gob.GobEncoder + "Is": {[]string{"error"}, []string{"bool"}}, // errors.Is "MarshalJSON": {[]string{}, []string{"[]byte", "error"}}, // json.Marshaler "MarshalXML": {[]string{"*xml.Encoder", "xml.StartElement"}, []string{"error"}}, // xml.Marshaler "ReadByte": {[]string{}, []string{"byte", "error"}}, // io.ByteReader @@ -76,6 +78,7 @@ var canonicalMethods = map[string]struct{ args, results []string }{ "UnmarshalXML": {[]string{"*xml.Decoder", "xml.StartElement"}, []string{"error"}}, // xml.Unmarshaler "UnreadByte": {[]string{}, []string{"error"}}, "UnreadRune": {[]string{}, []string{"error"}}, + "Unwrap": {[]string{}, []string{"error"}}, // errors.Unwrap "WriteByte": {[]string{"byte"}, []string{"error"}}, // jpeg.writer (matching bufio.Writer) "WriteTo": {[]string{"=io.Writer"}, []string{"int64", "error"}}, // io.WriterTo } @@ -123,6 +126,14 @@ func canonicalMethod(pass *analysis.Pass, id *ast.Ident) { return } + // Special case: Is, As and Unwrap only apply when type + // implements error. + if id.Name == "Is" || id.Name == "As" || id.Name == "Unwrap" { + if recv := sign.Recv(); recv == nil || !implementsError(recv.Type()) { + return + } + } + // Do the =s (if any) all match? if !matchParams(pass, expect.args, args, "=") || !matchParams(pass, expect.results, results, "=") { return @@ -185,3 +196,9 @@ func matchParamType(expect string, actual types.Type) bool { // Overkill but easy. return typeString(actual) == expect } + +var errorType = types.Universe.Lookup("error").Type().Underlying().(*types.Interface) + +func implementsError(actual types.Type) bool { + return types.Implements(actual, errorType) +} diff --git a/libgo/go/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go b/libgo/go/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go index 02ec2fa..3232821 100644 --- a/libgo/go/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go +++ b/libgo/go/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go @@ -97,7 +97,7 @@ func Main(analyzers ...*analysis.Analyzer) { Usage of %[1]s: %.16[1]s unit.cfg # execute analysis specified by config file - %.16[1]s help # general help + %.16[1]s help # general help, including listing analyzers and flags %.16[1]s help name # help on specific analyzer and its flags `, progname) os.Exit(1) diff --git a/libgo/go/golang.org/x/tools/go/analysis/unitchecker/unitchecker112.go b/libgo/go/golang.org/x/tools/go/analysis/unitchecker/unitchecker112.go index 9051456..3180f4a 100644 --- a/libgo/go/golang.org/x/tools/go/analysis/unitchecker/unitchecker112.go +++ b/libgo/go/golang.org/x/tools/go/analysis/unitchecker/unitchecker112.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build go1.12 // +build go1.12 package unitchecker diff --git a/libgo/go/hash/crc32/crc32_otherarch.go b/libgo/go/hash/crc32/crc32_otherarch.go index 86f9fd9..07e257a 100644 --- a/libgo/go/hash/crc32/crc32_otherarch.go +++ b/libgo/go/hash/crc32/crc32_otherarch.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//-go:build !amd64 && !s390x && !ppc64le && !arm64 // -build !amd64,!s390x,!ppc64le,!arm64 package crc32 diff --git a/libgo/go/hash/crc32/gen_const_ppc64le.go b/libgo/go/hash/crc32/gen_const_ppc64le.go index d7af018..c98454c 100644 --- a/libgo/go/hash/crc32/gen_const_ppc64le.go +++ b/libgo/go/hash/crc32/gen_const_ppc64le.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // Generate the constant table associated with the poly used by the diff --git a/libgo/go/hash/maphash/maphash.go b/libgo/go/hash/maphash/maphash.go index ecc147d..d022d74 100644 --- a/libgo/go/hash/maphash/maphash.go +++ b/libgo/go/hash/maphash/maphash.go @@ -13,7 +13,10 @@ // package maphash -import "unsafe" +import ( + "internal/unsafeheader" + "unsafe" +) // A Seed is a random value that selects the specific hash function // computed by a Hash. If two Hashes use the same Seeds, they @@ -34,7 +37,7 @@ type Seed struct { // // The zero Hash is a valid Hash ready to use. // A zero Hash chooses a random seed for itself during -// the first call to a Reset, Write, Seed, Sum64, or Seed method. +// the first call to a Reset, Write, Seed, or Sum64 method. // For control over the seed, use SetSeed. // // The computed hash values depend only on the initial seed and @@ -54,13 +57,19 @@ type Seed struct { // If multiple goroutines must compute the same seeded hash, // each can declare its own Hash and call SetSeed with a common Seed. type Hash struct { - _ [0]func() // not comparable - seed Seed // initial seed used for this hash - state Seed // current hash of all flushed bytes - buf [64]byte // unflushed byte buffer - n int // number of unflushed bytes + _ [0]func() // not comparable + seed Seed // initial seed used for this hash + state Seed // current hash of all flushed bytes + buf [bufSize]byte // unflushed byte buffer + n int // number of unflushed bytes } +// bufSize is the size of the Hash write buffer. +// The buffer ensures that writes depend only on the sequence of bytes, +// not the sequence of WriteByte/Write/WriteString calls, +// by always calling rthash with a full buffer (except for the tail). +const bufSize = 128 + // initSeed seeds the hash if necessary. // initSeed is called lazily before any operation that actually uses h.seed/h.state. // Note that this does not include Write/WriteByte/WriteString in the case @@ -68,7 +77,9 @@ type Hash struct { // which does call h.initSeed.) func (h *Hash) initSeed() { if h.seed.s == 0 { - h.setSeed(MakeSeed()) + seed := MakeSeed() + h.seed = seed + h.state = seed } } @@ -87,27 +98,58 @@ func (h *Hash) WriteByte(b byte) error { // It always writes all of b and never fails; the count and error result are for implementing io.Writer. func (h *Hash) Write(b []byte) (int, error) { size := len(b) - for h.n+len(b) > len(h.buf) { + // Deal with bytes left over in h.buf. + // h.n <= bufSize is always true. + // Checking it is ~free and it lets the compiler eliminate a bounds check. + if h.n > 0 && h.n <= bufSize { k := copy(h.buf[h.n:], b) - h.n = len(h.buf) + h.n += k + if h.n < bufSize { + // Copied the entirety of b to h.buf. + return size, nil + } b = b[k:] h.flush() + // No need to set h.n = 0 here; it happens just before exit. + } + // Process as many full buffers as possible, without copying, and calling initSeed only once. + if len(b) > bufSize { + h.initSeed() + for len(b) > bufSize { + h.state.s = rthash(&b[0], bufSize, h.state.s) + b = b[bufSize:] + } } - h.n += copy(h.buf[h.n:], b) + // Copy the tail. + copy(h.buf[:], b) + h.n = len(b) return size, nil } // WriteString adds the bytes of s to the sequence of bytes hashed by h. // It always writes all of s and never fails; the count and error result are for implementing io.StringWriter. func (h *Hash) WriteString(s string) (int, error) { + // WriteString mirrors Write. See Write for comments. size := len(s) - for h.n+len(s) > len(h.buf) { + if h.n > 0 && h.n <= bufSize { k := copy(h.buf[h.n:], s) - h.n = len(h.buf) + h.n += k + if h.n < bufSize { + return size, nil + } s = s[k:] h.flush() } - h.n += copy(h.buf[h.n:], s) + if len(s) > bufSize { + h.initSeed() + for len(s) > bufSize { + ptr := (*byte)((*unsafeheader.String)(unsafe.Pointer(&s)).Data) + h.state.s = rthash(ptr, bufSize, h.state.s) + s = s[bufSize:] + } + } + copy(h.buf[:], s) + h.n = len(s) return size, nil } @@ -123,17 +165,12 @@ func (h *Hash) Seed() Seed { // Two Hash objects with different seeds will very likely behave differently. // Any bytes added to h before this call will be discarded. func (h *Hash) SetSeed(seed Seed) { - h.setSeed(seed) - h.n = 0 -} - -// setSeed sets seed without discarding accumulated data. -func (h *Hash) setSeed(seed Seed) { if seed.s == 0 { panic("maphash: use of uninitialized Seed") } h.seed = seed h.state = seed + h.n = 0 } // Reset discards all bytes added to h. @@ -150,7 +187,7 @@ func (h *Hash) flush() { panic("maphash: flush of partially full buffer") } h.initSeed() - h.state.s = rthash(h.buf[:], h.state.s) + h.state.s = rthash(&h.buf[0], h.n, h.state.s) h.n = 0 } @@ -163,7 +200,7 @@ func (h *Hash) flush() { // by using bit masking, shifting, or modular arithmetic. func (h *Hash) Sum64() uint64 { h.initSeed() - return rthash(h.buf[:h.n], h.state.s) + return rthash(&h.buf[0], h.n, h.state.s) } // MakeSeed returns a new random seed. @@ -184,18 +221,18 @@ func MakeSeed() Seed { //go:linkname runtime_fastrand runtime.fastrand func runtime_fastrand() uint32 -func rthash(b []byte, seed uint64) uint64 { - if len(b) == 0 { +func rthash(ptr *byte, len int, seed uint64) uint64 { + if len == 0 { return seed } // The runtime hasher only works on uintptr. For 64-bit // architectures, we use the hasher directly. Otherwise, // we use two parallel hashers on the lower and upper 32 bits. if unsafe.Sizeof(uintptr(0)) == 8 { - return uint64(runtime_memhash(unsafe.Pointer(&b[0]), uintptr(seed), uintptr(len(b)))) + return uint64(runtime_memhash(unsafe.Pointer(ptr), uintptr(seed), uintptr(len))) } - lo := runtime_memhash(unsafe.Pointer(&b[0]), uintptr(seed), uintptr(len(b))) - hi := runtime_memhash(unsafe.Pointer(&b[0]), uintptr(seed>>32), uintptr(len(b))) + lo := runtime_memhash(unsafe.Pointer(ptr), uintptr(seed), uintptr(len)) + hi := runtime_memhash(unsafe.Pointer(ptr), uintptr(seed>>32), uintptr(len)) return uint64(hi)<<32 | uint64(lo) } diff --git a/libgo/go/hash/maphash/maphash_test.go b/libgo/go/hash/maphash/maphash_test.go index daf6eb4..78cdfc0 100644 --- a/libgo/go/hash/maphash/maphash_test.go +++ b/libgo/go/hash/maphash/maphash_test.go @@ -5,6 +5,7 @@ package maphash import ( + "bytes" "hash" "testing" ) @@ -34,19 +35,57 @@ func TestSeededHash(t *testing.T) { } func TestHashGrouping(t *testing.T) { - b := []byte("foo") - h1 := new(Hash) - h2 := new(Hash) - h2.SetSeed(h1.Seed()) - h1.Write(b) - for _, x := range b { - err := h2.WriteByte(x) + b := bytes.Repeat([]byte("foo"), 100) + hh := make([]*Hash, 7) + for i := range hh { + hh[i] = new(Hash) + } + for _, h := range hh[1:] { + h.SetSeed(hh[0].Seed()) + } + hh[0].Write(b) + hh[1].WriteString(string(b)) + + writeByte := func(h *Hash, b byte) { + err := h.WriteByte(b) if err != nil { t.Fatalf("WriteByte: %v", err) } } - if h1.Sum64() != h2.Sum64() { - t.Errorf("hash of \"foo\" and \"f\",\"o\",\"o\" not identical") + writeSingleByte := func(h *Hash, b byte) { + _, err := h.Write([]byte{b}) + if err != nil { + t.Fatalf("Write single byte: %v", err) + } + } + writeStringSingleByte := func(h *Hash, b byte) { + _, err := h.WriteString(string([]byte{b})) + if err != nil { + t.Fatalf("WriteString single byte: %v", err) + } + } + + for i, x := range b { + writeByte(hh[2], x) + writeSingleByte(hh[3], x) + if i == 0 { + writeByte(hh[4], x) + } else { + writeSingleByte(hh[4], x) + } + writeStringSingleByte(hh[5], x) + if i == 0 { + writeByte(hh[6], x) + } else { + writeStringSingleByte(hh[6], x) + } + } + + sum := hh[0].Sum64() + for i, h := range hh { + if sum != h.Sum64() { + t.Errorf("hash %d not identical to a single Write", i) + } } } diff --git a/libgo/go/html/fuzz.go b/libgo/go/html/fuzz.go index ffa3e25..ecaf4f9 100644 --- a/libgo/go/html/fuzz.go +++ b/libgo/go/html/fuzz.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gofuzz // +build gofuzz package html diff --git a/libgo/go/html/template/exec_test.go b/libgo/go/html/template/exec_test.go index 7d1bef1..8885873 100644 --- a/libgo/go/html/template/exec_test.go +++ b/libgo/go/html/template/exec_test.go @@ -1720,8 +1720,6 @@ var v = "v"; ` func TestEscapeRace(t *testing.T) { - t.Skip("this test currently fails with -race; see issue #39807") - tmpl := New("") _, err := tmpl.New("templ.html").Parse(raceText) if err != nil { diff --git a/libgo/go/image/color/palette/gen.go b/libgo/go/image/color/palette/gen.go index 3243e53..7bb257d 100644 --- a/libgo/go/image/color/palette/gen.go +++ b/libgo/go/image/color/palette/gen.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package main diff --git a/libgo/go/image/draw/draw.go b/libgo/go/image/draw/draw.go index 8f96aa2..13f6668 100644 --- a/libgo/go/image/draw/draw.go +++ b/libgo/go/image/draw/draw.go @@ -23,6 +23,16 @@ type Image interface { Set(x, y int, c color.Color) } +// RGBA64Image extends both the Image and image.RGBA64Image interfaces with a +// SetRGBA64 method to change a single pixel. SetRGBA64 is equivalent to +// calling Set, but it can avoid allocations from converting concrete color +// types to the color.Color interface type. +type RGBA64Image interface { + image.RGBA64Image + Set(x, y int, c color.Color) + SetRGBA64(x, y int, c color.RGBA64) +} + // Quantizer produces a palette for an image. type Quantizer interface { // Quantize appends up to cap(p) - len(p) colors to p and returns the diff --git a/libgo/go/image/geom.go b/libgo/go/image/geom.go index 78e9e49..e71aa61 100644 --- a/libgo/go/image/geom.go +++ b/libgo/go/image/geom.go @@ -246,6 +246,14 @@ func (r Rectangle) At(x, y int) color.Color { return color.Transparent } +// RGBA64At implements the RGBA64Image interface. +func (r Rectangle) RGBA64At(x, y int) color.RGBA64 { + if (Point{x, y}).In(r) { + return color.RGBA64{0xffff, 0xffff, 0xffff, 0xffff} + } + return color.RGBA64{} +} + // Bounds implements the Image interface. func (r Rectangle) Bounds() Rectangle { return r diff --git a/libgo/go/image/gif/reader.go b/libgo/go/image/gif/reader.go index e580ab0..9e8268c 100644 --- a/libgo/go/image/gif/reader.go +++ b/libgo/go/image/gif/reader.go @@ -116,7 +116,7 @@ type decoder struct { // consumed when checking that the blockReader is exhausted. // // To avoid the allocation of a bufio.Reader for the lzw Reader, blockReader -// implements io.ReadByte and buffers blocks into the decoder's "tmp" buffer. +// implements io.ByteReader and buffers blocks into the decoder's "tmp" buffer. type blockReader struct { d *decoder i, j uint8 // d.tmp[i:j] contains the buffered bytes diff --git a/libgo/go/image/image.go b/libgo/go/image/image.go index 8adba96..930d9ac 100644 --- a/libgo/go/image/image.go +++ b/libgo/go/image/image.go @@ -45,6 +45,17 @@ type Image interface { At(x, y int) color.Color } +// RGBA64Image is an Image whose pixels can be converted directly to a +// color.RGBA64. +type RGBA64Image interface { + // RGBA64At returns the RGBA64 color of the pixel at (x, y). It is + // equivalent to calling At(x, y).RGBA() and converting the resulting + // 32-bit return values to a color.RGBA64, but it can avoid allocations + // from converting concrete color types to the color.Color interface type. + RGBA64At(x, y int) color.RGBA64 + Image +} + // PalettedImage is an image whose colors may come from a limited palette. // If m is a PalettedImage and m.ColorModel() returns a color.Palette p, // then m.At(x, y) should be equivalent to p[m.ColorIndexAt(x, y)]. If m's @@ -90,6 +101,24 @@ func (p *RGBA) At(x, y int) color.Color { return p.RGBAAt(x, y) } +func (p *RGBA) RGBA64At(x, y int) color.RGBA64 { + if !(Point{x, y}.In(p.Rect)) { + return color.RGBA64{} + } + i := p.PixOffset(x, y) + s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 + r := uint16(s[0]) + g := uint16(s[1]) + b := uint16(s[2]) + a := uint16(s[3]) + return color.RGBA64{ + (r << 8) | r, + (g << 8) | g, + (b << 8) | b, + (a << 8) | a, + } +} + func (p *RGBA) RGBAAt(x, y int) color.RGBA { if !(Point{x, y}.In(p.Rect)) { return color.RGBA{} @@ -118,6 +147,18 @@ func (p *RGBA) Set(x, y int, c color.Color) { s[3] = c1.A } +func (p *RGBA) SetRGBA64(x, y int, c color.RGBA64) { + if !(Point{x, y}.In(p.Rect)) { + return + } + i := p.PixOffset(x, y) + s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 + s[0] = uint8(c.R >> 8) + s[1] = uint8(c.G >> 8) + s[2] = uint8(c.B >> 8) + s[3] = uint8(c.A >> 8) +} + func (p *RGBA) SetRGBA(x, y int, c color.RGBA) { if !(Point{x, y}.In(p.Rect)) { return @@ -311,6 +352,11 @@ func (p *NRGBA) At(x, y int) color.Color { return p.NRGBAAt(x, y) } +func (p *NRGBA) RGBA64At(x, y int) color.RGBA64 { + r, g, b, a := p.NRGBAAt(x, y).RGBA() + return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)} +} + func (p *NRGBA) NRGBAAt(x, y int) color.NRGBA { if !(Point{x, y}.In(p.Rect)) { return color.NRGBA{} @@ -339,6 +385,24 @@ func (p *NRGBA) Set(x, y int, c color.Color) { s[3] = c1.A } +func (p *NRGBA) SetRGBA64(x, y int, c color.RGBA64) { + if !(Point{x, y}.In(p.Rect)) { + return + } + r, g, b, a := uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A) + if (a != 0) && (a != 0xffff) { + r = (r * 0xffff) / a + g = (g * 0xffff) / a + b = (b * 0xffff) / a + } + i := p.PixOffset(x, y) + s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 + s[0] = uint8(r >> 8) + s[1] = uint8(g >> 8) + s[2] = uint8(b >> 8) + s[3] = uint8(a >> 8) +} + func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) { if !(Point{x, y}.In(p.Rect)) { return @@ -415,6 +479,11 @@ func (p *NRGBA64) At(x, y int) color.Color { return p.NRGBA64At(x, y) } +func (p *NRGBA64) RGBA64At(x, y int) color.RGBA64 { + r, g, b, a := p.NRGBA64At(x, y).RGBA() + return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)} +} + func (p *NRGBA64) NRGBA64At(x, y int) color.NRGBA64 { if !(Point{x, y}.In(p.Rect)) { return color.NRGBA64{} @@ -452,6 +521,28 @@ func (p *NRGBA64) Set(x, y int, c color.Color) { s[7] = uint8(c1.A) } +func (p *NRGBA64) SetRGBA64(x, y int, c color.RGBA64) { + if !(Point{x, y}.In(p.Rect)) { + return + } + r, g, b, a := uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A) + if (a != 0) && (a != 0xffff) { + r = (r * 0xffff) / a + g = (g * 0xffff) / a + b = (b * 0xffff) / a + } + i := p.PixOffset(x, y) + s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857 + s[0] = uint8(r >> 8) + s[1] = uint8(r) + s[2] = uint8(g >> 8) + s[3] = uint8(g) + s[4] = uint8(b >> 8) + s[5] = uint8(b) + s[6] = uint8(a >> 8) + s[7] = uint8(a) +} + func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) { if !(Point{x, y}.In(p.Rect)) { return @@ -532,6 +623,12 @@ func (p *Alpha) At(x, y int) color.Color { return p.AlphaAt(x, y) } +func (p *Alpha) RGBA64At(x, y int) color.RGBA64 { + a := uint16(p.AlphaAt(x, y).A) + a |= a << 8 + return color.RGBA64{a, a, a, a} +} + func (p *Alpha) AlphaAt(x, y int) color.Alpha { if !(Point{x, y}.In(p.Rect)) { return color.Alpha{} @@ -554,6 +651,14 @@ func (p *Alpha) Set(x, y int, c color.Color) { p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A } +func (p *Alpha) SetRGBA64(x, y int, c color.RGBA64) { + if !(Point{x, y}.In(p.Rect)) { + return + } + i := p.PixOffset(x, y) + p.Pix[i] = uint8(c.A >> 8) +} + func (p *Alpha) SetAlpha(x, y int, c color.Alpha) { if !(Point{x, y}.In(p.Rect)) { return @@ -626,6 +731,11 @@ func (p *Alpha16) At(x, y int) color.Color { return p.Alpha16At(x, y) } +func (p *Alpha16) RGBA64At(x, y int) color.RGBA64 { + a := p.Alpha16At(x, y).A + return color.RGBA64{a, a, a, a} +} + func (p *Alpha16) Alpha16At(x, y int) color.Alpha16 { if !(Point{x, y}.In(p.Rect)) { return color.Alpha16{} @@ -650,6 +760,15 @@ func (p *Alpha16) Set(x, y int, c color.Color) { p.Pix[i+1] = uint8(c1.A) } +func (p *Alpha16) SetRGBA64(x, y int, c color.RGBA64) { + if !(Point{x, y}.In(p.Rect)) { + return + } + i := p.PixOffset(x, y) + p.Pix[i+0] = uint8(c.A >> 8) + p.Pix[i+1] = uint8(c.A) +} + func (p *Alpha16) SetAlpha16(x, y int, c color.Alpha16) { if !(Point{x, y}.In(p.Rect)) { return @@ -723,6 +842,12 @@ func (p *Gray) At(x, y int) color.Color { return p.GrayAt(x, y) } +func (p *Gray) RGBA64At(x, y int) color.RGBA64 { + gray := uint16(p.GrayAt(x, y).Y) + gray |= gray << 8 + return color.RGBA64{gray, gray, gray, 0xffff} +} + func (p *Gray) GrayAt(x, y int) color.Gray { if !(Point{x, y}.In(p.Rect)) { return color.Gray{} @@ -745,6 +870,16 @@ func (p *Gray) Set(x, y int, c color.Color) { p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y } +func (p *Gray) SetRGBA64(x, y int, c color.RGBA64) { + if !(Point{x, y}.In(p.Rect)) { + return + } + // This formula is the same as in color.grayModel. + gray := (19595*uint32(c.R) + 38470*uint32(c.G) + 7471*uint32(c.B) + 1<<15) >> 24 + i := p.PixOffset(x, y) + p.Pix[i] = uint8(gray) +} + func (p *Gray) SetGray(x, y int, c color.Gray) { if !(Point{x, y}.In(p.Rect)) { return @@ -804,6 +939,11 @@ func (p *Gray16) At(x, y int) color.Color { return p.Gray16At(x, y) } +func (p *Gray16) RGBA64At(x, y int) color.RGBA64 { + gray := p.Gray16At(x, y).Y + return color.RGBA64{gray, gray, gray, 0xffff} +} + func (p *Gray16) Gray16At(x, y int) color.Gray16 { if !(Point{x, y}.In(p.Rect)) { return color.Gray16{} @@ -828,6 +968,17 @@ func (p *Gray16) Set(x, y int, c color.Color) { p.Pix[i+1] = uint8(c1.Y) } +func (p *Gray16) SetRGBA64(x, y int, c color.RGBA64) { + if !(Point{x, y}.In(p.Rect)) { + return + } + // This formula is the same as in color.gray16Model. + gray := (19595*uint32(c.R) + 38470*uint32(c.G) + 7471*uint32(c.B) + 1<<15) >> 16 + i := p.PixOffset(x, y) + p.Pix[i+0] = uint8(gray >> 8) + p.Pix[i+1] = uint8(gray) +} + func (p *Gray16) SetGray16(x, y int, c color.Gray16) { if !(Point{x, y}.In(p.Rect)) { return @@ -888,6 +1039,11 @@ func (p *CMYK) At(x, y int) color.Color { return p.CMYKAt(x, y) } +func (p *CMYK) RGBA64At(x, y int) color.RGBA64 { + r, g, b, a := p.CMYKAt(x, y).RGBA() + return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)} +} + func (p *CMYK) CMYKAt(x, y int) color.CMYK { if !(Point{x, y}.In(p.Rect)) { return color.CMYK{} @@ -916,6 +1072,19 @@ func (p *CMYK) Set(x, y int, c color.Color) { s[3] = c1.K } +func (p *CMYK) SetRGBA64(x, y int, c color.RGBA64) { + if !(Point{x, y}.In(p.Rect)) { + return + } + cc, mm, yy, kk := color.RGBToCMYK(uint8(c.R>>8), uint8(c.G>>8), uint8(c.B>>8)) + i := p.PixOffset(x, y) + s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857 + s[0] = cc + s[1] = mm + s[2] = yy + s[3] = kk +} + func (p *CMYK) SetCMYK(x, y int, c color.CMYK) { if !(Point{x, y}.In(p.Rect)) { return @@ -988,6 +1157,26 @@ func (p *Paletted) At(x, y int) color.Color { return p.Palette[p.Pix[i]] } +func (p *Paletted) RGBA64At(x, y int) color.RGBA64 { + if len(p.Palette) == 0 { + return color.RGBA64{} + } + c := color.Color(nil) + if !(Point{x, y}.In(p.Rect)) { + c = p.Palette[0] + } else { + i := p.PixOffset(x, y) + c = p.Palette[p.Pix[i]] + } + r, g, b, a := c.RGBA() + return color.RGBA64{ + uint16(r), + uint16(g), + uint16(b), + uint16(a), + } +} + // PixOffset returns the index of the first element of Pix that corresponds to // the pixel at (x, y). func (p *Paletted) PixOffset(x, y int) int { @@ -1002,6 +1191,14 @@ func (p *Paletted) Set(x, y int, c color.Color) { p.Pix[i] = uint8(p.Palette.Index(c)) } +func (p *Paletted) SetRGBA64(x, y int, c color.RGBA64) { + if !(Point{x, y}.In(p.Rect)) { + return + } + i := p.PixOffset(x, y) + p.Pix[i] = uint8(p.Palette.Index(c)) +} + func (p *Paletted) ColorIndexAt(x, y int) uint8 { if !(Point{x, y}.In(p.Rect)) { return 0 diff --git a/libgo/go/image/image_test.go b/libgo/go/image/image_test.go index b9b9bfa..7f41bcb 100644 --- a/libgo/go/image/image_test.go +++ b/libgo/go/image/image_test.go @@ -6,6 +6,7 @@ package image import ( "image/color" + "image/color/palette" "testing" ) @@ -191,6 +192,92 @@ func Test16BitsPerColorChannel(t *testing.T) { } } +func TestRGBA64Image(t *testing.T) { + // memset sets every element of s to v. + memset := func(s []byte, v byte) { + for i := range s { + s[i] = v + } + } + + r := Rect(0, 0, 3, 2) + testCases := []Image{ + NewAlpha(r), + NewAlpha16(r), + NewCMYK(r), + NewGray(r), + NewGray16(r), + NewNRGBA(r), + NewNRGBA64(r), + NewNYCbCrA(r, YCbCrSubsampleRatio444), + NewPaletted(r, palette.Plan9), + NewRGBA(r), + NewRGBA64(r), + NewUniform(color.RGBA64{}), + NewYCbCr(r, YCbCrSubsampleRatio444), + r, + } + for _, tc := range testCases { + switch tc := tc.(type) { + // Most of the concrete image types in the testCases implement the + // draw.RGBA64Image interface: they have a SetRGBA64 method. We use an + // interface literal here, instead of importing "image/draw", to avoid + // an import cycle. + // + // The YCbCr and NYCbCrA types are special-cased. Chroma subsampling + // means that setting one pixel can modify neighboring pixels. They + // don't have Set or SetRGBA64 methods because that side effect could + // be surprising. Here, we just memset the channel buffers instead. + // + // The Uniform and Rectangle types are also special-cased, as they + // don't have a Set or SetRGBA64 method. + case interface { + SetRGBA64(x, y int, c color.RGBA64) + }: + tc.SetRGBA64(1, 1, color.RGBA64{0x7FFF, 0x3FFF, 0x0000, 0x7FFF}) + + case *NYCbCrA: + memset(tc.YCbCr.Y, 0x77) + memset(tc.YCbCr.Cb, 0x88) + memset(tc.YCbCr.Cr, 0x99) + memset(tc.A, 0xAA) + + case *Uniform: + tc.C = color.RGBA64{0x7FFF, 0x3FFF, 0x0000, 0x7FFF} + + case *YCbCr: + memset(tc.Y, 0x77) + memset(tc.Cb, 0x88) + memset(tc.Cr, 0x99) + + case Rectangle: + // No-op. Rectangle pixels' colors are immutable. They're always + // color.Opaque. + + default: + t.Errorf("could not initialize pixels for %T", tc) + continue + } + + // Check that RGBA64At(x, y) is equivalent to At(x, y).RGBA(). + rgba64Image, ok := tc.(RGBA64Image) + if !ok { + t.Errorf("%T is not an RGBA64Image", tc) + continue + } + got := rgba64Image.RGBA64At(1, 1) + wantR, wantG, wantB, wantA := tc.At(1, 1).RGBA() + if (uint32(got.R) != wantR) || (uint32(got.G) != wantG) || + (uint32(got.B) != wantB) || (uint32(got.A) != wantA) { + t.Errorf("%T:\ngot (0x%04X, 0x%04X, 0x%04X, 0x%04X)\n"+ + "want (0x%04X, 0x%04X, 0x%04X, 0x%04X)", tc, + got.R, got.G, got.B, got.A, + wantR, wantG, wantB, wantA) + continue + } + } +} + func BenchmarkAt(b *testing.B) { for _, tc := range testImages { b.Run(tc.name, func(b *testing.B) { diff --git a/libgo/go/image/internal/imageutil/gen.go b/libgo/go/image/internal/imageutil/gen.go index 36de5dc..38f4130 100644 --- a/libgo/go/image/internal/imageutil/gen.go +++ b/libgo/go/image/internal/imageutil/gen.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package main diff --git a/libgo/go/image/jpeg/reader.go b/libgo/go/image/jpeg/reader.go index 4a4706f..b340723 100644 --- a/libgo/go/image/jpeg/reader.go +++ b/libgo/go/image/jpeg/reader.go @@ -14,9 +14,6 @@ import ( "io" ) -// TODO(nigeltao): fix up the doc comment style so that sentences start with -// the name of the type or function that they annotate. - // A FormatError reports that the input is not a valid JPEG. type FormatError string diff --git a/libgo/go/image/names.go b/libgo/go/image/names.go index 8595a35..17b0658 100644 --- a/libgo/go/image/names.go +++ b/libgo/go/image/names.go @@ -41,6 +41,11 @@ func (c *Uniform) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point func (c *Uniform) At(x, y int) color.Color { return c.C } +func (c *Uniform) RGBA64At(x, y int) color.RGBA64 { + r, g, b, a := c.C.RGBA() + return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)} +} + // Opaque scans the entire image and reports whether it is fully opaque. func (c *Uniform) Opaque() bool { _, _, _, a := c.C.RGBA() diff --git a/libgo/go/image/png/fuzz.go b/libgo/go/image/png/fuzz.go index d9cb392..6508533 100644 --- a/libgo/go/image/png/fuzz.go +++ b/libgo/go/image/png/fuzz.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gofuzz // +build gofuzz package png diff --git a/libgo/go/image/png/writer.go b/libgo/go/image/png/writer.go index 53adc16..cbcdb9e 100644 --- a/libgo/go/image/png/writer.go +++ b/libgo/go/image/png/writer.go @@ -51,6 +51,7 @@ type encoder struct { bw *bufio.Writer } +// CompressionLevel indicates the compression level. type CompressionLevel int const ( diff --git a/libgo/go/image/ycbcr.go b/libgo/go/image/ycbcr.go index fbdffe1..328b90d 100644 --- a/libgo/go/image/ycbcr.go +++ b/libgo/go/image/ycbcr.go @@ -71,6 +71,11 @@ func (p *YCbCr) At(x, y int) color.Color { return p.YCbCrAt(x, y) } +func (p *YCbCr) RGBA64At(x, y int) color.RGBA64 { + r, g, b, a := p.YCbCrAt(x, y).RGBA() + return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)} +} + func (p *YCbCr) YCbCrAt(x, y int) color.YCbCr { if !(Point{x, y}.In(p.Rect)) { return color.YCbCr{} @@ -210,6 +215,11 @@ func (p *NYCbCrA) At(x, y int) color.Color { return p.NYCbCrAAt(x, y) } +func (p *NYCbCrA) RGBA64At(x, y int) color.RGBA64 { + r, g, b, a := p.NYCbCrAAt(x, y).RGBA() + return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)} +} + func (p *NYCbCrA) NYCbCrAAt(x, y int) color.NYCbCrA { if !(Point{X: x, Y: y}.In(p.Rect)) { return color.NYCbCrA{} diff --git a/libgo/go/index/suffixarray/gen.go b/libgo/go/index/suffixarray/gen.go index 94184d7..3bc9b1e 100644 --- a/libgo/go/index/suffixarray/gen.go +++ b/libgo/go/index/suffixarray/gen.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // Gen generates sais2.go by duplicating functions in sais.go diff --git a/libgo/go/internal/buildcfg/cfg.go b/libgo/go/internal/buildcfg/cfg.go new file mode 100644 index 0000000..4bf418e --- /dev/null +++ b/libgo/go/internal/buildcfg/cfg.go @@ -0,0 +1,136 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package buildcfg provides access to the build configuration +// described by the current environment. It is for use by build tools +// such as cmd/go or cmd/compile and for setting up go/build's Default context. +// +// Note that it does NOT provide access to the build configuration used to +// build the currently-running binary. For that, use runtime.GOOS etc +// as well as internal/goexperiment. +package buildcfg + +import ( + "fmt" + "os" + "path/filepath" + "strings" +) + +var ( + defaultGOROOT = defaultGOROOTValue() + + GOROOT = envOr("GOROOT", defaultGOROOT) + GOARCH = envOr("GOARCH", defaultGOARCH) + GOOS = envOr("GOOS", defaultGOOS) + GO386 = envOr("GO386", defaultGO386) + GOARM = goarm() + GOMIPS = gomips() + GOMIPS64 = gomips64() + GOPPC64 = goppc64() + GOWASM = gowasm() + GO_LDSO = defaultGO_LDSO + Version = version +) + +// Error is one of the errors found (if any) in the build configuration. +var Error error + +// Check exits the program with a fatal error if Error is non-nil. +func Check() { + if Error != nil { + fmt.Fprintf(os.Stderr, "%s: %v\n", filepath.Base(os.Args[0]), Error) + os.Exit(2) + } +} + +func envOr(key, value string) string { + if x := os.Getenv(key); x != "" { + return x + } + return value +} + +func goarm() int { + def := defaultGOARM + if GOOS == "android" && GOARCH == "arm" { + // Android arm devices always support GOARM=7. + def = "7" + } + switch v := envOr("GOARM", def); v { + case "5": + return 5 + case "6": + return 6 + case "7": + return 7 + } + Error = fmt.Errorf("invalid GOARM: must be 5, 6, 7") + return int(def[0] - '0') +} + +func gomips() string { + switch v := envOr("GOMIPS", defaultGOMIPS); v { + case "hardfloat", "softfloat": + return v + } + Error = fmt.Errorf("invalid GOMIPS: must be hardfloat, softfloat") + return defaultGOMIPS +} + +func gomips64() string { + switch v := envOr("GOMIPS64", defaultGOMIPS64); v { + case "hardfloat", "softfloat": + return v + } + Error = fmt.Errorf("invalid GOMIPS64: must be hardfloat, softfloat") + return defaultGOMIPS64 +} + +func goppc64() int { + switch v := envOr("GOPPC64", defaultGOPPC64); v { + case "power8": + return 8 + case "power9": + return 9 + } + Error = fmt.Errorf("invalid GOPPC64: must be power8, power9") + return int(defaultGOPPC64[len("power")] - '0') +} + +type gowasmFeatures struct { + SignExt bool + SatConv bool +} + +func (f gowasmFeatures) String() string { + var flags []string + if f.SatConv { + flags = append(flags, "satconv") + } + if f.SignExt { + flags = append(flags, "signext") + } + return strings.Join(flags, ",") +} + +func gowasm() (f gowasmFeatures) { + for _, opt := range strings.Split(envOr("GOWASM", ""), ",") { + switch opt { + case "satconv": + f.SatConv = true + case "signext": + f.SignExt = true + case "": + // ignore + default: + Error = fmt.Errorf("invalid GOWASM: no such feature %q", opt) + } + } + return +} + +func Getgoextlinkenabled() string { + return envOr("GO_EXTLINK_ENABLED", defaultGO_EXTLINK_ENABLED) +} diff --git a/libgo/go/internal/buildcfg/exp.go b/libgo/go/internal/buildcfg/exp.go new file mode 100644 index 0000000..736c080 --- /dev/null +++ b/libgo/go/internal/buildcfg/exp.go @@ -0,0 +1,189 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package buildcfg + +import ( + "fmt" + "reflect" + "strings" + + "internal/goexperiment" +) + +// Experiment contains the toolchain experiments enabled for the +// current build. +// +// (This is not necessarily the set of experiments the compiler itself +// was built with.) +// +// experimentBaseline specifies the experiment flags that are enabled by +// default in the current toolchain. This is, in effect, the "control" +// configuration and any variation from this is an experiment. +var Experiment, experimentBaseline = func() (goexperiment.Flags, goexperiment.Flags) { + flags, baseline, err := ParseGOEXPERIMENT(GOOS, GOARCH, envOr("GOEXPERIMENT", defaultGOEXPERIMENT)) + if err != nil { + Error = err + } + return flags, baseline +}() + +const DefaultGOEXPERIMENT = defaultGOEXPERIMENT + +// FramePointerEnabled enables the use of platform conventions for +// saving frame pointers. +// +// This used to be an experiment, but now it's always enabled on +// platforms that support it. +// +// Note: must agree with runtime.framepointer_enabled. +var FramePointerEnabled = GOARCH == "amd64" || GOARCH == "arm64" + +// ParseGOEXPERIMENT parses a (GOOS, GOARCH, GOEXPERIMENT) +// configuration tuple and returns the enabled and baseline experiment +// flag sets. +// +// TODO(mdempsky): Move to internal/goexperiment. +func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment.Flags, err error) { + regabiSupported := false + + baseline = goexperiment.Flags{ + RegabiWrappers: regabiSupported, + RegabiG: regabiSupported, + RegabiReflect: regabiSupported, + RegabiDefer: regabiSupported, + RegabiArgs: regabiSupported, + } + + // Start with the statically enabled set of experiments. + flags = baseline + + // Pick up any changes to the baseline configuration from the + // GOEXPERIMENT environment. This can be set at make.bash time + // and overridden at build time. + if goexp != "" { + // Create a map of known experiment names. + names := make(map[string]func(bool)) + rv := reflect.ValueOf(&flags).Elem() + rt := rv.Type() + for i := 0; i < rt.NumField(); i++ { + field := rv.Field(i) + names[strings.ToLower(rt.Field(i).Name)] = field.SetBool + } + + // "regabi" is an alias for all working regabi + // subexperiments, and not an experiment itself. Doing + // this as an alias make both "regabi" and "noregabi" + // do the right thing. + names["regabi"] = func(v bool) { + flags.RegabiWrappers = v + flags.RegabiG = v + flags.RegabiReflect = v + flags.RegabiDefer = v + flags.RegabiArgs = v + } + + // Parse names. + for _, f := range strings.Split(goexp, ",") { + if f == "" { + continue + } + if f == "none" { + // GOEXPERIMENT=none disables all experiment flags. + // This is used by cmd/dist, which doesn't know how + // to build with any experiment flags. + flags = goexperiment.Flags{} + continue + } + val := true + if strings.HasPrefix(f, "no") { + f, val = f[2:], false + } + set, ok := names[f] + if !ok { + err = fmt.Errorf("unknown GOEXPERIMENT %s", f) + return + } + set(val) + } + } + + // regabi is only supported on amd64. + if goarch != "amd64" { + flags.RegabiWrappers = false + flags.RegabiG = false + flags.RegabiReflect = false + flags.RegabiDefer = false + flags.RegabiArgs = false + } + // Check regabi dependencies. + if flags.RegabiG && !flags.RegabiWrappers { + err = fmt.Errorf("GOEXPERIMENT regabig requires regabiwrappers") + } + if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiG && flags.RegabiReflect && flags.RegabiDefer) { + err = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabig,regabireflect,regabidefer") + } + return +} + +// expList returns the list of lower-cased experiment names for +// experiments that differ from base. base may be nil to indicate no +// experiments. If all is true, then include all experiment flags, +// regardless of base. +func expList(exp, base *goexperiment.Flags, all bool) []string { + var list []string + rv := reflect.ValueOf(exp).Elem() + var rBase reflect.Value + if base != nil { + rBase = reflect.ValueOf(base).Elem() + } + rt := rv.Type() + for i := 0; i < rt.NumField(); i++ { + name := strings.ToLower(rt.Field(i).Name) + val := rv.Field(i).Bool() + baseVal := false + if base != nil { + baseVal = rBase.Field(i).Bool() + } + if all || val != baseVal { + if val { + list = append(list, name) + } else { + list = append(list, "no"+name) + } + } + } + return list +} + +// GOEXPERIMENT is a comma-separated list of enabled or disabled +// experiments that differ from the baseline experiment configuration. +// GOEXPERIMENT is exactly what a user would set on the command line +// to get the set of enabled experiments. +func GOEXPERIMENT() string { + return strings.Join(expList(&Experiment, &experimentBaseline, false), ",") +} + +// EnabledExperiments returns a list of enabled experiments, as +// lower-cased experiment names. +func EnabledExperiments() []string { + return expList(&Experiment, nil, false) +} + +// AllExperiments returns a list of all experiment settings. +// Disabled experiments appear in the list prefixed by "no". +func AllExperiments() []string { + return expList(&Experiment, nil, true) +} + +// UpdateExperiments updates the Experiment global based on a new GOARCH value. +// This is only required for cmd/go, which can change GOARCH after +// program startup due to use of "go env -w". +func UpdateExperiments(goos, goarch, goexperiment string) { + var err error + Experiment, experimentBaseline, err = ParseGOEXPERIMENT(goos, goarch, goexperiment) + if err != nil { + Error = err + } +} diff --git a/libgo/go/internal/bytealg/bytealg.go b/libgo/go/internal/bytealg/bytealg.go index 58efb95..68de560 100644 --- a/libgo/go/internal/bytealg/bytealg.go +++ b/libgo/go/internal/bytealg/bytealg.go @@ -17,6 +17,8 @@ const ( offsetX86HasPOPCNT = unsafe.Offsetof(cpu.X86.HasPOPCNT) offsetS390xHasVX = unsafe.Offsetof(cpu.S390X.HasVX) + + offsetPPC64HasPOWER9 = unsafe.Offsetof(cpu.PPC64.IsPOWER9) ) // MaxLen is the maximum length of the string to be searched for (argument b) in Index. diff --git a/libgo/go/internal/bytealg/compare_generic.go b/libgo/go/internal/bytealg/compare_generic.go index a29e8e7..45e6a02 100644 --- a/libgo/go/internal/bytealg/compare_generic.go +++ b/libgo/go/internal/bytealg/compare_generic.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build ignore_for_gccgo -// +build !386,!amd64,!s390x,!arm,!arm64,!ppc64,!ppc64le,!mips,!mipsle,!wasm,!mips64,!mips64le +//go:build ignore +// +build ignore package bytealg diff --git a/libgo/go/internal/bytealg/compare_native.go b/libgo/go/internal/bytealg/compare_native.go index b189998..629e858 100644 --- a/libgo/go/internal/bytealg/compare_native.go +++ b/libgo/go/internal/bytealg/compare_native.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//-go:build 386 || amd64 || s390x || arm || arm64 || ppc64 || ppc64le || mips || mipsle || wasm || mips64 || mips64le // -build 386 amd64 s390x arm arm64 ppc64 ppc64le mips mipsle wasm mips64 mips64le package bytealg diff --git a/libgo/go/internal/bytealg/count_generic.go b/libgo/go/internal/bytealg/count_generic.go index 7e4510c..d0e1c3b 100644 --- a/libgo/go/internal/bytealg/count_generic.go +++ b/libgo/go/internal/bytealg/count_generic.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//-go:build !amd64 && !arm && !arm64 && !ppc64le && !ppc64 && !riscv64 && !s390x // -build !amd64,!arm,!arm64,!ppc64le,!ppc64,!riscv64,!s390x package bytealg diff --git a/libgo/go/internal/bytealg/count_native.go b/libgo/go/internal/bytealg/count_native.go index a0151a0..efb782f 100644 --- a/libgo/go/internal/bytealg/count_native.go +++ b/libgo/go/internal/bytealg/count_native.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build ignore_for_gccgo -// +build amd64 arm arm64 ppc64le ppc64 riscv64 s390x +//go:build ignore +// +build ignore package bytealg diff --git a/libgo/go/internal/bytealg/index_amd64.go b/libgo/go/internal/bytealg/index_amd64.go index dd6a6cf..7208118 100644 --- a/libgo/go/internal/bytealg/index_amd64.go +++ b/libgo/go/internal/bytealg/index_amd64.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore_for_gccgo // +build ignore_for_gccgo package bytealg diff --git a/libgo/go/internal/bytealg/index_generic.go b/libgo/go/internal/bytealg/index_generic.go index c595c23..a880eb3 100644 --- a/libgo/go/internal/bytealg/index_generic.go +++ b/libgo/go/internal/bytealg/index_generic.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build ignore_for_gccgo -// +build !amd64,!arm64,!s390x +//go:build ignore +// +build ignore package bytealg diff --git a/libgo/go/internal/bytealg/index_native.go b/libgo/go/internal/bytealg/index_native.go index 26f4769..7086940 100644 --- a/libgo/go/internal/bytealg/index_native.go +++ b/libgo/go/internal/bytealg/index_native.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// -build amd64 arm64 s390x +//-go:build amd64 || arm64 || s390x || ppc64le || ppc64 +// -build amd64 arm64 s390x ppc64le ppc64 package bytealg diff --git a/libgo/go/internal/bytealg/index_ppc64x.go b/libgo/go/internal/bytealg/index_ppc64x.go new file mode 100644 index 0000000..f8f8f50 --- /dev/null +++ b/libgo/go/internal/bytealg/index_ppc64x.go @@ -0,0 +1,27 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore_for_gccgo +// +build ignore_for_gccgo + +package bytealg + +import "internal/cpu" + +const MaxBruteForce = 16 + +var SupportsPower9 = cpu.PPC64.IsPOWER9 + +func init() { + MaxLen = 32 +} + +// Cutover reports the number of failures of IndexByte we should tolerate +// before switching over to Index. +// n is the number of bytes processed so far. +// See the bytes.Index implementation for details. +func Cutover(n int) int { + // 1 error per 8 characters, plus a few slop to start. + return (n + 16) / 8 +} diff --git a/libgo/go/internal/bytealg/indexbyte_generic.go b/libgo/go/internal/bytealg/indexbyte_generic.go index 46325dd..09a6615 100644 --- a/libgo/go/internal/bytealg/indexbyte_generic.go +++ b/libgo/go/internal/bytealg/indexbyte_generic.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build ignore_for_gccgo -// +build !386,!amd64,!s390x,!arm,!arm64,!ppc64,!ppc64le,!mips,!mipsle,!mips64,!mips64le,!riscv,!riscv64,!wasm +//go:build ignore +// +build ignore package bytealg diff --git a/libgo/go/internal/bytealg/indexbyte_native.go b/libgo/go/internal/bytealg/indexbyte_native.go index c427e66..2cc118c 100644 --- a/libgo/go/internal/bytealg/indexbyte_native.go +++ b/libgo/go/internal/bytealg/indexbyte_native.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// -build 386 amd64 s390x arm arm64 ppc64 ppc64le mips mipsle mips64 mips64le riscv riscv64 wasm +//-go:build 386 || amd64 || s390x || arm || arm64 || ppc64 || ppc64le || mips || mipsle || mips64 || mips64le || riscv64 || wasm +// -build 386 amd64 s390x arm arm64 ppc64 ppc64le mips mipsle mips64 mips64le riscv64 wasm package bytealg diff --git a/libgo/go/internal/cfg/cfg.go b/libgo/go/internal/cfg/cfg.go index 5530213..815994b 100644 --- a/libgo/go/internal/cfg/cfg.go +++ b/libgo/go/internal/cfg/cfg.go @@ -39,6 +39,7 @@ const KnownEnv = ` GOCACHE GOENV GOEXE + GOEXPERIMENT GOFLAGS GOGCCFLAGS GOHOSTARCH diff --git a/libgo/go/internal/cpu/cpu_arm64_android.go b/libgo/go/internal/cpu/cpu_arm64_android.go index 3c9e57c..ac6eee5 100644 --- a/libgo/go/internal/cpu/cpu_arm64_android.go +++ b/libgo/go/internal/cpu/cpu_arm64_android.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build arm64 // +build arm64 package cpu diff --git a/libgo/go/internal/cpu/cpu_arm64_darwin.go b/libgo/go/internal/cpu/cpu_arm64_darwin.go index e094b97..ce1b250 100644 --- a/libgo/go/internal/cpu/cpu_arm64_darwin.go +++ b/libgo/go/internal/cpu/cpu_arm64_darwin.go @@ -2,9 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build arm64 -// +build darwin -// +build !ios +//go:build arm64 && darwin && !ios +// +build arm64,darwin,!ios package cpu diff --git a/libgo/go/internal/cpu/cpu_arm64_freebsd.go b/libgo/go/internal/cpu/cpu_arm64_freebsd.go index 9de2005..8c48137 100644 --- a/libgo/go/internal/cpu/cpu_arm64_freebsd.go +++ b/libgo/go/internal/cpu/cpu_arm64_freebsd.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build arm64 // +build arm64 package cpu diff --git a/libgo/go/internal/cpu/cpu_arm64_hwcap.go b/libgo/go/internal/cpu/cpu_arm64_hwcap.go index fdaf43e..8ac04fd 100644 --- a/libgo/go/internal/cpu/cpu_arm64_hwcap.go +++ b/libgo/go/internal/cpu/cpu_arm64_hwcap.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build arm64 -// +build linux +//go:build arm64 && linux +// +build arm64,linux package cpu diff --git a/libgo/go/internal/cpu/cpu_arm64_linux.go b/libgo/go/internal/cpu/cpu_arm64_linux.go index 2f7411f..c3a3f9a 100644 --- a/libgo/go/internal/cpu/cpu_arm64_linux.go +++ b/libgo/go/internal/cpu/cpu_arm64_linux.go @@ -2,9 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build arm64 -// +build linux -// +build !android +//go:build arm64 && linux && !android +// +build arm64,linux,!android package cpu diff --git a/libgo/go/internal/cpu/cpu_arm64_other.go b/libgo/go/internal/cpu/cpu_arm64_other.go index f191db2..e8b5d529 100644 --- a/libgo/go/internal/cpu/cpu_arm64_other.go +++ b/libgo/go/internal/cpu/cpu_arm64_other.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build arm64 && !linux && !freebsd && !android && (!darwin || ios) // +build arm64 // +build !linux // +build !freebsd diff --git a/libgo/go/internal/cpu/cpu_mips64x.go b/libgo/go/internal/cpu/cpu_mips64x.go index 58fbd3d..c660403 100644 --- a/libgo/go/internal/cpu/cpu_mips64x.go +++ b/libgo/go/internal/cpu/cpu_mips64x.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build mips64 || mips64le // +build mips64 mips64le package cpu diff --git a/libgo/go/internal/cpu/cpu_no_name.go b/libgo/go/internal/cpu/cpu_no_name.go index f028a92..8e636d5 100644 --- a/libgo/go/internal/cpu/cpu_no_name.go +++ b/libgo/go/internal/cpu/cpu_no_name.go @@ -2,9 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !386 -// +build !amd64 -// +build !amd64p32 +//go:build !386 && !amd64 && !amd64p32 +// +build !386,!amd64,!amd64p32 package cpu diff --git a/libgo/go/internal/cpu/cpu_ppc64x.go b/libgo/go/internal/cpu/cpu_ppc64x.go index 0a48f6a..1c7c39f 100644 --- a/libgo/go/internal/cpu/cpu_ppc64x.go +++ b/libgo/go/internal/cpu/cpu_ppc64x.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ppc || ppc64 || ppc64le // +build ppc ppc64 ppc64le package cpu diff --git a/libgo/go/internal/cpu/cpu_ppc64x_aix.go b/libgo/go/internal/cpu/cpu_ppc64x_aix.go index e2422a6..c7e47b2 100644 --- a/libgo/go/internal/cpu/cpu_ppc64x_aix.go +++ b/libgo/go/internal/cpu/cpu_ppc64x_aix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ppc || ppc64 || ppc64le // +build ppc ppc64 ppc64le package cpu diff --git a/libgo/go/internal/cpu/cpu_ppc64x_linux.go b/libgo/go/internal/cpu/cpu_ppc64x_linux.go index 068a799..0c89f3b 100644 --- a/libgo/go/internal/cpu/cpu_ppc64x_linux.go +++ b/libgo/go/internal/cpu/cpu_ppc64x_linux.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ppc || ppc64 || ppc64le // +build ppc ppc64 ppc64le package cpu diff --git a/libgo/go/internal/cpu/cpu_x86.go b/libgo/go/internal/cpu/cpu_x86.go index 338d909..6182532 100644 --- a/libgo/go/internal/cpu/cpu_x86.go +++ b/libgo/go/internal/cpu/cpu_x86.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build 386 || amd64 || amd64p32 // +build 386 amd64 amd64p32 package cpu diff --git a/libgo/go/internal/cpu/cpu_x86_test.go b/libgo/go/internal/cpu/cpu_x86_test.go index 61db93b..e3e16cc 100644 --- a/libgo/go/internal/cpu/cpu_x86_test.go +++ b/libgo/go/internal/cpu/cpu_x86_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build 386 || amd64 // +build 386 amd64 package cpu_test diff --git a/libgo/go/internal/execabs/execabs_test.go b/libgo/go/internal/execabs/execabs_test.go index b714585..97a3f39 100644 --- a/libgo/go/internal/execabs/execabs_test.go +++ b/libgo/go/internal/execabs/execabs_test.go @@ -8,7 +8,6 @@ import ( "context" "fmt" "internal/testenv" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -42,8 +41,8 @@ func TestCommand(t *testing.T) { if runtime.GOOS == "windows" { executable += ".exe" } - if err := ioutil.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil { - t.Fatalf("ioutil.WriteFile failed: %s", err) + if err := os.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil { + t.Fatalf("os.WriteFile failed: %s", err) } cwd, err := os.Getwd() if err != nil { @@ -77,8 +76,8 @@ func TestLookPath(t *testing.T) { if runtime.GOOS == "windows" { executable += ".exe" } - if err := ioutil.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil { - t.Fatalf("ioutil.WriteFile failed: %s", err) + if err := os.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil { + t.Fatalf("os.WriteFile failed: %s", err) } cwd, err := os.Getwd() if err != nil { diff --git a/libgo/go/internal/goexperiment/exp_fieldtrack_off.go b/libgo/go/internal/goexperiment/exp_fieldtrack_off.go new file mode 100644 index 0000000..e5e1326 --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_fieldtrack_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.fieldtrack +// +build !goexperiment.fieldtrack + +package goexperiment + +const FieldTrack = false +const FieldTrackInt = 0 diff --git a/libgo/go/internal/goexperiment/exp_fieldtrack_on.go b/libgo/go/internal/goexperiment/exp_fieldtrack_on.go new file mode 100644 index 0000000..0d8c447 --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_fieldtrack_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.fieldtrack +// +build goexperiment.fieldtrack + +package goexperiment + +const FieldTrack = true +const FieldTrackInt = 1 diff --git a/libgo/go/internal/goexperiment/exp_preemptibleloops_off.go b/libgo/go/internal/goexperiment/exp_preemptibleloops_off.go new file mode 100644 index 0000000..7a26088 --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_preemptibleloops_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.preemptibleloops +// +build !goexperiment.preemptibleloops + +package goexperiment + +const PreemptibleLoops = false +const PreemptibleLoopsInt = 0 diff --git a/libgo/go/internal/goexperiment/exp_preemptibleloops_on.go b/libgo/go/internal/goexperiment/exp_preemptibleloops_on.go new file mode 100644 index 0000000..a9ca28c --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_preemptibleloops_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.preemptibleloops +// +build goexperiment.preemptibleloops + +package goexperiment + +const PreemptibleLoops = true +const PreemptibleLoopsInt = 1 diff --git a/libgo/go/internal/goexperiment/exp_regabi_off.go b/libgo/go/internal/goexperiment/exp_regabi_off.go new file mode 100644 index 0000000..5d88238 --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_regabi_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.regabi +// +build !goexperiment.regabi + +package goexperiment + +const Regabi = false +const RegabiInt = 0 diff --git a/libgo/go/internal/goexperiment/exp_regabi_on.go b/libgo/go/internal/goexperiment/exp_regabi_on.go new file mode 100644 index 0000000..c08d58e --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_regabi_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.regabi +// +build goexperiment.regabi + +package goexperiment + +const Regabi = true +const RegabiInt = 1 diff --git a/libgo/go/internal/goexperiment/exp_regabiargs_off.go b/libgo/go/internal/goexperiment/exp_regabiargs_off.go new file mode 100644 index 0000000..31a139b --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_regabiargs_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.regabiargs +// +build !goexperiment.regabiargs + +package goexperiment + +const RegabiArgs = false +const RegabiArgsInt = 0 diff --git a/libgo/go/internal/goexperiment/exp_regabiargs_on.go b/libgo/go/internal/goexperiment/exp_regabiargs_on.go new file mode 100644 index 0000000..9b26f3c --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_regabiargs_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.regabiargs +// +build goexperiment.regabiargs + +package goexperiment + +const RegabiArgs = true +const RegabiArgsInt = 1 diff --git a/libgo/go/internal/goexperiment/exp_regabidefer_off.go b/libgo/go/internal/goexperiment/exp_regabidefer_off.go new file mode 100644 index 0000000..b47c0c2 --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_regabidefer_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.regabidefer +// +build !goexperiment.regabidefer + +package goexperiment + +const RegabiDefer = false +const RegabiDeferInt = 0 diff --git a/libgo/go/internal/goexperiment/exp_regabidefer_on.go b/libgo/go/internal/goexperiment/exp_regabidefer_on.go new file mode 100644 index 0000000..bbf2f6c --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_regabidefer_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.regabidefer +// +build goexperiment.regabidefer + +package goexperiment + +const RegabiDefer = true +const RegabiDeferInt = 1 diff --git a/libgo/go/internal/goexperiment/exp_regabig_off.go b/libgo/go/internal/goexperiment/exp_regabig_off.go new file mode 100644 index 0000000..1b37d45 --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_regabig_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.regabig +// +build !goexperiment.regabig + +package goexperiment + +const RegabiG = false +const RegabiGInt = 0 diff --git a/libgo/go/internal/goexperiment/exp_regabig_on.go b/libgo/go/internal/goexperiment/exp_regabig_on.go new file mode 100644 index 0000000..7e5b162 --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_regabig_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.regabig +// +build goexperiment.regabig + +package goexperiment + +const RegabiG = true +const RegabiGInt = 1 diff --git a/libgo/go/internal/goexperiment/exp_regabireflect_off.go b/libgo/go/internal/goexperiment/exp_regabireflect_off.go new file mode 100644 index 0000000..515f4a5 --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_regabireflect_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.regabireflect +// +build !goexperiment.regabireflect + +package goexperiment + +const RegabiReflect = false +const RegabiReflectInt = 0 diff --git a/libgo/go/internal/goexperiment/exp_regabireflect_on.go b/libgo/go/internal/goexperiment/exp_regabireflect_on.go new file mode 100644 index 0000000..e8a3e9c --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_regabireflect_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.regabireflect +// +build goexperiment.regabireflect + +package goexperiment + +const RegabiReflect = true +const RegabiReflectInt = 1 diff --git a/libgo/go/internal/goexperiment/exp_regabiwrappers_off.go b/libgo/go/internal/goexperiment/exp_regabiwrappers_off.go new file mode 100644 index 0000000..bfa0fa3 --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_regabiwrappers_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.regabiwrappers +// +build !goexperiment.regabiwrappers + +package goexperiment + +const RegabiWrappers = false +const RegabiWrappersInt = 0 diff --git a/libgo/go/internal/goexperiment/exp_regabiwrappers_on.go b/libgo/go/internal/goexperiment/exp_regabiwrappers_on.go new file mode 100644 index 0000000..11ffffb --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_regabiwrappers_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.regabiwrappers +// +build goexperiment.regabiwrappers + +package goexperiment + +const RegabiWrappers = true +const RegabiWrappersInt = 1 diff --git a/libgo/go/internal/goexperiment/exp_staticlockranking_off.go b/libgo/go/internal/goexperiment/exp_staticlockranking_off.go new file mode 100644 index 0000000..3d546c0 --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_staticlockranking_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.staticlockranking +// +build !goexperiment.staticlockranking + +package goexperiment + +const StaticLockRanking = false +const StaticLockRankingInt = 0 diff --git a/libgo/go/internal/goexperiment/exp_staticlockranking_on.go b/libgo/go/internal/goexperiment/exp_staticlockranking_on.go new file mode 100644 index 0000000..78188fb --- /dev/null +++ b/libgo/go/internal/goexperiment/exp_staticlockranking_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.staticlockranking +// +build goexperiment.staticlockranking + +package goexperiment + +const StaticLockRanking = true +const StaticLockRankingInt = 1 diff --git a/libgo/go/internal/goexperiment/flags.go b/libgo/go/internal/goexperiment/flags.go new file mode 100644 index 0000000..cd4c178 --- /dev/null +++ b/libgo/go/internal/goexperiment/flags.go @@ -0,0 +1,93 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package goexperiment implements support for toolchain experiments. +// +// Toolchain experiments are controlled by the GOEXPERIMENT +// environment variable. GOEXPERIMENT is a comma-separated list of +// experiment names. GOEXPERIMENT can be set at make.bash time, which +// sets the default experiments for binaries built with the tool +// chain; or it can be set at build time. GOEXPERIMENT can also be set +// to "none", which disables any experiments that were enabled at +// make.bash time. +// +// Experiments are exposed to the build in the following ways: +// +// - Build tag goexperiment.x is set if experiment x (lower case) is +// enabled. +// +// - For each experiment x (in camel case), this package contains a +// boolean constant x and an integer constant xInt. +// +// - In runtime assembly, the macro GOEXPERIMENT_x is defined if +// experiment x (lower case) is enabled. +// +// In the toolchain, the set of experiments enabled for the current +// build should be accessed via objabi.Experiment. +// +// The set of experiments is included in the output of runtime.Version() +// and "go version <binary>" if it differs from the default experiments. +// +// For the set of experiments supported by the current toolchain, see +// "go doc goexperiment.Flags". +// +// Note that this package defines the set of experiments (in Flags) +// and records the experiments that were enabled when the package +// was compiled (as boolean and integer constants). +// +// Note especially that this package does not itself change behavior +// at run time based on the GOEXPERIMENT variable. +// The code used in builds to interpret the GOEXPERIMENT variable +// is in the separate package internal/buildcfg. +package goexperiment + +//go:generate go run mkconsts.go + +// Flags is the set of experiments that can be enabled or disabled in +// the current toolchain. +// +// When specified in the GOEXPERIMENT environment variable or as build +// tags, experiments use the strings.ToLower of their field name. +// +// For the baseline experimental configuration, see +// objabi.experimentBaseline. +// +// If you change this struct definition, run "go generate". +type Flags struct { + FieldTrack bool + PreemptibleLoops bool + StaticLockRanking bool + + // Regabi is split into several sub-experiments that can be + // enabled individually. Not all combinations work. + // The "regabi" GOEXPERIMENT is an alias for all "working" + // subexperiments. + + // RegabiWrappers enables ABI wrappers for calling between + // ABI0 and ABIInternal functions. Without this, the ABIs are + // assumed to be identical so cross-ABI calls are direct. + RegabiWrappers bool + // RegabiG enables dedicated G and zero registers in + // ABIInternal. + // + // Requires wrappers because it makes the ABIs incompatible. + RegabiG bool + // RegabiReflect enables the register-passing paths in + // reflection calls. This is also gated by intArgRegs in + // reflect and runtime (which are disabled by default) so it + // can be used in targeted tests. + RegabiReflect bool + // RegabiDefer enables desugaring defer and go calls + // into argument-less closures. + RegabiDefer bool + // RegabiArgs enables register arguments/results in all + // compiled Go functions. + // + // Requires wrappers (to do ABI translation), g (because + // runtime assembly that's been ported to ABIInternal uses the + // G register), reflect (so reflection calls use registers), + // and defer (because the runtime doesn't support passing + // register arguments to defer/go). + RegabiArgs bool +} diff --git a/libgo/go/internal/goexperiment/mkconsts.go b/libgo/go/internal/goexperiment/mkconsts.go new file mode 100644 index 0000000..204ca9d --- /dev/null +++ b/libgo/go/internal/goexperiment/mkconsts.go @@ -0,0 +1,74 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore +// +build ignore + +// mkconsts generates const definition files for each GOEXPERIMENT. +package main + +import ( + "bytes" + "fmt" + "internal/goexperiment" + "log" + "os" + "reflect" + "strings" +) + +func main() { + // Delete existing experiment constant files. + ents, err := os.ReadDir(".") + if err != nil { + log.Fatal(err) + } + for _, ent := range ents { + name := ent.Name() + if !strings.HasPrefix(name, "exp_") { + continue + } + // Check that this is definitely a generated file. + data, err := os.ReadFile(name) + if err != nil { + log.Fatalf("reading %s: %v", name, err) + } + if !bytes.Contains(data, []byte("Code generated by mkconsts")) { + log.Fatalf("%s: expected generated file", name) + } + if err := os.Remove(name); err != nil { + log.Fatal(err) + } + } + + // Generate new experiment constant files. + rt := reflect.TypeOf(&goexperiment.Flags{}).Elem() + for i := 0; i < rt.NumField(); i++ { + f := rt.Field(i).Name + buildTag := "goexperiment." + strings.ToLower(f) + for _, val := range []bool{false, true} { + name := fmt.Sprintf("exp_%s_%s.go", strings.ToLower(f), pick(val, "off", "on")) + data := fmt.Sprintf(`// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build %s%s +// +build %s%s + +package goexperiment + +const %s = %v +const %sInt = %s +`, pick(val, "!", ""), buildTag, pick(val, "!", ""), buildTag, f, val, f, pick(val, "0", "1")) + if err := os.WriteFile(name, []byte(data), 0666); err != nil { + log.Fatalf("writing %s: %v", name, err) + } + } + } +} + +func pick(v bool, f, t string) string { + if v { + return t + } + return f +} diff --git a/libgo/go/internal/goroot/gc.go b/libgo/go/internal/goroot/gc.go index ce72bc3..2338b78 100644 --- a/libgo/go/internal/goroot/gc.go +++ b/libgo/go/internal/goroot/gc.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gc // +build gc package goroot diff --git a/libgo/go/internal/goroot/gccgo.go b/libgo/go/internal/goroot/gccgo.go index 3530e59..b1041da 100644 --- a/libgo/go/internal/goroot/gccgo.go +++ b/libgo/go/internal/goroot/gccgo.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gccgo // +build gccgo package goroot diff --git a/libgo/go/internal/goversion/goversion.go b/libgo/go/internal/goversion/goversion.go index 513be45..4cc1568 100644 --- a/libgo/go/internal/goversion/goversion.go +++ b/libgo/go/internal/goversion/goversion.go @@ -9,4 +9,4 @@ package goversion // // It should be updated at the start of each development cycle to be // the version of the next Go 1.x release. See golang.org/issue/40705. -const Version = 16 +const Version = 17 diff --git a/libgo/go/internal/itoa/itoa.go b/libgo/go/internal/itoa/itoa.go new file mode 100644 index 0000000..c6062d9 --- /dev/null +++ b/libgo/go/internal/itoa/itoa.go @@ -0,0 +1,33 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Simple conversions to avoid depending on strconv. + +package itoa + +// Itoa converts val to a decimal string. +func Itoa(val int) string { + if val < 0 { + return "-" + Uitoa(uint(-val)) + } + return Uitoa(uint(val)) +} + +// Uitoa converts val to a decimal string. +func Uitoa(val uint) string { + if val == 0 { // avoid string allocation + return "0" + } + var buf [20]byte // big enough for 64bit value base 10 + i := len(buf) - 1 + for val >= 10 { + q := val / 10 + buf[i] = byte('0' + val - q*10) + i-- + val = q + } + // val < 10 + buf[i] = byte('0' + val) + return string(buf[i:]) +} diff --git a/libgo/go/internal/itoa/itoa_test.go b/libgo/go/internal/itoa/itoa_test.go new file mode 100644 index 0000000..71931c1 --- /dev/null +++ b/libgo/go/internal/itoa/itoa_test.go @@ -0,0 +1,40 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package itoa_test + +import ( + "fmt" + "internal/itoa" + "math" + "testing" +) + +var ( + minInt64 int64 = math.MinInt64 + maxInt64 int64 = math.MaxInt64 + maxUint64 uint64 = math.MaxUint64 +) + +func TestItoa(t *testing.T) { + tests := []int{int(minInt64), math.MinInt32, -999, -100, -1, 0, 1, 100, 999, math.MaxInt32, int(maxInt64)} + for _, tt := range tests { + got := itoa.Itoa(tt) + want := fmt.Sprint(tt) + if want != got { + t.Fatalf("Itoa(%d) = %s, want %s", tt, got, want) + } + } +} + +func TestUitoa(t *testing.T) { + tests := []uint{0, 1, 100, 999, math.MaxUint32, uint(maxUint64)} + for _, tt := range tests { + got := itoa.Uitoa(tt) + want := fmt.Sprint(tt) + if want != got { + t.Fatalf("Uitoa(%d) = %s, want %s", tt, got, want) + } + } +} diff --git a/libgo/go/internal/poll/copy_file_range_linux.go b/libgo/go/internal/poll/copy_file_range_linux.go index 01b242a..5b9e5d4 100644 --- a/libgo/go/internal/poll/copy_file_range_linux.go +++ b/libgo/go/internal/poll/copy_file_range_linux.go @@ -78,7 +78,7 @@ func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err // Go supports Linux >= 2.6.33, so the system call // may not be present. // - // If we see ENOSYS, we have certainly not transfered + // If we see ENOSYS, we have certainly not transferred // any data, so we can tell the caller that we // couldn't handle the transfer and let them fall // back to more generic code. @@ -91,13 +91,13 @@ func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err // Prior to Linux 5.3, it was not possible to // copy_file_range across file systems. Similarly to // the ENOSYS case above, if we see EXDEV, we have - // not transfered any data, and we can let the caller + // not transferred any data, and we can let the caller // fall back to generic code. // // As for EINVAL, that is what we see if, for example, // dst or src refer to a pipe rather than a regular // file. This is another case where no data has been - // transfered, so we consider it unhandled. + // transferred, so we consider it unhandled. // // If src and dst are on CIFS, we can see EIO. // See issue #42334. diff --git a/libgo/go/internal/poll/errno_unix.go b/libgo/go/internal/poll/errno_unix.go index 922230b..d03a2d2 100644 --- a/libgo/go/internal/poll/errno_unix.go +++ b/libgo/go/internal/poll/errno_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package poll diff --git a/libgo/go/internal/poll/errno_windows.go b/libgo/go/internal/poll/errno_windows.go index e3bddb4..c55f5f0 100644 --- a/libgo/go/internal/poll/errno_windows.go +++ b/libgo/go/internal/poll/errno_windows.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package poll diff --git a/libgo/go/internal/poll/error_stub_test.go b/libgo/go/internal/poll/error_stub_test.go index c40ffcd..bcc25dd 100644 --- a/libgo/go/internal/poll/error_stub_test.go +++ b/libgo/go/internal/poll/error_stub_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !linux // +build !linux package poll_test diff --git a/libgo/go/internal/poll/export_linux_test.go b/libgo/go/internal/poll/export_linux_test.go new file mode 100644 index 0000000..7fba793 --- /dev/null +++ b/libgo/go/internal/poll/export_linux_test.go @@ -0,0 +1,22 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Export guts for testing on linux. +// Since testing imports os and os imports internal/poll, +// the internal/poll tests can not be in package poll. + +package poll + +var ( + GetPipe = getPipe + PutPipe = putPipe + NewPipe = newPipe + DestroyPipe = destroyPipe +) + +func GetPipeFds(p *SplicePipe) (int, int) { + return p.rfd, p.wfd +} + +type SplicePipe = splicePipe diff --git a/libgo/go/internal/poll/export_posix_test.go b/libgo/go/internal/poll/export_posix_test.go index 8ab4fd6..1e714cd 100644 --- a/libgo/go/internal/poll/export_posix_test.go +++ b/libgo/go/internal/poll/export_posix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows // Export guts for testing on posix. diff --git a/libgo/go/internal/poll/export_test.go b/libgo/go/internal/poll/export_test.go index 02664d9..e1125cb 100644 --- a/libgo/go/internal/poll/export_test.go +++ b/libgo/go/internal/poll/export_test.go @@ -33,3 +33,5 @@ func (mu *FDMutex) RWLock(read bool) bool { func (mu *FDMutex) RWUnlock(read bool) bool { return mu.rwunlock(read) } + +var Fcntl = fcntl diff --git a/libgo/go/internal/poll/fcntl_js.go b/libgo/go/internal/poll/fcntl_js.go index 120fc11..7bf0ddc 100644 --- a/libgo/go/internal/poll/fcntl_js.go +++ b/libgo/go/internal/poll/fcntl_js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package poll diff --git a/libgo/go/internal/poll/fcntl_libc.go b/libgo/go/internal/poll/fcntl_libc.go index ed00f76..e9a98e3 100644 --- a/libgo/go/internal/poll/fcntl_libc.go +++ b/libgo/go/internal/poll/fcntl_libc.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || solaris // +build aix darwin solaris package poll diff --git a/libgo/go/internal/poll/fcntl_syscall.go b/libgo/go/internal/poll/fcntl_syscall.go index fb82b9b..cd0061f 100644 --- a/libgo/go/internal/poll/fcntl_syscall.go +++ b/libgo/go/internal/poll/fcntl_syscall.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build dragonfly || freebsd || hurd || linux || netbsd || openbsd // +build dragonfly freebsd hurd linux netbsd openbsd package poll diff --git a/libgo/go/internal/poll/fd.go b/libgo/go/internal/poll/fd.go index b72ea3d..69a9005 100644 --- a/libgo/go/internal/poll/fd.go +++ b/libgo/go/internal/poll/fd.go @@ -13,11 +13,22 @@ import ( "errors" ) -// ErrNetClosing is returned when a network descriptor is used after -// it has been closed. Keep this string consistent because of issue -// #4373: since historically programs have not been able to detect +// errNetClosing is the type of the variable ErrNetClosing. +// This is used to implement the net.Error interface. +type errNetClosing struct{} + +// Error returns the error message for ErrNetClosing. +// Keep this string consistent because of issue #4373: +// since historically programs have not been able to detect // this error, they look for the string. -var ErrNetClosing = errors.New("use of closed network connection") +func (e errNetClosing) Error() string { return "use of closed network connection" } + +func (e errNetClosing) Timeout() bool { return false } +func (e errNetClosing) Temporary() bool { return false } + +// ErrNetClosing is returned when a network descriptor is used after +// it has been closed. +var ErrNetClosing = errNetClosing{} // ErrFileClosing is returned when a file descriptor is used after it // has been closed. diff --git a/libgo/go/internal/poll/fd_fsync_posix.go b/libgo/go/internal/poll/fd_fsync_posix.go index 9be0f54..21f1de4 100644 --- a/libgo/go/internal/poll/fd_fsync_posix.go +++ b/libgo/go/internal/poll/fd_fsync_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package poll diff --git a/libgo/go/internal/poll/fd_io_plan9.go b/libgo/go/internal/poll/fd_io_plan9.go index 287d11b..3205ac8 100644 --- a/libgo/go/internal/poll/fd_io_plan9.go +++ b/libgo/go/internal/poll/fd_io_plan9.go @@ -5,6 +5,7 @@ package poll import ( + "internal/itoa" "runtime" "sync" "syscall" @@ -71,7 +72,7 @@ func (aio *asyncIO) Cancel() { if aio.pid == -1 { return } - f, e := syscall.Open("/proc/"+itoa(aio.pid)+"/note", syscall.O_WRONLY) + f, e := syscall.Open("/proc/"+itoa.Itoa(aio.pid)+"/note", syscall.O_WRONLY) if e != nil { return } diff --git a/libgo/go/internal/poll/fd_poll_js.go b/libgo/go/internal/poll/fd_poll_js.go index d6b28e5..760e248 100644 --- a/libgo/go/internal/poll/fd_poll_js.go +++ b/libgo/go/internal/poll/fd_poll_js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package poll diff --git a/libgo/go/internal/poll/fd_poll_runtime.go b/libgo/go/internal/poll/fd_poll_runtime.go index 55aa304..f40b845 100644 --- a/libgo/go/internal/poll/fd_poll_runtime.go +++ b/libgo/go/internal/poll/fd_poll_runtime.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || windows || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd windows solaris package poll @@ -38,10 +39,6 @@ func (pd *pollDesc) init(fd *FD) error { serverInit.Do(runtime_pollServerInit) ctx, errno := runtime_pollOpen(uintptr(fd.Sysfd)) if errno != 0 { - if ctx != 0 { - runtime_pollUnblock(ctx) - runtime_pollClose(ctx) - } return errnoErr(syscall.Errno(errno)) } pd.runtimeCtx = ctx diff --git a/libgo/go/internal/poll/fd_posix.go b/libgo/go/internal/poll/fd_posix.go index 16c2e50..fd64e53 100644 --- a/libgo/go/internal/poll/fd_posix.go +++ b/libgo/go/internal/poll/fd_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows package poll diff --git a/libgo/go/internal/poll/fd_posix_test.go b/libgo/go/internal/poll/fd_posix_test.go index dfcfd5c..1dc3f0f 100644 --- a/libgo/go/internal/poll/fd_posix_test.go +++ b/libgo/go/internal/poll/fd_posix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows package poll_test diff --git a/libgo/go/internal/poll/fd_unix.go b/libgo/go/internal/poll/fd_unix.go index 013b7e5..d8861de 100644 --- a/libgo/go/internal/poll/fd_unix.go +++ b/libgo/go/internal/poll/fd_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package poll @@ -230,7 +231,7 @@ func (fd *FD) ReadFrom(p []byte) (int, syscall.Sockaddr, error) { } // ReadMsg wraps the recvmsg network call. -func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, error) { +func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) { if err := fd.readLock(); err != nil { return 0, 0, 0, nil, err } @@ -239,7 +240,7 @@ func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, er return 0, 0, 0, nil, err } for { - n, oobn, flags, sa, err := syscall.Recvmsg(fd.Sysfd, p, oob, 0) + n, oobn, sysflags, sa, err := syscall.Recvmsg(fd.Sysfd, p, oob, flags) if err != nil { if err == syscall.EINTR { continue @@ -252,7 +253,7 @@ func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, er } } err = fd.eofError(n, err) - return n, oobn, flags, sa, err + return n, oobn, sysflags, sa, err } } diff --git a/libgo/go/internal/poll/fd_windows.go b/libgo/go/internal/poll/fd_windows.go index d8c834f..4a51695 100644 --- a/libgo/go/internal/poll/fd_windows.go +++ b/libgo/go/internal/poll/fd_windows.go @@ -1013,7 +1013,7 @@ func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) { } // ReadMsg wraps the WSARecvMsg network call. -func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, error) { +func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) { if err := fd.readLock(); err != nil { return 0, 0, 0, nil, err } @@ -1028,6 +1028,7 @@ func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, er o.rsa = new(syscall.RawSockaddrAny) o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa)) o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa)) + o.msg.Flags = uint32(flags) n, err := execIO(o, func(o *operation) error { return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil) }) diff --git a/libgo/go/internal/poll/fd_writev_darwin.go b/libgo/go/internal/poll/fd_writev_darwin.go index e202447..805fa2c 100644 --- a/libgo/go/internal/poll/fd_writev_darwin.go +++ b/libgo/go/internal/poll/fd_writev_darwin.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin // +build darwin package poll diff --git a/libgo/go/internal/poll/fd_writev_illumos.go b/libgo/go/internal/poll/fd_writev_illumos.go index 1fa47ab..a0b11ed 100644 --- a/libgo/go/internal/poll/fd_writev_illumos.go +++ b/libgo/go/internal/poll/fd_writev_illumos.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build illumos // +build illumos package poll diff --git a/libgo/go/internal/poll/fd_writev_unix.go b/libgo/go/internal/poll/fd_writev_unix.go index daeec96..87f284a 100644 --- a/libgo/go/internal/poll/fd_writev_unix.go +++ b/libgo/go/internal/poll/fd_writev_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build dragonfly || freebsd || linux || netbsd || openbsd // +build dragonfly freebsd linux netbsd openbsd package poll diff --git a/libgo/go/internal/poll/hook_cloexec.go b/libgo/go/internal/poll/hook_cloexec.go index b8ce58d..18b445a 100644 --- a/libgo/go/internal/poll/hook_cloexec.go +++ b/libgo/go/internal/poll/hook_cloexec.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build dragonfly || freebsd || hurd || illumos || linux || netbsd || openbsd // +build dragonfly freebsd hurd illumos linux netbsd openbsd package poll diff --git a/libgo/go/internal/poll/hook_unix.go b/libgo/go/internal/poll/hook_unix.go index 7bb6f88..5223fb7 100644 --- a/libgo/go/internal/poll/hook_unix.go +++ b/libgo/go/internal/poll/hook_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package poll diff --git a/libgo/go/internal/poll/iovec_illumos.go b/libgo/go/internal/poll/iovec_illumos.go index 0570674..f4058b2 100644 --- a/libgo/go/internal/poll/iovec_illumos.go +++ b/libgo/go/internal/poll/iovec_illumos.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build illumos // +build illumos package poll diff --git a/libgo/go/internal/poll/iovec_unix.go b/libgo/go/internal/poll/iovec_unix.go index 6f98947..6fd5d86 100644 --- a/libgo/go/internal/poll/iovec_unix.go +++ b/libgo/go/internal/poll/iovec_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd // +build darwin dragonfly freebsd linux netbsd openbsd package poll diff --git a/libgo/go/internal/poll/sendfile_bsd.go b/libgo/go/internal/poll/sendfile_bsd.go index 66005a9..3ba30a2 100644 --- a/libgo/go/internal/poll/sendfile_bsd.go +++ b/libgo/go/internal/poll/sendfile_bsd.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build dragonfly || freebsd // +build dragonfly freebsd package poll @@ -22,7 +23,7 @@ func SendFile(dstFD *FD, src int, pos, remain int64) (int64, error) { return 0, err } - dst := int(dstFD.Sysfd) + dst := dstFD.Sysfd var written int64 var err error for remain > 0 { diff --git a/libgo/go/internal/poll/sendfile_solaris.go b/libgo/go/internal/poll/sendfile_solaris.go index 748c851..0a88430 100644 --- a/libgo/go/internal/poll/sendfile_solaris.go +++ b/libgo/go/internal/poll/sendfile_solaris.go @@ -24,7 +24,7 @@ func SendFile(dstFD *FD, src int, pos, remain int64) (int64, error) { return 0, err } - dst := int(dstFD.Sysfd) + dst := dstFD.Sysfd var written int64 var err error for remain > 0 { diff --git a/libgo/go/internal/poll/sock_cloexec.go b/libgo/go/internal/poll/sock_cloexec.go index 09bc4b6..7daa11e 100644 --- a/libgo/go/internal/poll/sock_cloexec.go +++ b/libgo/go/internal/poll/sock_cloexec.go @@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// This file implements sysSocket and accept for platforms that -// provide a fast path for setting SetNonblock and CloseOnExec. +// This file implements accept for platforms that provide a fast path for +// setting SetNonblock and CloseOnExec. +//go:build dragonfly || freebsd || hurd || illumos || linux || netbsd || openbsd // +build dragonfly freebsd hurd illumos linux netbsd openbsd package poll diff --git a/libgo/go/internal/poll/sockopt.go b/libgo/go/internal/poll/sockopt.go index 2c6b68b..975f84b 100644 --- a/libgo/go/internal/poll/sockopt.go +++ b/libgo/go/internal/poll/sockopt.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows package poll diff --git a/libgo/go/internal/poll/sockopt_unix.go b/libgo/go/internal/poll/sockopt_unix.go index ef266d0..02a7859 100644 --- a/libgo/go/internal/poll/sockopt_unix.go +++ b/libgo/go/internal/poll/sockopt_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package poll diff --git a/libgo/go/internal/poll/sockoptip.go b/libgo/go/internal/poll/sockoptip.go index fc476bd..bcefa6b 100644 --- a/libgo/go/internal/poll/sockoptip.go +++ b/libgo/go/internal/poll/sockoptip.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows package poll diff --git a/libgo/go/internal/poll/splice_linux.go b/libgo/go/internal/poll/splice_linux.go index ca772e9..c7114f2 100644 --- a/libgo/go/internal/poll/splice_linux.go +++ b/libgo/go/internal/poll/splice_linux.go @@ -5,6 +5,8 @@ package poll import ( + "runtime" + "sync" "sync/atomic" "syscall" "unsafe" @@ -22,23 +24,23 @@ const ( // Splice transfers at most remain bytes of data from src to dst, using the // splice system call to minimize copies of data from and to userspace. // -// Splice creates a temporary pipe, to serve as a buffer for the data transfer. +// Splice gets a pipe buffer from the pool or creates a new one if needed, to serve as a buffer for the data transfer. // src and dst must both be stream-oriented sockets. // // If err != nil, sc is the system call which caused the error. func Splice(dst, src *FD, remain int64) (written int64, handled bool, sc string, err error) { - prfd, pwfd, sc, err := newTempPipe() + p, sc, err := getPipe() if err != nil { return 0, false, sc, err } - defer destroyTempPipe(prfd, pwfd) + defer putPipe(p) var inPipe, n int for err == nil && remain > 0 { max := maxSpliceSize if int64(max) > remain { max = int(remain) } - inPipe, err = spliceDrain(pwfd, src, max) + inPipe, err = spliceDrain(p.wfd, src, max) // The operation is considered handled if splice returns no // error, or an error other than EINVAL. An EINVAL means the // kernel does not support splice for the socket type of src. @@ -51,13 +53,16 @@ func Splice(dst, src *FD, remain int64) (written int64, handled bool, sc string, // If inPipe == 0 && err == nil, src is at EOF, and the // transfer is complete. handled = handled || (err != syscall.EINVAL) - if err != nil || (inPipe == 0 && err == nil) { + if err != nil || inPipe == 0 { break } - n, err = splicePump(dst, prfd, inPipe) + p.data += inPipe + + n, err = splicePump(dst, p.rfd, inPipe) if n > 0 { written += int64(n) remain -= int64(n) + p.data -= n } } if err != nil { @@ -148,13 +153,58 @@ func splice(out int, in int, max int, flags int) (int, error) { return int(n), err } +type splicePipe struct { + rfd int + wfd int + data int +} + +// splicePipePool caches pipes to avoid high-frequency construction and destruction of pipe buffers. +// The garbage collector will free all pipes in the sync.Pool periodically, thus we need to set up +// a finalizer for each pipe to close its file descriptors before the actual GC. +var splicePipePool = sync.Pool{New: newPoolPipe} + +func newPoolPipe() interface{} { + // Discard the error which occurred during the creation of pipe buffer, + // redirecting the data transmission to the conventional way utilizing read() + write() as a fallback. + p := newPipe() + if p == nil { + return nil + } + runtime.SetFinalizer(p, destroyPipe) + return p +} + +// getPipe tries to acquire a pipe buffer from the pool or create a new one with newPipe() if it gets nil from the cache. +// +// Note that it may fail to create a new pipe buffer by newPipe(), in which case getPipe() will return a generic error +// and system call name splice in a string as the indication. +func getPipe() (*splicePipe, string, error) { + v := splicePipePool.Get() + if v == nil { + return nil, "splice", syscall.EINVAL + } + return v.(*splicePipe), "", nil +} + +func putPipe(p *splicePipe) { + // If there is still data left in the pipe, + // then close and discard it instead of putting it back into the pool. + if p.data != 0 { + runtime.SetFinalizer(p, nil) + destroyPipe(p) + return + } + splicePipePool.Put(p) +} + var disableSplice unsafe.Pointer -// newTempPipe sets up a temporary pipe for a splice operation. -func newTempPipe() (prfd, pwfd int, sc string, err error) { +// newPipe sets up a pipe for a splice operation. +func newPipe() (sp *splicePipe) { p := (*bool)(atomic.LoadPointer(&disableSplice)) if p != nil && *p { - return -1, -1, "splice", syscall.EINVAL + return nil } var fds [2]int @@ -164,9 +214,11 @@ func newTempPipe() (prfd, pwfd int, sc string, err error) { // closed. const flags = syscall.O_CLOEXEC | syscall.O_NONBLOCK if err := syscall.Pipe2(fds[:], flags); err != nil { - return -1, -1, "pipe2", err + return nil } + sp = &splicePipe{rfd: fds[0], wfd: fds[1]} + if p == nil { p = new(bool) defer atomic.StorePointer(&disableSplice, unsafe.Pointer(p)) @@ -174,25 +226,21 @@ func newTempPipe() (prfd, pwfd int, sc string, err error) { // F_GETPIPE_SZ was added in 2.6.35, which does not have the -EAGAIN bug. if syscall.F_GETPIPE_SZ == 0 { *p = true - destroyTempPipe(fds[0], fds[1]) - return -1, -1, "fcntl", syscall.EINVAL + destroyPipe(sp) + return nil } if _, err := fcntl(fds[0], syscall.F_GETPIPE_SZ, 0); err != nil { *p = true - destroyTempPipe(fds[0], fds[1]) - return -1, -1, "fcntl", err + destroyPipe(sp) + return nil } } - return fds[0], fds[1], "", nil + return } -// destroyTempPipe destroys a temporary pipe. -func destroyTempPipe(prfd, pwfd int) error { - err := CloseFunc(prfd) - err1 := CloseFunc(pwfd) - if err == nil { - return err1 - } - return err +// destroyPipe destroys a pipe. +func destroyPipe(p *splicePipe) { + CloseFunc(p.rfd) + CloseFunc(p.wfd) } diff --git a/libgo/go/internal/poll/splice_linux_test.go b/libgo/go/internal/poll/splice_linux_test.go new file mode 100644 index 0000000..206a027 --- /dev/null +++ b/libgo/go/internal/poll/splice_linux_test.go @@ -0,0 +1,122 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package poll_test + +import ( + "internal/poll" + "runtime" + "syscall" + "testing" + "time" +) + +// checkPipes returns true if all pipes are closed properly, false otherwise. +func checkPipes(fds []int) bool { + for _, fd := range fds { + // Check if each pipe fd has been closed. + _, err := poll.Fcntl(fd, syscall.F_GETPIPE_SZ, 0) + if err == nil { + return false + } + } + return true +} + +func TestSplicePipePool(t *testing.T) { + if runtime.Compiler == "gccgo" { + t.Skip("gofrontend conservative stack collection causes this test to fail") + } + + const N = 64 + var ( + p *poll.SplicePipe + ps []*poll.SplicePipe + fds []int + err error + ) + for i := 0; i < N; i++ { + p, _, err = poll.GetPipe() + if err != nil { + t.Skip("failed to create pipe, skip this test") + } + _, pwfd := poll.GetPipeFds(p) + fds = append(fds, pwfd) + ps = append(ps, p) + } + for _, p = range ps { + poll.PutPipe(p) + } + ps = nil + p = nil + + // Exploit the timeout of "go test" as a timer for the subsequent verification. + timeout := 5 * time.Minute + if deadline, ok := t.Deadline(); ok { + timeout = deadline.Sub(time.Now()) + timeout -= timeout / 10 // Leave 10% headroom for cleanup. + } + expiredTime := time.NewTimer(timeout) + defer expiredTime.Stop() + + // Trigger garbage collection repeatedly, waiting for all pipes in sync.Pool + // to either be deallocated and closed, or to time out. + for { + runtime.GC() + time.Sleep(10 * time.Millisecond) + if checkPipes(fds) { + break + } + select { + case <-expiredTime.C: + t.Fatal("at least one pipe is still open") + default: + } + } +} + +func BenchmarkSplicePipe(b *testing.B) { + b.Run("SplicePipeWithPool", func(b *testing.B) { + for i := 0; i < b.N; i++ { + p, _, err := poll.GetPipe() + if err != nil { + continue + } + poll.PutPipe(p) + } + }) + b.Run("SplicePipeWithoutPool", func(b *testing.B) { + for i := 0; i < b.N; i++ { + p := poll.NewPipe() + if p == nil { + b.Skip("newPipe returned nil") + } + poll.DestroyPipe(p) + } + }) +} + +func BenchmarkSplicePipePoolParallel(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + p, _, err := poll.GetPipe() + if err != nil { + continue + } + poll.PutPipe(p) + } + }) +} + +func BenchmarkSplicePipeNativeParallel(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + p := poll.NewPipe() + if p == nil { + b.Skip("newPipe returned nil") + } + poll.DestroyPipe(p) + } + }) +} diff --git a/libgo/go/internal/poll/strconv.go b/libgo/go/internal/poll/strconv.go index 21cb40d..c98332d 100644 --- a/libgo/go/internal/poll/strconv.go +++ b/libgo/go/internal/poll/strconv.go @@ -2,38 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build plan9 // +build plan9 -// Simple conversions to avoid depending on strconv. - package poll -// Convert integer to decimal string -func itoa(val int) string { - if val < 0 { - return "-" + uitoa(uint(-val)) - } - return uitoa(uint(val)) -} - -// Convert unsigned integer to decimal string -func uitoa(val uint) string { - if val == 0 { // avoid string allocation - return "0" - } - var buf [20]byte // big enough for 64bit value base 10 - i := len(buf) - 1 - for val >= 10 { - q := val / 10 - buf[i] = byte('0' + val - q*10) - i-- - val = q - } - // val < 10 - buf[i] = byte('0' + val) - return string(buf[i:]) -} - // stringsHasSuffix is strings.HasSuffix. It reports whether s ends in // suffix. func stringsHasSuffix(s, suffix string) bool { diff --git a/libgo/go/internal/poll/sys_cloexec.go b/libgo/go/internal/poll/sys_cloexec.go index 4b3c642..7e6d422 100644 --- a/libgo/go/internal/poll/sys_cloexec.go +++ b/libgo/go/internal/poll/sys_cloexec.go @@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// This file implements sysSocket and accept for platforms that do not -// provide a fast path for setting SetNonblock and CloseOnExec. +// This file implements accept for platforms that do not provide a fast path for +// setting SetNonblock and CloseOnExec. +//go:build aix || darwin || (js && wasm) || (solaris && !illumos) // +build aix darwin js,wasm solaris,!illumos package poll diff --git a/libgo/go/internal/poll/writev.go b/libgo/go/internal/poll/writev.go index 0123fc3..824de75 100644 --- a/libgo/go/internal/poll/writev.go +++ b/libgo/go/internal/poll/writev.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || illumos || linux || netbsd || openbsd // +build darwin dragonfly freebsd illumos linux netbsd openbsd package poll diff --git a/libgo/go/internal/race/norace.go b/libgo/go/internal/race/norace.go index d83c016..67b1305 100644 --- a/libgo/go/internal/race/norace.go +++ b/libgo/go/internal/race/norace.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !race // +build !race package race diff --git a/libgo/go/internal/race/race.go b/libgo/go/internal/race/race.go index 2e7d97b..40f2c99 100644 --- a/libgo/go/internal/race/race.go +++ b/libgo/go/internal/race/race.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build race // +build race package race diff --git a/libgo/go/internal/reflectlite/all_test.go b/libgo/go/internal/reflectlite/all_test.go index 2ea28e0..e15f364 100644 --- a/libgo/go/internal/reflectlite/all_test.go +++ b/libgo/go/internal/reflectlite/all_test.go @@ -982,21 +982,6 @@ func TestNames(t *testing.T) { } } -type embed struct { - EmbedWithUnexpMeth -} - -/* -func TestNameBytesAreAligned(t *testing.T) { - typ := TypeOf(embed{}) - b := FirstMethodNameBytes(typ) - v := uintptr(unsafe.Pointer(b)) - if v%unsafe.Alignof((*byte)(nil)) != 0 { - t.Errorf("reflect.name.bytes pointer is not aligned: %x", v) - } -} -*/ - // TestUnaddressableField tests that the reflect package will not allow // a type from another package to be used as a named type with an // unexported field. diff --git a/libgo/go/internal/reflectlite/type.go b/libgo/go/internal/reflectlite/type.go index 0c1b994..db1469d 100644 --- a/libgo/go/internal/reflectlite/type.go +++ b/libgo/go/internal/reflectlite/type.go @@ -67,7 +67,7 @@ type Type interface { } /* - * These data structures are known to the compiler (../../cmd/internal/gc/reflect.go). + * These data structures are known to the compiler (../../cmd/internal/reflectdata/reflect.go). * A few are known to ../runtime/type.go to convey to debuggers. * They are also known to ../runtime/type.go. */ diff --git a/libgo/go/internal/syscall/execenv/execenv_default.go b/libgo/go/internal/syscall/execenv/execenv_default.go index 4bdbb55..73289f1 100644 --- a/libgo/go/internal/syscall/execenv/execenv_default.go +++ b/libgo/go/internal/syscall/execenv/execenv_default.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows // +build !windows package execenv diff --git a/libgo/go/internal/syscall/execenv/execenv_windows.go b/libgo/go/internal/syscall/execenv/execenv_windows.go index b50029c..6c06549 100644 --- a/libgo/go/internal/syscall/execenv/execenv_windows.go +++ b/libgo/go/internal/syscall/execenv/execenv_windows.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package execenv diff --git a/libgo/go/internal/syscall/unix/at.go b/libgo/go/internal/syscall/unix/at.go index a602d3a..5059af3 100644 --- a/libgo/go/internal/syscall/unix/at.go +++ b/libgo/go/internal/syscall/unix/at.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//-go:build linux || openbsd || netbsd || dragonfly // -build linux openbsd netbsd dragonfly package unix diff --git a/libgo/go/internal/syscall/unix/getentropy_darwin.go b/libgo/go/internal/syscall/unix/getentropy_darwin.go new file mode 100644 index 0000000..e1a410a --- /dev/null +++ b/libgo/go/internal/syscall/unix/getentropy_darwin.go @@ -0,0 +1,30 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unix + +import ( + "internal/abi" + "syscall" + "unsafe" +) + +//go:cgo_import_dynamic libc_getentropy getentropy "/usr/lib/libSystem.B.dylib" + +func libc_getentropy_trampoline() + +// GetEntropy calls the macOS getentropy system call. +func GetEntropy(p []byte) error { + _, _, errno := syscall_syscall(abi.FuncPCABI0(libc_getentropy_trampoline), + uintptr(unsafe.Pointer(&p[0])), + uintptr(len(p)), + 0) + if errno != 0 { + return errno + } + return nil +} + +//go:linkname syscall_syscall syscall.syscall +func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) diff --git a/libgo/go/internal/syscall/unix/getrandom.go b/libgo/go/internal/syscall/unix/getrandom.go new file mode 100644 index 0000000..d2c58c0 --- /dev/null +++ b/libgo/go/internal/syscall/unix/getrandom.go @@ -0,0 +1,40 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build dragonfly || freebsd || linux +// +build dragonfly freebsd linux + +package unix + +import ( + "sync/atomic" + "syscall" + "unsafe" +) + +var getrandomUnsupported int32 // atomic + +// GetRandomFlag is a flag supported by the getrandom system call. +type GetRandomFlag uintptr + +// GetRandom calls the getrandom system call. +func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) { + if len(p) == 0 { + return 0, nil + } + if atomic.LoadInt32(&getrandomUnsupported) != 0 { + return 0, syscall.ENOSYS + } + r1, _, errno := syscall.Syscall(getrandomTrap, + uintptr(unsafe.Pointer(&p[0])), + uintptr(len(p)), + uintptr(flags)) + if errno != 0 { + if errno == syscall.ENOSYS { + atomic.StoreInt32(&getrandomUnsupported, 1) + } + return 0, errno + } + return int(r1), nil +} diff --git a/libgo/go/internal/syscall/unix/getrandom_dragonfly.go b/libgo/go/internal/syscall/unix/getrandom_dragonfly.go new file mode 100644 index 0000000..fbf78f9 --- /dev/null +++ b/libgo/go/internal/syscall/unix/getrandom_dragonfly.go @@ -0,0 +1,16 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unix + +// DragonFlyBSD getrandom system call number. +const getrandomTrap uintptr = 550 + +const ( + // GRND_RANDOM is only set for portability purpose, no-op on DragonFlyBSD. + GRND_RANDOM GetRandomFlag = 0x0001 + + // GRND_NONBLOCK means return EAGAIN rather than blocking. + GRND_NONBLOCK GetRandomFlag = 0x0002 +) diff --git a/libgo/go/internal/syscall/unix/getrandom_freebsd.go b/libgo/go/internal/syscall/unix/getrandom_freebsd.go index f1ba573..8c4f3df 100644 --- a/libgo/go/internal/syscall/unix/getrandom_freebsd.go +++ b/libgo/go/internal/syscall/unix/getrandom_freebsd.go @@ -4,19 +4,8 @@ package unix -import ( - "sync/atomic" - "syscall" - "unsafe" -) - -var randomUnsupported int32 // atomic - // FreeBSD getrandom system call number. -const randomTrap uintptr = 563 - -// GetRandomFlag is a flag supported by the getrandom system call. -type GetRandomFlag uintptr +const getrandomTrap uintptr = 563 const ( // GRND_NONBLOCK means return EAGAIN rather than blocking. @@ -25,24 +14,3 @@ const ( // GRND_RANDOM is only set for portability purpose, no-op on FreeBSD. GRND_RANDOM GetRandomFlag = 0x0002 ) - -// GetRandom calls the FreeBSD getrandom system call. -func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) { - if len(p) == 0 { - return 0, nil - } - if atomic.LoadInt32(&randomUnsupported) != 0 { - return 0, syscall.ENOSYS - } - r1, _, errno := syscall.Syscall(randomTrap, - uintptr(unsafe.Pointer(&p[0])), - uintptr(len(p)), - uintptr(flags)) - if errno != 0 { - if errno == syscall.ENOSYS { - atomic.StoreInt32(&randomUnsupported, 1) - } - return 0, errno - } - return int(r1), nil -} diff --git a/libgo/go/internal/syscall/unix/getrandom_linux.go b/libgo/go/internal/syscall/unix/getrandom_linux.go index 490d516..8ccd8d3 100644 --- a/libgo/go/internal/syscall/unix/getrandom_linux.go +++ b/libgo/go/internal/syscall/unix/getrandom_linux.go @@ -4,17 +4,6 @@ package unix -import ( - "sync/atomic" - "syscall" - "unsafe" -) - -var randomUnsupported int32 // atomic - -// GetRandomFlag is a flag supported by the getrandom system call. -type GetRandomFlag uintptr - const ( // GRND_NONBLOCK means return EAGAIN rather than blocking. GRND_NONBLOCK GetRandomFlag = 0x0001 @@ -22,25 +11,3 @@ const ( // GRND_RANDOM means use the /dev/random pool instead of /dev/urandom. GRND_RANDOM GetRandomFlag = 0x0002 ) - -// GetRandom calls the Linux getrandom system call. -// See https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c6e9d6f38894798696f23c8084ca7edbf16ee895 -func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) { - if len(p) == 0 { - return 0, nil - } - if atomic.LoadInt32(&randomUnsupported) != 0 { - return 0, syscall.ENOSYS - } - r1, _, errno := syscall.Syscall(getrandomTrap, - uintptr(unsafe.Pointer(&p[0])), - uintptr(len(p)), - uintptr(flags)) - if errno != 0 { - if errno == syscall.ENOSYS { - atomic.StoreInt32(&randomUnsupported, 1) - } - return 0, errno - } - return int(r1), nil -} diff --git a/libgo/go/internal/syscall/unix/getrandom_solaris.go b/libgo/go/internal/syscall/unix/getrandom_solaris.go new file mode 100644 index 0000000..caf9b60 --- /dev/null +++ b/libgo/go/internal/syscall/unix/getrandom_solaris.go @@ -0,0 +1,46 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unix + +import ( + "sync/atomic" + "syscall" + "unsafe" +) + +//extern getrandom +func libc_getrandom(*byte, uintptr, uint32) uintptr + +// GetRandomFlag is a flag supported by the getrandom system call. +type GetRandomFlag uintptr + +const ( + // GRND_NONBLOCK means return EAGAIN rather than blocking. + GRND_NONBLOCK GetRandomFlag = 0x0001 + + // GRND_RANDOM means use the /dev/random pool instead of /dev/urandom. + GRND_RANDOM GetRandomFlag = 0x0002 +) + +// GetRandom calls the getrandom system call. +func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) { + if len(p) == 0 { + return 0, nil + } + if atomic.LoadInt32(&getrandomUnsupported) != 0 { + return 0, syscall.ENOSYS + } + syscall.Entersyscall() + r1 := libc_getrandom(&p[0], uintptr(len(p)), uint32(flags)) + syscall.Exitsyscall() + if r1 == 0 { + errno := syscall.GetErrno() + if errno == syscall.ENOSYS { + atomic.StoreInt32(&getrandomUnsupported, 1) + } + return 0, errno + } + return int(r1), nil +} diff --git a/libgo/go/internal/syscall/unix/nonblocking.go b/libgo/go/internal/syscall/unix/nonblocking.go index 1734cdc..dc2e107 100644 --- a/libgo/go/internal/syscall/unix/nonblocking.go +++ b/libgo/go/internal/syscall/unix/nonblocking.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build dragonfly || freebsd || hurd || linux || netbsd || openbsd // +build dragonfly freebsd hurd linux netbsd openbsd package unix diff --git a/libgo/go/internal/syscall/unix/nonblocking_js.go b/libgo/go/internal/syscall/unix/nonblocking_js.go index a360b53..a5a5080 100644 --- a/libgo/go/internal/syscall/unix/nonblocking_js.go +++ b/libgo/go/internal/syscall/unix/nonblocking_js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package unix diff --git a/libgo/go/internal/syscall/unix/nonblocking_libc.go b/libgo/go/internal/syscall/unix/nonblocking_libc.go index 464314d..876fb16 100644 --- a/libgo/go/internal/syscall/unix/nonblocking_libc.go +++ b/libgo/go/internal/syscall/unix/nonblocking_libc.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || solaris // +build aix darwin solaris package unix diff --git a/libgo/go/internal/syscall/unix/sysnum_linux_generic.go b/libgo/go/internal/syscall/unix/sysnum_linux_generic.go index 3d34fdb..d8db1bb 100644 --- a/libgo/go/internal/syscall/unix/sysnum_linux_generic.go +++ b/libgo/go/internal/syscall/unix/sysnum_linux_generic.go @@ -2,8 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux && (arm64 || riscv64 || arm64be || nios2 || riscv) // +build linux -// +build arm64 arm64be nios2 riscv riscv64 +// +build arm64 riscv64 arm64be nios2 riscv package unix diff --git a/libgo/go/internal/syscall/unix/sysnum_linux_mips64x.go b/libgo/go/internal/syscall/unix/sysnum_linux_mips64x.go index 6680942..f353d4d 100644 --- a/libgo/go/internal/syscall/unix/sysnum_linux_mips64x.go +++ b/libgo/go/internal/syscall/unix/sysnum_linux_mips64x.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build mips64 || mips64le // +build mips64 mips64le package unix diff --git a/libgo/go/internal/syscall/unix/sysnum_linux_mipsx.go b/libgo/go/internal/syscall/unix/sysnum_linux_mipsx.go index 185d832..4ed4715 100644 --- a/libgo/go/internal/syscall/unix/sysnum_linux_mipsx.go +++ b/libgo/go/internal/syscall/unix/sysnum_linux_mipsx.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build mips || mipsle // +build mips mipsle package unix diff --git a/libgo/go/internal/syscall/unix/sysnum_linux_ppc64x.go b/libgo/go/internal/syscall/unix/sysnum_linux_ppc64x.go index aa2e81a..5befa08 100644 --- a/libgo/go/internal/syscall/unix/sysnum_linux_ppc64x.go +++ b/libgo/go/internal/syscall/unix/sysnum_linux_ppc64x.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ppc || ppc64 || ppc64le // +build ppc ppc64 ppc64le package unix diff --git a/libgo/go/internal/testenv/testenv_cgo.go b/libgo/go/internal/testenv/testenv_cgo.go index e3d4d16..02f08f5 100644 --- a/libgo/go/internal/testenv/testenv_cgo.go +++ b/libgo/go/internal/testenv/testenv_cgo.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cgo // +build cgo package testenv diff --git a/libgo/go/internal/testenv/testenv_notwin.go b/libgo/go/internal/testenv/testenv_notwin.go index ccb5d55..846ec93 100644 --- a/libgo/go/internal/testenv/testenv_notwin.go +++ b/libgo/go/internal/testenv/testenv_notwin.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows // +build !windows package testenv diff --git a/libgo/go/internal/trace/parser.go b/libgo/go/internal/trace/parser.go index c371ff3..254f201 100644 --- a/libgo/go/internal/trace/parser.go +++ b/libgo/go/internal/trace/parser.go @@ -1042,8 +1042,8 @@ const ( EvGoSysBlock = 30 // syscall blocks [timestamp] EvGoWaiting = 31 // denotes that goroutine is blocked when tracing starts [timestamp, goroutine id] EvGoInSyscall = 32 // denotes that goroutine is in syscall when tracing starts [timestamp, goroutine id] - EvHeapAlloc = 33 // memstats.heap_live change [timestamp, heap_alloc] - EvNextGC = 34 // memstats.next_gc change [timestamp, next_gc] + EvHeapAlloc = 33 // gcController.heapLive change [timestamp, heap live bytes] + EvHeapGoal = 34 // gcController.heapGoal change [timestamp, heap goal bytes] EvTimerGoroutine = 35 // denotes timer goroutine [timer goroutine id] EvFutileWakeup = 36 // denotes that the previous wakeup of this goroutine was futile [timestamp] EvString = 37 // string dictionary entry [ID, length, string] @@ -1102,7 +1102,7 @@ var EventDescriptions = [EvCount]struct { EvGoWaiting: {"GoWaiting", 1005, false, []string{"g"}, nil}, EvGoInSyscall: {"GoInSyscall", 1005, false, []string{"g"}, nil}, EvHeapAlloc: {"HeapAlloc", 1005, false, []string{"mem"}, nil}, - EvNextGC: {"NextGC", 1005, false, []string{"mem"}, nil}, + EvHeapGoal: {"HeapGoal", 1005, false, []string{"mem"}, nil}, EvTimerGoroutine: {"TimerGoroutine", 1005, false, []string{"g"}, nil}, // in 1.5 format it was {"g", "unused"} EvFutileWakeup: {"FutileWakeup", 1005, false, []string{}, nil}, EvString: {"String", 1007, false, []string{}, nil}, diff --git a/libgo/go/io/example_test.go b/libgo/go/io/example_test.go index 6d338ac..a18df9f 100644 --- a/libgo/go/io/example_test.go +++ b/libgo/go/io/example_test.go @@ -103,7 +103,9 @@ func ExampleReadFull() { } func ExampleWriteString() { - io.WriteString(os.Stdout, "Hello World") + if _, err := io.WriteString(os.Stdout, "Hello World"); err != nil { + log.Fatal(err) + } // Output: Hello World } diff --git a/libgo/go/io/fs/example_test.go b/libgo/go/io/fs/example_test.go new file mode 100644 index 0000000..c902703 --- /dev/null +++ b/libgo/go/io/fs/example_test.go @@ -0,0 +1,25 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fs_test + +import ( + "fmt" + "io/fs" + "log" + "os" +) + +func ExampleWalkDir() { + root := "/usr/local/go/bin" + fileSystem := os.DirFS(root) + + fs.WalkDir(fileSystem, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + log.Fatal(err) + } + fmt.Println(path) + return nil + }) +} diff --git a/libgo/go/io/fs/fs.go b/libgo/go/io/fs/fs.go index 3d2e2ee..e1be324 100644 --- a/libgo/go/io/fs/fs.go +++ b/libgo/go/io/fs/fs.go @@ -73,8 +73,8 @@ func ValidPath(name string) bool { // A File provides access to a single file. // The File interface is the minimum implementation required of the file. -// A file may implement additional interfaces, such as -// ReadDirFile, ReaderAt, or Seeker, to provide additional or optimized functionality. +// Directory files should also implement ReadDirFile. +// A file may implement io.ReaderAt or io.Seeker as optimizations. type File interface { Stat() (FileInfo, error) Read([]byte) (int, error) diff --git a/libgo/go/io/fs/readdir.go b/libgo/go/io/fs/readdir.go index 3a5aa6d..2b10ddb 100644 --- a/libgo/go/io/fs/readdir.go +++ b/libgo/go/io/fs/readdir.go @@ -45,3 +45,33 @@ func ReadDir(fsys FS, name string) ([]DirEntry, error) { sort.Slice(list, func(i, j int) bool { return list[i].Name() < list[j].Name() }) return list, err } + +// dirInfo is a DirEntry based on a FileInfo. +type dirInfo struct { + fileInfo FileInfo +} + +func (di dirInfo) IsDir() bool { + return di.fileInfo.IsDir() +} + +func (di dirInfo) Type() FileMode { + return di.fileInfo.Mode().Type() +} + +func (di dirInfo) Info() (FileInfo, error) { + return di.fileInfo, nil +} + +func (di dirInfo) Name() string { + return di.fileInfo.Name() +} + +// FileInfoToDirEntry returns a DirEntry that returns information from info. +// If info is nil, FileInfoToDirEntry returns nil. +func FileInfoToDirEntry(info FileInfo) DirEntry { + if info == nil { + return nil + } + return dirInfo{fileInfo: info} +} diff --git a/libgo/go/io/fs/readdir_test.go b/libgo/go/io/fs/readdir_test.go index 405bfa6..a2b2c12 100644 --- a/libgo/go/io/fs/readdir_test.go +++ b/libgo/go/io/fs/readdir_test.go @@ -6,7 +6,10 @@ package fs_test import ( . "io/fs" + "os" "testing" + "testing/fstest" + "time" ) type readDirOnly struct{ ReadDirFS } @@ -41,3 +44,50 @@ func TestReadDir(t *testing.T) { dirs, err = ReadDir(sub, ".") check("sub(.)", dirs, err) } + +func TestFileInfoToDirEntry(t *testing.T) { + testFs := fstest.MapFS{ + "notadir.txt": { + Data: []byte("hello, world"), + Mode: 0, + ModTime: time.Now(), + Sys: &sysValue, + }, + "adir": { + Data: nil, + Mode: os.ModeDir, + ModTime: time.Now(), + Sys: &sysValue, + }, + } + + tests := []struct { + path string + wantMode FileMode + wantDir bool + }{ + {path: "notadir.txt", wantMode: 0, wantDir: false}, + {path: "adir", wantMode: os.ModeDir, wantDir: true}, + } + + for _, test := range tests { + test := test + t.Run(test.path, func(t *testing.T) { + fi, err := Stat(testFs, test.path) + if err != nil { + t.Fatal(err) + } + + dirEntry := FileInfoToDirEntry(fi) + if g, w := dirEntry.Type(), test.wantMode; g != w { + t.Errorf("FileMode mismatch: got=%v, want=%v", g, w) + } + if g, w := dirEntry.Name(), test.path; g != w { + t.Errorf("Name mismatch: got=%v, want=%v", g, w) + } + if g, w := dirEntry.IsDir(), test.wantDir; g != w { + t.Errorf("IsDir mismatch: got=%v, want=%v", g, w) + } + }) + } +} diff --git a/libgo/go/io/fs/readfile.go b/libgo/go/io/fs/readfile.go index 7ee9ead..d3c181c 100644 --- a/libgo/go/io/fs/readfile.go +++ b/libgo/go/io/fs/readfile.go @@ -15,6 +15,9 @@ type ReadFileFS interface { // A successful call returns a nil error, not io.EOF. // (Because ReadFile reads the whole file, the expected EOF // from the final Read is not treated as an error to be reported.) + // + // The caller is permitted to modify the returned byte slice. + // This method should return a copy of the underlying data. ReadFile(name string) ([]byte, error) } diff --git a/libgo/go/io/fs/sub.go b/libgo/go/io/fs/sub.go index 64cdffe..ae20e03 100644 --- a/libgo/go/io/fs/sub.go +++ b/libgo/go/io/fs/sub.go @@ -19,10 +19,10 @@ type SubFS interface { // Sub returns an FS corresponding to the subtree rooted at fsys's dir. // -// If fs implements SubFS, Sub calls returns fsys.Sub(dir). -// Otherwise, if dir is ".", Sub returns fsys unchanged. +// If dir is ".", Sub returns fsys unchanged. +// Otherwise, if fs implements SubFS, Sub returns fsys.Sub(dir). // Otherwise, Sub returns a new FS implementation sub that, -// in effect, implements sub.Open(dir) as fsys.Open(path.Join(dir, name)). +// in effect, implements sub.Open(name) as fsys.Open(path.Join(dir, name)). // The implementation also translates calls to ReadDir, ReadFile, and Glob appropriately. // // Note that Sub(os.DirFS("/"), "prefix") is equivalent to os.DirFS("/prefix") @@ -68,7 +68,7 @@ func (f *subFS) shorten(name string) (rel string, ok bool) { return "", false } -// fixErr shortens any reported names in PathErrors by stripping dir. +// fixErr shortens any reported names in PathErrors by stripping f.dir. func (f *subFS) fixErr(err error) error { if e, ok := err.(*PathError); ok { if short, ok := f.shorten(e.Path); ok { @@ -125,3 +125,14 @@ func (f *subFS) Glob(pattern string) ([]string, error) { } return list, f.fixErr(err) } + +func (f *subFS) Sub(dir string) (FS, error) { + if dir == "." { + return f, nil + } + full, err := f.fullName("sub", dir) + if err != nil { + return nil, err + } + return &subFS{f.fsys, full}, nil +} diff --git a/libgo/go/io/fs/walk_test.go b/libgo/go/io/fs/walk_test.go index ebc4e50..5e127e7 100644 --- a/libgo/go/io/fs/walk_test.go +++ b/libgo/go/io/fs/walk_test.go @@ -6,7 +6,6 @@ package fs_test import ( . "io/fs" - "io/ioutil" "os" pathpkg "path" "testing" @@ -96,11 +95,7 @@ func mark(entry DirEntry, err error, errors *[]error, clear bool) error { } func TestWalkDir(t *testing.T) { - tmpDir, err := ioutil.TempDir("", "TestWalk") - if err != nil { - t.Fatal("creating temp dir:", err) - } - defer os.RemoveAll(tmpDir) + tmpDir := t.TempDir() origDir, err := os.Getwd() if err != nil { diff --git a/libgo/go/io/io.go b/libgo/go/io/io.go index ffd3ced..2724321 100644 --- a/libgo/go/io/io.go +++ b/libgo/go/io/io.go @@ -566,7 +566,7 @@ func (t *teeReader) Read(p []byte) (n int, err error) { return } -// Discard is an Writer on which all Write calls succeed +// Discard is a Writer on which all Write calls succeed // without doing anything. var Discard Writer = discard{} diff --git a/libgo/go/io/ioutil/tempfile.go b/libgo/go/io/ioutil/tempfile.go index af7c6fd..c43db2c 100644 --- a/libgo/go/io/ioutil/tempfile.go +++ b/libgo/go/io/ioutil/tempfile.go @@ -5,38 +5,9 @@ package ioutil import ( - "errors" "os" - "path/filepath" - "strconv" - "strings" - "sync" - "time" ) -// Random number state. -// We generate random temporary file names so that there's a good -// chance the file doesn't exist yet - keeps the number of tries in -// TempFile to a minimum. -var rand uint32 -var randmu sync.Mutex - -func reseed() uint32 { - return uint32(time.Now().UnixNano() + int64(os.Getpid())) -} - -func nextRandom() string { - randmu.Lock() - r := rand - if r == 0 { - r = reseed() - } - r = r*1664525 + 1013904223 // constants from Numerical Recipes - rand = r - randmu.Unlock() - return strconv.Itoa(int(1e9 + r%1e9))[1:] -} - // TempFile creates a new temporary file in the directory dir, // opens the file for reading and writing, and returns the resulting *os.File. // The filename is generated by taking pattern and adding a random @@ -48,48 +19,10 @@ func nextRandom() string { // will not choose the same file. The caller can use f.Name() // to find the pathname of the file. It is the caller's responsibility // to remove the file when no longer needed. +// +// As of Go 1.17, this function simply calls os.CreateTemp. func TempFile(dir, pattern string) (f *os.File, err error) { - if dir == "" { - dir = os.TempDir() - } - - prefix, suffix, err := prefixAndSuffix(pattern) - if err != nil { - return - } - - nconflict := 0 - for i := 0; i < 10000; i++ { - name := filepath.Join(dir, prefix+nextRandom()+suffix) - f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) - if os.IsExist(err) { - if nconflict++; nconflict > 10 { - randmu.Lock() - rand = reseed() - randmu.Unlock() - } - continue - } - break - } - return -} - -var errPatternHasSeparator = errors.New("pattern contains path separator") - -// prefixAndSuffix splits pattern by the last wildcard "*", if applicable, -// returning prefix as the part before "*" and suffix as the part after "*". -func prefixAndSuffix(pattern string) (prefix, suffix string, err error) { - if strings.ContainsRune(pattern, os.PathSeparator) { - err = errPatternHasSeparator - return - } - if pos := strings.LastIndex(pattern, "*"); pos != -1 { - prefix, suffix = pattern[:pos], pattern[pos+1:] - } else { - prefix = pattern - } - return + return os.CreateTemp(dir, pattern) } // TempDir creates a new temporary directory in the directory dir. @@ -101,37 +34,8 @@ func prefixAndSuffix(pattern string) (prefix, suffix string, err error) { // Multiple programs calling TempDir simultaneously // will not choose the same directory. It is the caller's responsibility // to remove the directory when no longer needed. +// +// As of Go 1.17, this function simply calls os.MkdirTemp. func TempDir(dir, pattern string) (name string, err error) { - if dir == "" { - dir = os.TempDir() - } - - prefix, suffix, err := prefixAndSuffix(pattern) - if err != nil { - return - } - - nconflict := 0 - for i := 0; i < 10000; i++ { - try := filepath.Join(dir, prefix+nextRandom()+suffix) - err = os.Mkdir(try, 0700) - if os.IsExist(err) { - if nconflict++; nconflict > 10 { - randmu.Lock() - rand = reseed() - randmu.Unlock() - } - continue - } - if os.IsNotExist(err) { - if _, err := os.Stat(dir); os.IsNotExist(err) { - return "", err - } - } - if err == nil { - name = try - } - break - } - return + return os.MkdirTemp(dir, pattern) } diff --git a/libgo/go/io/ioutil/tempfile_test.go b/libgo/go/io/ioutil/tempfile_test.go index 440c7cf..5cef18c 100644 --- a/libgo/go/io/ioutil/tempfile_test.go +++ b/libgo/go/io/ioutil/tempfile_test.go @@ -50,6 +50,9 @@ func TestTempFile_pattern(t *testing.T) { } } +// This string is from os.errPatternHasSeparator. +const patternHasSeparator = "pattern contains path separator" + func TestTempFile_BadPattern(t *testing.T) { tmpDir, err := TempDir("", t.Name()) if err != nil { @@ -81,9 +84,8 @@ func TestTempFile_BadPattern(t *testing.T) { if tt.wantErr { if err == nil { t.Errorf("Expected an error for pattern %q", tt.pattern) - } - if g, w := err, ErrPatternHasSeparator; g != w { - t.Errorf("Error mismatch: got %#v, want %#v for pattern %q", g, w, tt.pattern) + } else if !strings.Contains(err.Error(), patternHasSeparator) { + t.Errorf("Error mismatch: got %#v, want %q for pattern %q", err, patternHasSeparator, tt.pattern) } } else if err != nil { t.Errorf("Unexpected error %v for pattern %q", err, tt.pattern) @@ -183,9 +185,8 @@ func TestTempDir_BadPattern(t *testing.T) { if tt.wantErr { if err == nil { t.Errorf("Expected an error for pattern %q", tt.pattern) - } - if g, w := err, ErrPatternHasSeparator; g != w { - t.Errorf("Error mismatch: got %#v, want %#v for pattern %q", g, w, tt.pattern) + } else if !strings.Contains(err.Error(), patternHasSeparator) { + t.Errorf("Error mismatch: got %#v, want %q for pattern %q", err, patternHasSeparator, tt.pattern) } } else if err != nil { t.Errorf("Unexpected error %v for pattern %q", err, tt.pattern) diff --git a/libgo/go/log/syslog/example_test.go b/libgo/go/log/syslog/example_test.go index 4288d37..9939765 100644 --- a/libgo/go/log/syslog/example_test.go +++ b/libgo/go/log/syslog/example_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows && !plan9 // +build !windows,!plan9 package syslog_test diff --git a/libgo/go/log/syslog/syslog.go b/libgo/go/log/syslog/syslog.go index 97c10f3..6abd4ad 100644 --- a/libgo/go/log/syslog/syslog.go +++ b/libgo/go/log/syslog/syslog.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows && !plan9 // +build !windows,!plan9 package syslog diff --git a/libgo/go/log/syslog/syslog_test.go b/libgo/go/log/syslog/syslog_test.go index 207bcf5..62c6250 100644 --- a/libgo/go/log/syslog/syslog_test.go +++ b/libgo/go/log/syslog/syslog_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows && !plan9 && !js // +build !windows,!plan9,!js package syslog diff --git a/libgo/go/log/syslog/syslog_unix.go b/libgo/go/log/syslog/syslog_unix.go index 940e92e..a3654c5 100644 --- a/libgo/go/log/syslog/syslog_unix.go +++ b/libgo/go/log/syslog/syslog_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows && !plan9 && !solaris && !irix // +build !windows,!plan9,!solaris,!irix package syslog diff --git a/libgo/go/math/all_test.go b/libgo/go/math/all_test.go index 3aae037..55c805e 100644 --- a/libgo/go/math/all_test.go +++ b/libgo/go/math/all_test.go @@ -2067,6 +2067,21 @@ var fmaC = []struct{ x, y, z, want float64 }{ {-7.751454006381804e-05, 5.588653777189071e-308, -2.2207280111272877e-308, -2.2211612130544025e-308}, } +var sqrt32 = []float32{ + 0, + float32(Copysign(0, -1)), + float32(NaN()), + float32(Inf(1)), + float32(Inf(-1)), + 1, + 2, + -2, + 4.9790119248836735e+00, + 7.7388724745781045e+00, + -2.7688005719200159e-01, + -5.0106036182710749e+00, +} + func tolerance(a, b, e float64) bool { // Multiplying by e here can underflow denormal values to zero. // Check a==b so that at least if a and b are small and identical @@ -3181,6 +3196,34 @@ func TestFloatMinMax(t *testing.T) { } } +func TestFloatMinima(t *testing.T) { + if q := float32(SmallestNonzeroFloat32 / 2); q != 0 { + t.Errorf("float32(SmallestNonzeroFloat32 / 2) = %g, want 0", q) + } + if q := float64(SmallestNonzeroFloat64 / 2); q != 0 { + t.Errorf("float64(SmallestNonzeroFloat64 / 2) = %g, want 0", q) + } +} + +var indirectSqrt = Sqrt + +// TestFloat32Sqrt checks the correctness of the float32 square root optimization result. +func TestFloat32Sqrt(t *testing.T) { + for _, v := range sqrt32 { + want := float32(indirectSqrt(float64(v))) + got := float32(Sqrt(float64(v))) + if IsNaN(float64(want)) { + if !IsNaN(float64(got)) { + t.Errorf("got=%#v want=NaN, v=%#v", got, v) + } + continue + } + if got != want { + t.Errorf("got=%#v want=%#v, v=%#v", got, want, v) + } + } +} + // Benchmarks // Global exported variables are used to store the diff --git a/libgo/go/math/arith_s390x.go b/libgo/go/math/arith_s390x.go index c28651e..6352734 100644 --- a/libgo/go/math/arith_s390x.go +++ b/libgo/go/math/arith_s390x.go @@ -2,78 +2,172 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package math import "internal/cpu" +func expTrampolineSetup(x float64) float64 +func expAsm(x float64) float64 + +func logTrampolineSetup(x float64) float64 +func logAsm(x float64) float64 + +// Below here all functions are grouped in stubs.go for other +// architectures. + +const haveArchLog10 = true + +func archLog10(x float64) float64 func log10TrampolineSetup(x float64) float64 func log10Asm(x float64) float64 +const haveArchCos = true + +func archCos(x float64) float64 func cosTrampolineSetup(x float64) float64 func cosAsm(x float64) float64 +const haveArchCosh = true + +func archCosh(x float64) float64 func coshTrampolineSetup(x float64) float64 func coshAsm(x float64) float64 +const haveArchSin = true + +func archSin(x float64) float64 func sinTrampolineSetup(x float64) float64 func sinAsm(x float64) float64 +const haveArchSinh = true + +func archSinh(x float64) float64 func sinhTrampolineSetup(x float64) float64 func sinhAsm(x float64) float64 +const haveArchTanh = true + +func archTanh(x float64) float64 func tanhTrampolineSetup(x float64) float64 func tanhAsm(x float64) float64 +const haveArchLog1p = true + +func archLog1p(x float64) float64 func log1pTrampolineSetup(x float64) float64 func log1pAsm(x float64) float64 +const haveArchAtanh = true + +func archAtanh(x float64) float64 func atanhTrampolineSetup(x float64) float64 func atanhAsm(x float64) float64 +const haveArchAcos = true + +func archAcos(x float64) float64 func acosTrampolineSetup(x float64) float64 func acosAsm(x float64) float64 +const haveArchAcosh = true + +func archAcosh(x float64) float64 func acoshTrampolineSetup(x float64) float64 func acoshAsm(x float64) float64 +const haveArchAsin = true + +func archAsin(x float64) float64 func asinTrampolineSetup(x float64) float64 func asinAsm(x float64) float64 +const haveArchAsinh = true + +func archAsinh(x float64) float64 func asinhTrampolineSetup(x float64) float64 func asinhAsm(x float64) float64 +const haveArchErf = true + +func archErf(x float64) float64 func erfTrampolineSetup(x float64) float64 func erfAsm(x float64) float64 +const haveArchErfc = true + +func archErfc(x float64) float64 func erfcTrampolineSetup(x float64) float64 func erfcAsm(x float64) float64 +const haveArchAtan = true + +func archAtan(x float64) float64 func atanTrampolineSetup(x float64) float64 func atanAsm(x float64) float64 +const haveArchAtan2 = true + +func archAtan2(y, x float64) float64 func atan2TrampolineSetup(x, y float64) float64 func atan2Asm(x, y float64) float64 +const haveArchCbrt = true + +func archCbrt(x float64) float64 func cbrtTrampolineSetup(x float64) float64 func cbrtAsm(x float64) float64 -func logTrampolineSetup(x float64) float64 -func logAsm(x float64) float64 +const haveArchTan = true +func archTan(x float64) float64 func tanTrampolineSetup(x float64) float64 func tanAsm(x float64) float64 -func expTrampolineSetup(x float64) float64 -func expAsm(x float64) float64 +const haveArchExpm1 = true +func archExpm1(x float64) float64 func expm1TrampolineSetup(x float64) float64 func expm1Asm(x float64) float64 +const haveArchPow = true + +func archPow(x, y float64) float64 func powTrampolineSetup(x, y float64) float64 func powAsm(x, y float64) float64 +const haveArchFrexp = false + +func archFrexp(x float64) (float64, int) { + panic("not implemented") +} + +const haveArchLdexp = false + +func archLdexp(frac float64, exp int) float64 { + panic("not implemented") +} + +const haveArchLog2 = false + +func archLog2(x float64) float64 { + panic("not implemented") +} + +const haveArchMod = false + +func archMod(x, y float64) float64 { + panic("not implemented") +} + +const haveArchRemainder = false + +func archRemainder(x, y float64) float64 { + panic("not implemented") +} + // hasVX reports whether the machine has the z/Architecture // vector facility installed and enabled. var hasVX = cpu.S390X.HasVX diff --git a/libgo/go/math/asin.go b/libgo/go/math/asin.go index 46a5fe9..ac70bcb 100644 --- a/libgo/go/math/asin.go +++ b/libgo/go/math/asin.go @@ -16,14 +16,13 @@ package math // Special cases are: // Asin(±0) = ±0 // Asin(x) = NaN if x < -1 or x > 1 - -//extern asin -func libc_asin(float64) float64 - func Asin(x float64) float64 { return libc_asin(x) } +//extern asin +func libc_asin(float64) float64 + func asin(x float64) float64 { if x == 0 { return x // special case @@ -54,14 +53,13 @@ func asin(x float64) float64 { // // Special case is: // Acos(x) = NaN if x < -1 or x > 1 - -//extern acos -func libc_acos(float64) float64 - func Acos(x float64) float64 { return libc_acos(x) } +//extern acos +func libc_acos(float64) float64 + func acos(x float64) float64 { return Pi/2 - Asin(x) } diff --git a/libgo/go/math/atan.go b/libgo/go/math/atan.go index 4c9eda4..e4c997e 100644 --- a/libgo/go/math/atan.go +++ b/libgo/go/math/atan.go @@ -90,12 +90,8 @@ func satan(x float64) float64 { // Atan returns the arctangent, in radians, of x. // // Special cases are: -// Atan(±0) = ±0 -// Atan(±Inf) = ±Pi/2 - -//extern atan -func libc_atan(float64) float64 - +// Atan(±0) = ±0 +// Atan(±Inf) = ±Pi/2 func Atan(x float64) float64 { if x == 0 { return x @@ -103,6 +99,9 @@ func Atan(x float64) float64 { return libc_atan(x) } +//extern atan +func libc_atan(float64) float64 + func atan(x float64) float64 { if x == 0 { return x diff --git a/libgo/go/math/big/arith.go b/libgo/go/math/big/arith.go index 750ce8a..8f55c19 100644 --- a/libgo/go/math/big/arith.go +++ b/libgo/go/math/big/arith.go @@ -170,12 +170,16 @@ func shrVU_g(z, x []Word, s uint) (c Word) { if len(z) == 0 { return } + if len(x) != len(z) { + // This is an invariant guaranteed by the caller. + panic("len(x) != len(z)") + } s &= _W - 1 // hint to the compiler that shifts by s don't need guard code ŝ := _W - s ŝ &= _W - 1 // ditto c = x[0] << ŝ - for i := 0; i < len(z)-1; i++ { - z[i] = x[i]>>s | x[i+1]<<ŝ + for i := 1; i < len(z); i++ { + z[i-1] = x[i-1]>>s | x[i]<<ŝ } z[len(z)-1] = x[len(z)-1] >> s return @@ -263,20 +267,6 @@ func divWW(x1, x0, y, m Word) (q, r Word) { return Word(qq), Word(r0 >> s) } -func divWVW(z []Word, xn Word, x []Word, y Word) (r Word) { - r = xn - if len(x) == 1 { - qq, rr := bits.Div(uint(r), uint(x[0]), uint(y)) - z[0] = Word(qq) - return Word(rr) - } - rec := reciprocalWord(y) - for i := len(z) - 1; i >= 0; i-- { - z[i], r = divWW(r, x[i], y, rec) - } - return r -} - // reciprocalWord return the reciprocal of the divisor. rec = floor(( _B^2 - 1 ) / u - _B). u = d1 << nlz(d1). func reciprocalWord(d1 Word) Word { u := uint(d1 << nlz(d1)) diff --git a/libgo/go/math/big/arith_amd64.go b/libgo/go/math/big/arith_amd64.go index 35164f3..8e4e1a9 100644 --- a/libgo/go/math/big/arith_amd64.go +++ b/libgo/go/math/big/arith_amd64.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build ignore_for_gccgo -// +build !math_big_pure_go +//go:build ignore +// +build ignore package big diff --git a/libgo/go/math/big/arith_decl.go b/libgo/go/math/big/arith_decl.go index a14fda3..d80b92b 100644 --- a/libgo/go/math/big/arith_decl.go +++ b/libgo/go/math/big/arith_decl.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore -// +build !math_big_pure_go package big diff --git a/libgo/go/math/big/arith_decl_pure.go b/libgo/go/math/big/arith_decl_pure.go index ac78985..cbfd1dd 100644 --- a/libgo/go/math/big/arith_decl_pure.go +++ b/libgo/go/math/big/arith_decl_pure.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//-go:build math_big_pure_go // -build math_big_pure_go package big diff --git a/libgo/go/math/big/arith_decl_s390x.go b/libgo/go/math/big/arith_decl_s390x.go index 712f115..96445b0 100644 --- a/libgo/go/math/big/arith_decl_s390x.go +++ b/libgo/go/math/big/arith_decl_s390x.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore -// +build !math_big_pure_go package big diff --git a/libgo/go/math/big/arith_s390x_test.go b/libgo/go/math/big/arith_s390x_test.go index be1ca7d..bda4811 100644 --- a/libgo/go/math/big/arith_s390x_test.go +++ b/libgo/go/math/big/arith_s390x_test.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore -// +build s390x,!math_big_pure_go package big diff --git a/libgo/go/math/big/arith_test.go b/libgo/go/math/big/arith_test.go index 2aca0ef..7b3427f 100644 --- a/libgo/go/math/big/arith_test.go +++ b/libgo/go/math/big/arith_test.go @@ -671,3 +671,27 @@ func BenchmarkDivWVW(b *testing.B) { }) } } + +func BenchmarkNonZeroShifts(b *testing.B) { + for _, n := range benchSizes { + if isRaceBuilder && n > 1e3 { + continue + } + x := rndV(n) + s := uint(rand.Int63n(_W-2)) + 1 // avoid 0 and over-large shifts + z := make([]Word, n) + b.Run(fmt.Sprint(n), func(b *testing.B) { + b.SetBytes(int64(n * _W)) + b.Run("shrVU", func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = shrVU(z, x, s) + } + }) + b.Run("shlVU", func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = shlVU(z, x, s) + } + }) + }) + } +} diff --git a/libgo/go/math/big/int.go b/libgo/go/math/big/int.go index 65f3248..7647346 100644 --- a/libgo/go/math/big/int.go +++ b/libgo/go/math/big/int.go @@ -425,7 +425,7 @@ func (z *Int) SetString(s string, base int) (*Int, bool) { return z.setFromScanner(strings.NewReader(s), base) } -// setFromScanner implements SetString given an io.BytesScanner. +// setFromScanner implements SetString given an io.ByteScanner. // For documentation see comments of SetString. func (z *Int) setFromScanner(r io.ByteScanner, base int) (*Int, bool) { if _, _, err := z.scan(r, base); err != nil { diff --git a/libgo/go/math/big/link_test.go b/libgo/go/math/big/link_test.go index 42f9cef..6e33aa5 100644 --- a/libgo/go/math/big/link_test.go +++ b/libgo/go/math/big/link_test.go @@ -42,7 +42,7 @@ func main() {} if err != nil { t.Fatalf("nm: %v, %s", err, nm) } - const want = "runtime.(*Frames).Next" + const want = "runtime.main" if !bytes.Contains(nm, []byte(want)) { // Test the test. t.Errorf("expected symbol %q not found", want) diff --git a/libgo/go/math/big/nat.go b/libgo/go/math/big/nat.go index bbd6c88..140c619 100644 --- a/libgo/go/math/big/nat.go +++ b/libgo/go/math/big/nat.go @@ -631,48 +631,6 @@ func (z nat) mulRange(a, b uint64) nat { return z.mul(nat(nil).mulRange(a, m), nat(nil).mulRange(m+1, b)) } -// q = (x-r)/y, with 0 <= r < y -func (z nat) divW(x nat, y Word) (q nat, r Word) { - m := len(x) - switch { - case y == 0: - panic("division by zero") - case y == 1: - q = z.set(x) // result is x - return - case m == 0: - q = z[:0] // result is 0 - return - } - // m > 0 - z = z.make(m) - r = divWVW(z, 0, x, y) - q = z.norm() - return -} - -func (z nat) div(z2, u, v nat) (q, r nat) { - if len(v) == 0 { - panic("division by zero") - } - - if u.cmp(v) < 0 { - q = z[:0] - r = z2.set(u) - return - } - - if len(v) == 1 { - var r2 Word - q, r2 = z.divW(u, v[0]) - r = z2.setWord(r2) - return - } - - q, r = z.divLarge(z2, u, v) - return -} - // getNat returns a *nat of len n. The contents may not be zero. // The pool holds *nat to avoid allocation when converting to interface{}. func getNat(n int) *nat { @@ -693,276 +651,6 @@ func putNat(x *nat) { var natPool sync.Pool -// q = (uIn-r)/vIn, with 0 <= r < vIn -// Uses z as storage for q, and u as storage for r if possible. -// See Knuth, Volume 2, section 4.3.1, Algorithm D. -// Preconditions: -// len(vIn) >= 2 -// len(uIn) >= len(vIn) -// u must not alias z -func (z nat) divLarge(u, uIn, vIn nat) (q, r nat) { - n := len(vIn) - m := len(uIn) - n - - // D1. - shift := nlz(vIn[n-1]) - // do not modify vIn, it may be used by another goroutine simultaneously - vp := getNat(n) - v := *vp - shlVU(v, vIn, shift) - - // u may safely alias uIn or vIn, the value of uIn is used to set u and vIn was already used - u = u.make(len(uIn) + 1) - u[len(uIn)] = shlVU(u[0:len(uIn)], uIn, shift) - - // z may safely alias uIn or vIn, both values were used already - if alias(z, u) { - z = nil // z is an alias for u - cannot reuse - } - q = z.make(m + 1) - - if n < divRecursiveThreshold { - q.divBasic(u, v) - } else { - q.divRecursive(u, v) - } - putNat(vp) - - q = q.norm() - shrVU(u, u, shift) - r = u.norm() - - return q, r -} - -// divBasic performs word-by-word division of u by v. -// The quotient is written in pre-allocated q. -// The remainder overwrites input u. -// -// Precondition: -// - q is large enough to hold the quotient u / v -// which has a maximum length of len(u)-len(v)+1. -func (q nat) divBasic(u, v nat) { - n := len(v) - m := len(u) - n - - qhatvp := getNat(n + 1) - qhatv := *qhatvp - - // D2. - vn1 := v[n-1] - rec := reciprocalWord(vn1) - for j := m; j >= 0; j-- { - // D3. - qhat := Word(_M) - var ujn Word - if j+n < len(u) { - ujn = u[j+n] - } - if ujn != vn1 { - var rhat Word - qhat, rhat = divWW(ujn, u[j+n-1], vn1, rec) - - // x1 | x2 = q̂v_{n-2} - vn2 := v[n-2] - x1, x2 := mulWW(qhat, vn2) - // test if q̂v_{n-2} > br̂ + u_{j+n-2} - ujn2 := u[j+n-2] - for greaterThan(x1, x2, rhat, ujn2) { - qhat-- - prevRhat := rhat - rhat += vn1 - // v[n-1] >= 0, so this tests for overflow. - if rhat < prevRhat { - break - } - x1, x2 = mulWW(qhat, vn2) - } - } - - // D4. - // Compute the remainder u - (q̂*v) << (_W*j). - // The subtraction may overflow if q̂ estimate was off by one. - qhatv[n] = mulAddVWW(qhatv[0:n], v, qhat, 0) - qhl := len(qhatv) - if j+qhl > len(u) && qhatv[n] == 0 { - qhl-- - } - c := subVV(u[j:j+qhl], u[j:], qhatv) - if c != 0 { - c := addVV(u[j:j+n], u[j:], v) - // If n == qhl, the carry from subVV and the carry from addVV - // cancel out and don't affect u[j+n]. - if n < qhl { - u[j+n] += c - } - qhat-- - } - - if j == m && m == len(q) && qhat == 0 { - continue - } - q[j] = qhat - } - - putNat(qhatvp) -} - -const divRecursiveThreshold = 100 - -// divRecursive performs word-by-word division of u by v. -// The quotient is written in pre-allocated z. -// The remainder overwrites input u. -// -// Precondition: -// - len(z) >= len(u)-len(v) -// -// See Burnikel, Ziegler, "Fast Recursive Division", Algorithm 1 and 2. -func (z nat) divRecursive(u, v nat) { - // Recursion depth is less than 2 log2(len(v)) - // Allocate a slice of temporaries to be reused across recursion. - recDepth := 2 * bits.Len(uint(len(v))) - // large enough to perform Karatsuba on operands as large as v - tmp := getNat(3 * len(v)) - temps := make([]*nat, recDepth) - z.clear() - z.divRecursiveStep(u, v, 0, tmp, temps) - for _, n := range temps { - if n != nil { - putNat(n) - } - } - putNat(tmp) -} - -// divRecursiveStep computes the division of u by v. -// - z must be large enough to hold the quotient -// - the quotient will overwrite z -// - the remainder will overwrite u -func (z nat) divRecursiveStep(u, v nat, depth int, tmp *nat, temps []*nat) { - u = u.norm() - v = v.norm() - - if len(u) == 0 { - z.clear() - return - } - n := len(v) - if n < divRecursiveThreshold { - z.divBasic(u, v) - return - } - m := len(u) - n - if m < 0 { - return - } - - // Produce the quotient by blocks of B words. - // Division by v (length n) is done using a length n/2 division - // and a length n/2 multiplication for each block. The final - // complexity is driven by multiplication complexity. - B := n / 2 - - // Allocate a nat for qhat below. - if temps[depth] == nil { - temps[depth] = getNat(n) - } else { - *temps[depth] = temps[depth].make(B + 1) - } - - j := m - for j > B { - // Divide u[j-B:j+n] by vIn. Keep remainder in u - // for next block. - // - // The following property will be used (Lemma 2): - // if u = u1 << s + u0 - // v = v1 << s + v0 - // then floor(u1/v1) >= floor(u/v) - // - // Moreover, the difference is at most 2 if len(v1) >= len(u/v) - // We choose s = B-1 since len(v)-s >= B+1 >= len(u/v) - s := (B - 1) - // Except for the first step, the top bits are always - // a division remainder, so the quotient length is <= n. - uu := u[j-B:] - - qhat := *temps[depth] - qhat.clear() - qhat.divRecursiveStep(uu[s:B+n], v[s:], depth+1, tmp, temps) - qhat = qhat.norm() - // Adjust the quotient: - // u = u_h << s + u_l - // v = v_h << s + v_l - // u_h = q̂ v_h + rh - // u = q̂ (v - v_l) + rh << s + u_l - // After the above step, u contains a remainder: - // u = rh << s + u_l - // and we need to subtract q̂ v_l - // - // But it may be a bit too large, in which case q̂ needs to be smaller. - qhatv := tmp.make(3 * n) - qhatv.clear() - qhatv = qhatv.mul(qhat, v[:s]) - for i := 0; i < 2; i++ { - e := qhatv.cmp(uu.norm()) - if e <= 0 { - break - } - subVW(qhat, qhat, 1) - c := subVV(qhatv[:s], qhatv[:s], v[:s]) - if len(qhatv) > s { - subVW(qhatv[s:], qhatv[s:], c) - } - addAt(uu[s:], v[s:], 0) - } - if qhatv.cmp(uu.norm()) > 0 { - panic("impossible") - } - c := subVV(uu[:len(qhatv)], uu[:len(qhatv)], qhatv) - if c > 0 { - subVW(uu[len(qhatv):], uu[len(qhatv):], c) - } - addAt(z, qhat, j-B) - j -= B - } - - // Now u < (v<<B), compute lower bits in the same way. - // Choose shift = B-1 again. - s := B - 1 - qhat := *temps[depth] - qhat.clear() - qhat.divRecursiveStep(u[s:].norm(), v[s:], depth+1, tmp, temps) - qhat = qhat.norm() - qhatv := tmp.make(3 * n) - qhatv.clear() - qhatv = qhatv.mul(qhat, v[:s]) - // Set the correct remainder as before. - for i := 0; i < 2; i++ { - if e := qhatv.cmp(u.norm()); e > 0 { - subVW(qhat, qhat, 1) - c := subVV(qhatv[:s], qhatv[:s], v[:s]) - if len(qhatv) > s { - subVW(qhatv[s:], qhatv[s:], c) - } - addAt(u[s:], v[s:], 0) - } - } - if qhatv.cmp(u.norm()) > 0 { - panic("impossible") - } - c := subVV(u[0:len(qhatv)], u[0:len(qhatv)], qhatv) - if c > 0 { - c = subVW(u[len(qhatv):], u[len(qhatv):], c) - } - if c > 0 { - panic("impossible") - } - - // Done! - addAt(z, qhat.norm(), 0) -} - // Length of x in bits. x must be normalized. func (x nat) bitLen() int { if i := len(x) - 1; i >= 0 { @@ -1170,19 +858,6 @@ func (z nat) xor(x, y nat) nat { return z.norm() } -// greaterThan reports whether (x1<<_W + x2) > (y1<<_W + y2) -func greaterThan(x1, x2, y1, y2 Word) bool { - return x1 > y1 || x1 == y1 && x2 > y2 -} - -// modW returns x % d. -func (x nat) modW(d Word) (r Word) { - // TODO(agl): we don't actually need to store the q value. - var q nat - q = q.make(len(x)) - return divWVW(q, 0, x, d) -} - // random creates a random integer in [0..limit), using the space in z if // possible. n is the bit length of limit. func (z nat) random(rand *rand.Rand, limit nat, n int) nat { diff --git a/libgo/go/math/big/natdiv.go b/libgo/go/math/big/natdiv.go new file mode 100644 index 0000000..882bb6d --- /dev/null +++ b/libgo/go/math/big/natdiv.go @@ -0,0 +1,884 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + +Multi-precision division. Here be dragons. + +Given u and v, where u is n+m digits, and v is n digits (with no leading zeros), +the goal is to return quo, rem such that u = quo*v + rem, where 0 ≤ rem < v. +That is, quo = ⌊u/v⌋ where ⌊x⌋ denotes the floor (truncation to integer) of x, +and rem = u - quo·v. + + +Long Division + +Division in a computer proceeds the same as long division in elementary school, +but computers are not as good as schoolchildren at following vague directions, +so we have to be much more precise about the actual steps and what can happen. + +We work from most to least significant digit of the quotient, doing: + + • Guess a digit q, the number of v to subtract from the current + section of u to zero out the topmost digit. + • Check the guess by multiplying q·v and comparing it against + the current section of u, adjusting the guess as needed. + • Subtract q·v from the current section of u. + • Add q to the corresponding section of the result quo. + +When all digits have been processed, the final remainder is left in u +and returned as rem. + +For example, here is a sketch of dividing 5 digits by 3 digits (n=3, m=2). + + q₂ q₁ q₀ + _________________ + v₂ v₁ v₀ ) u₄ u₃ u₂ u₁ u₀ + ↓ ↓ ↓ | | + [u₄ u₃ u₂]| | + - [ q₂·v ]| | + ----------- ↓ | + [ rem | u₁]| + - [ q₁·v ]| + ----------- ↓ + [ rem | u₀] + - [ q₀·v ] + ------------ + [ rem ] + +Instead of creating new storage for the remainders and copying digits from u +as indicated by the arrows, we use u's storage directly as both the source +and destination of the subtractions, so that the remainders overwrite +successive overlapping sections of u as the division proceeds, using a slice +of u to identify the current section. This avoids all the copying as well as +shifting of remainders. + +Division of u with n+m digits by v with n digits (in base B) can in general +produce at most m+1 digits, because: + + • u < B^(n+m) [B^(n+m) has n+m+1 digits] + • v ≥ B^(n-1) [B^(n-1) is the smallest n-digit number] + • u/v < B^(n+m) / B^(n-1) [divide bounds for u, v] + • u/v < B^(m+1) [simplify] + +The first step is special: it takes the top n digits of u and divides them by +the n digits of v, producing the first quotient digit and an n-digit remainder. +In the example, q₂ = ⌊u₄u₃u₂ / v⌋. + +The first step divides n digits by n digits to ensure that it produces only a +single digit. + +Each subsequent step appends the next digit from u to the remainder and divides +those n+1 digits by the n digits of v, producing another quotient digit and a +new n-digit remainder. + +Subsequent steps divide n+1 digits by n digits, an operation that in general +might produce two digits. However, as used in the algorithm, that division is +guaranteed to produce only a single digit. The dividend is of the form +rem·B + d, where rem is a remainder from the previous step and d is a single +digit, so: + + • rem ≤ v - 1 [rem is a remainder from dividing by v] + • rem·B ≤ v·B - B [multiply by B] + • d ≤ B - 1 [d is a single digit] + • rem·B + d ≤ v·B - 1 [add] + • rem·B + d < v·B [change ≤ to <] + • (rem·B + d)/v < B [divide by v] + + +Guess and Check + +At each step we need to divide n+1 digits by n digits, but this is for the +implementation of division by n digits, so we can't just invoke a division +routine: we _are_ the division routine. Instead, we guess at the answer and +then check it using multiplication. If the guess is wrong, we correct it. + +How can this guessing possibly be efficient? It turns out that the following +statement (let's call it the Good Guess Guarantee) is true. + +If + + • q = ⌊u/v⌋ where u is n+1 digits and v is n digits, + • q < B, and + • the topmost digit of v = vₙ₋₁ ≥ B/2, + +then q̂ = ⌊uₙuₙ₋₁ / vₙ₋₁⌋ satisfies q ≤ q̂ ≤ q+2. (Proof below.) + +That is, if we know the answer has only a single digit and we guess an answer +by ignoring the bottom n-1 digits of u and v, using a 2-by-1-digit division, +then that guess is at least as large as the correct answer. It is also not +too much larger: it is off by at most two from the correct answer. + +Note that in the first step of the overall division, which is an n-by-n-digit +division, the 2-by-1 guess uses an implicit uₙ = 0. + +Note that using a 2-by-1-digit division here does not mean calling ourselves +recursively. Instead, we use an efficient direct hardware implementation of +that operation. + +Note that because q is u/v rounded down, q·v must not exceed u: u ≥ q·v. +If a guess q̂ is too big, it will not satisfy this test. Viewed a different way, +the remainder r̂ for a given q̂ is u - q̂·v, which must be positive. If it is +negative, then the guess q̂ is too big. + +This gives us a way to compute q. First compute q̂ with 2-by-1-digit division. +Then, while u < q̂·v, decrement q̂; this loop executes at most twice, because +q̂ ≤ q+2. + + +Scaling Inputs + +The Good Guess Guarantee requires that the top digit of v (vₙ₋₁) be at least B/2. +For example in base 10, ⌊172/19⌋ = 9, but ⌊18/1⌋ = 18: the guess is wildly off +because the first digit 1 is smaller than B/2 = 5. + +We can ensure that v has a large top digit by multiplying both u and v by the +right amount. Continuing the example, if we multiply both 172 and 19 by 3, we +now have ⌊516/57⌋, the leading digit of v is now ≥ 5, and sure enough +⌊51/5⌋ = 10 is much closer to the correct answer 9. It would be easier here +to multiply by 4, because that can be done with a shift. Specifically, we can +always count the number of leading zeros i in the first digit of v and then +shift both u and v left by i bits. + +Having scaled u and v, the value ⌊u/v⌋ is unchanged, but the remainder will +be scaled: 172 mod 19 is 1, but 516 mod 57 is 3. We have to divide the remainder +by the scaling factor (shifting right i bits) when we finish. + +Note that these shifts happen before and after the entire division algorithm, +not at each step in the per-digit iteration. + +Note the effect of scaling inputs on the size of the possible quotient. +In the scaled u/v, u can gain a digit from scaling; v never does, because we +pick the scaling factor to make v's top digit larger but without overflowing. +If u and v have n+m and n digits after scaling, then: + + • u < B^(n+m) [B^(n+m) has n+m+1 digits] + • v ≥ B^n / 2 [vₙ₋₁ ≥ B/2, so vₙ₋₁·B^(n-1) ≥ B^n/2] + • u/v < B^(n+m) / (B^n / 2) [divide bounds for u, v] + • u/v < 2 B^m [simplify] + +The quotient can still have m+1 significant digits, but if so the top digit +must be a 1. This provides a different way to handle the first digit of the +result: compare the top n digits of u against v and fill in either a 0 or a 1. + + +Refining Guesses + +Before we check whether u < q̂·v, we can adjust our guess to change it from +q̂ = ⌊uₙuₙ₋₁ / vₙ₋₁⌋ into the refined guess ⌊uₙuₙ₋₁uₙ₋₂ / vₙ₋₁vₙ₋₂⌋. +Although not mentioned above, the Good Guess Guarantee also promises that this +3-by-2-digit division guess is more precise and at most one away from the real +answer q. The improvement from the 2-by-1 to the 3-by-2 guess can also be done +without n-digit math. + +If we have a guess q̂ = ⌊uₙuₙ₋₁ / vₙ₋₁⌋ and we want to see if it also equal to +⌊uₙuₙ₋₁uₙ₋₂ / vₙ₋₁vₙ₋₂⌋, we can use the same check we would for the full division: +if uₙuₙ₋₁uₙ₋₂ < q̂·vₙ₋₁vₙ₋₂, then the guess is too large and should be reduced. + +Checking uₙuₙ₋₁uₙ₋₂ < q̂·vₙ₋₁vₙ₋₂ is the same as uₙuₙ₋₁uₙ₋₂ - q̂·vₙ₋₁vₙ₋₂ < 0, +and + + uₙuₙ₋₁uₙ₋₂ - q̂·vₙ₋₁vₙ₋₂ = (uₙuₙ₋₁·B + uₙ₋₂) - q̂·(vₙ₋₁·B + vₙ₋₂) + [splitting off the bottom digit] + = (uₙuₙ₋₁ - q̂·vₙ₋₁)·B + uₙ₋₂ - q̂·vₙ₋₂ + [regrouping] + +The expression (uₙuₙ₋₁ - q̂·vₙ₋₁) is the remainder of uₙuₙ₋₁ / vₙ₋₁. +If the initial guess returns both q̂ and its remainder r̂, then checking +whether uₙuₙ₋₁uₙ₋₂ < q̂·vₙ₋₁vₙ₋₂ is the same as checking r̂·B + uₙ₋₂ < q̂·vₙ₋₂. + +If we find that r̂·B + uₙ₋₂ < q̂·vₙ₋₂, then we can adjust the guess by +decrementing q̂ and adding vₙ₋₁ to r̂. We repeat until r̂·B + uₙ₋₂ ≥ q̂·vₙ₋₂. +(As before, this fixup is only needed at most twice.) + +Now that q̂ = ⌊uₙuₙ₋₁uₙ₋₂ / vₙ₋₁vₙ₋₂⌋, as mentioned above it is at most one +away from the correct q, and we've avoided doing any n-digit math. +(If we need the new remainder, it can be computed as r̂·B + uₙ₋₂ - q̂·vₙ₋₂.) + +The final check u < q̂·v and the possible fixup must be done at full precision. +For random inputs, a fixup at this step is exceedingly rare: the 3-by-2 guess +is not often wrong at all. But still we must do the check. Note that since the +3-by-2 guess is off by at most 1, it can be convenient to perform the final +u < q̂·v as part of the computation of the remainder r = u - q̂·v. If the +subtraction underflows, decremeting q̂ and adding one v back to r is enough to +arrive at the final q, r. + +That's the entirety of long division: scale the inputs, and then loop over +each output position, guessing, checking, and correcting the next output digit. + +For a 2n-digit number divided by an n-digit number (the worst size-n case for +division complexity), this algorithm uses n+1 iterations, each of which must do +at least the 1-by-n-digit multiplication q̂·v. That's O(n) iterations of +O(n) time each, so O(n²) time overall. + + +Recursive Division + +For very large inputs, it is possible to improve on the O(n²) algorithm. +Let's call a group of n/2 real digits a (very) “wide digit”. We can run the +standard long division algorithm explained above over the wide digits instead of +the actual digits. This will result in many fewer steps, but the math involved in +each step is more work. + +Where basic long division uses a 2-by-1-digit division to guess the initial q̂, +the new algorithm must use a 2-by-1-wide-digit division, which is of course +really an n-by-n/2-digit division. That's OK: if we implement n-digit division +in terms of n/2-digit division, the recursion will terminate when the divisor +becomes small enough to handle with standard long division or even with the +2-by-1 hardware instruction. + +For example, here is a sketch of dividing 10 digits by 4, proceeding with +wide digits corresponding to two regular digits. The first step, still special, +must leave off a (regular) digit, dividing 5 by 4 and producing a 4-digit +remainder less than v. The middle steps divide 6 digits by 4, guaranteed to +produce two output digits each (one wide digit) with 4-digit remainders. +The final step must use what it has: the 4-digit remainder plus one more, +5 digits to divide by 4. + + q₆ q₅ q₄ q₃ q₂ q₁ q₀ + _______________________________ + v₃ v₂ v₁ v₀ ) u₉ u₈ u₇ u₆ u₅ u₄ u₃ u₂ u₁ u₀ + ↓ ↓ ↓ ↓ ↓ | | | | | + [u₉ u₈ u₇ u₆ u₅]| | | | | + - [ q₆q₅·v ]| | | | | + ----------------- ↓ ↓ | | | + [ rem |u₄ u₃]| | | + - [ q₄q₃·v ]| | | + -------------------- ↓ ↓ | + [ rem |u₂ u₁]| + - [ q₂q₁·v ]| + -------------------- ↓ + [ rem |u₀] + - [ q₀·v ] + ------------------ + [ rem ] + +An alternative would be to look ahead to how well n/2 divides into n+m and +adjust the first step to use fewer digits as needed, making the first step +more special to make the last step not special at all. For example, using the +same input, we could choose to use only 4 digits in the first step, leaving +a full wide digit for the last step: + + q₆ q₅ q₄ q₃ q₂ q₁ q₀ + _______________________________ + v₃ v₂ v₁ v₀ ) u₉ u₈ u₇ u₆ u₅ u₄ u₃ u₂ u₁ u₀ + ↓ ↓ ↓ ↓ | | | | | | + [u₉ u₈ u₇ u₆]| | | | | | + - [ q₆·v ]| | | | | | + -------------- ↓ ↓ | | | | + [ rem |u₅ u₄]| | | | + - [ q₅q₄·v ]| | | | + -------------------- ↓ ↓ | | + [ rem |u₃ u₂]| | + - [ q₃q₂·v ]| | + -------------------- ↓ ↓ + [ rem |u₁ u₀] + - [ q₁q₀·v ] + --------------------- + [ rem ] + +Today, the code in divRecursiveStep works like the first example. Perhaps in +the future we will make it work like the alternative, to avoid a special case +in the final iteration. + +Either way, each step is a 3-by-2-wide-digit division approximated first by +a 2-by-1-wide-digit division, just as we did for regular digits in long division. +Because the actual answer we want is a 3-by-2-wide-digit division, instead of +multiplying q̂·v directly during the fixup, we can use the quick refinement +from long division (an n/2-by-n/2 multiply) to correct q to its actual value +and also compute the remainder (as mentioned above), and then stop after that, +never doing a full n-by-n multiply. + +Instead of using an n-by-n/2-digit division to produce n/2 digits, we can add +(not discard) one more real digit, doing an (n+1)-by-(n/2+1)-digit division that +produces n/2+1 digits. That single extra digit tightens the Good Guess Guarantee +to q ≤ q̂ ≤ q+1 and lets us drop long division's special treatment of the first +digit. These benefits are discussed more after the Good Guess Guarantee proof +below. + + +How Fast is Recursive Division? + +For a 2n-by-n-digit division, this algorithm runs a 4-by-2 long division over +wide digits, producing two wide digits plus a possible leading regular digit 1, +which can be handled without a recursive call. That is, the algorithm uses two +full iterations, each using an n-by-n/2-digit division and an n/2-by-n/2-digit +multiplication, along with a few n-digit additions and subtractions. The standard +n-by-n-digit multiplication algorithm requires O(n²) time, making the overall +algorithm require time T(n) where + + T(n) = 2T(n/2) + O(n) + O(n²) + +which, by the Bentley-Haken-Saxe theorem, ends up reducing to T(n) = O(n²). +This is not an improvement over regular long division. + +When the number of digits n becomes large enough, Karatsuba's algorithm for +multiplication can be used instead, which takes O(n^log₂3) = O(n^1.6) time. +(Karatsuba multiplication is implemented in func karatsuba in nat.go.) +That makes the overall recursive division algorithm take O(n^1.6) time as well, +which is an improvement, but again only for large enough numbers. + +It is not critical to make sure that every recursion does only two recursive +calls. While in general the number of recursive calls can change the time +analysis, in this case doing three calls does not change the analysis: + + T(n) = 3T(n/2) + O(n) + O(n^log₂3) + +ends up being T(n) = O(n^log₂3). Because the Karatsuba multiplication taking +time O(n^log₂3) is itself doing 3 half-sized recursions, doing three for the +division does not hurt the asymptotic performance. Of course, it is likely +still faster in practice to do two. + + +Proof of the Good Guess Guarantee + +Given numbers x, y, let us break them into the quotients and remainders when +divided by some scaling factor S, with the added constraints that the quotient +x/y and the high part of y are both less than some limit T, and that the high +part of y is at least half as big as T. + + x₁ = ⌊x/S⌋ y₁ = ⌊y/S⌋ + x₀ = x mod S y₀ = y mod S + + x = x₁·S + x₀ 0 ≤ x₀ < S x/y < T + y = y₁·S + y₀ 0 ≤ y₀ < S T/2 ≤ y₁ < T + +And consider the two truncated quotients: + + q = ⌊x/y⌋ + q̂ = ⌊x₁/y₁⌋ + +We will prove that q ≤ q̂ ≤ q+2. + +The guarantee makes no real demands on the scaling factor S: it is simply the +magnitude of the digits cut from both x and y to produce x₁ and y₁. +The guarantee makes only limited demands on T: it must be large enough to hold +the quotient x/y, and y₁ must have roughly the same size. + +To apply to the earlier discussion of 2-by-1 guesses in long division, +we would choose: + + S = Bⁿ⁻¹ + T = B + x = u + x₁ = uₙuₙ₋₁ + x₀ = uₙ₋₂...u₀ + y = v + y₁ = vₙ₋₁ + y₀ = vₙ₋₂...u₀ + +These simpler variables avoid repeating those longer expressions in the proof. + +Note also that, by definition, truncating division ⌊x/y⌋ satisfies + + x/y - 1 < ⌊x/y⌋ ≤ x/y. + +This fact will be used a few times in the proofs. + +Proof that q ≤ q̂: + + q̂·y₁ = ⌊x₁/y₁⌋·y₁ [by definition, q̂ = ⌊x₁/y₁⌋] + > (x₁/y₁ - 1)·y₁ [x₁/y₁ - 1 < ⌊x₁/y₁⌋] + = x₁ - y₁ [distribute y₁] + + So q̂·y₁ > x₁ - y₁. + Since q̂·y₁ is an integer, q̂·y₁ ≥ x₁ - y₁ + 1. + + q̂ - q = q̂ - ⌊x/y⌋ [by definition, q = ⌊x/y⌋] + ≥ q̂ - x/y [⌊x/y⌋ < x/y] + = (1/y)·(q̂·y - x) [factor out 1/y] + ≥ (1/y)·(q̂·y₁·S - x) [y = y₁·S + y₀ ≥ y₁·S] + ≥ (1/y)·((x₁ - y₁ + 1)·S - x) [above: q̂·y₁ ≥ x₁ - y₁ + 1] + = (1/y)·(x₁·S - y₁·S + S - x) [distribute S] + = (1/y)·(S - x₀ - y₁·S) [-x = -x₁·S - x₀] + > -y₁·S / y [x₀ < S, so S - x₀ < 0; drop it] + ≥ -1 [y₁·S ≤ y] + + So q̂ - q > -1. + Since q̂ - q is an integer, q̂ - q ≥ 0, or equivalently q ≤ q̂. + +Proof that q̂ ≤ q+2: + + x₁/y₁ - x/y = x₁·S/y₁·S - x/y [multiply left term by S/S] + ≤ x/y₁·S - x/y [x₁S ≤ x] + = (x/y)·(y/y₁·S - 1) [factor out x/y] + = (x/y)·((y - y₁·S)/y₁·S) [move -1 into y/y₁·S fraction] + = (x/y)·(y₀/y₁·S) [y - y₁·S = y₀] + = (x/y)·(1/y₁)·(y₀/S) [factor out 1/y₁] + < (x/y)·(1/y₁) [y₀ < S, so y₀/S < 1] + ≤ (x/y)·(2/T) [y₁ ≥ T/2, so 1/y₁ ≤ 2/T] + < T·(2/T) [x/y < T] + = 2 [T·(2/T) = 2] + + So x₁/y₁ - x/y < 2. + + q̂ - q = ⌊x₁/y₁⌋ - q [by definition, q̂ = ⌊x₁/y₁⌋] + = ⌊x₁/y₁⌋ - ⌊x/y⌋ [by definition, q = ⌊x/y⌋] + ≤ x₁/y₁ - ⌊x/y⌋ [⌊x₁/y₁⌋ ≤ x₁/y₁] + < x₁/y₁ - (x/y - 1) [⌊x/y⌋ > x/y - 1] + = (x₁/y₁ - x/y) + 1 [regrouping] + < 2 + 1 [above: x₁/y₁ - x/y < 2] + = 3 + + So q̂ - q < 3. + Since q̂ - q is an integer, q̂ - q ≤ 2. + +Note that when x/y < T/2, the bounds tighten to x₁/y₁ - x/y < 1 and therefore +q̂ - q ≤ 1. + +Note also that in the general case 2n-by-n division where we don't know that +x/y < T, we do know that x/y < 2T, yielding the bound q̂ - q ≤ 4. So we could +remove the special case first step of long division as long as we allow the +first fixup loop to run up to four times. (Using a simple comparison to decide +whether the first digit is 0 or 1 is still more efficient, though.) + +Finally, note that when dividing three leading base-B digits by two (scaled), +we have T = B² and x/y < B = T/B, a much tighter bound than x/y < T. +This in turn yields the much tighter bound x₁/y₁ - x/y < 2/B. This means that +⌊x₁/y₁⌋ and ⌊x/y⌋ can only differ when x/y is less than 2/B greater than an +integer. For random x and y, the chance of this is 2/B, or, for large B, +approximately zero. This means that after we produce the 3-by-2 guess in the +long division algorithm, the fixup loop essentially never runs. + +In the recursive algorithm, the extra digit in (2·⌊n/2⌋+1)-by-(⌊n/2⌋+1)-digit +division has exactly the same effect: the probability of needing a fixup is the +same 2/B. Even better, we can allow the general case x/y < 2T and the fixup +probability only grows to 4/B, still essentially zero. + + +References + +There are no great references for implementing long division; thus this comment. +Here are some notes about what to expect from the obvious references. + +Knuth Volume 2 (Seminumerical Algorithms) section 4.3.1 is the usual canonical +reference for long division, but that entire series is highly compressed, never +repeating a necessary fact and leaving important insights to the exercises. +For example, no rationale whatsoever is given for the calculation that extends +q̂ from a 2-by-1 to a 3-by-2 guess, nor why it reduces the error bound. +The proof that the calculation even has the desired effect is left to exercises. +The solutions to those exercises provided at the back of the book are entirely +calculations, still with no explanation as to what is going on or how you would +arrive at the idea of doing those exact calculations. Nowhere is it mentioned +that this test extends the 2-by-1 guess into a 3-by-2 guess. The proof of the +Good Guess Guarantee is only for the 2-by-1 guess and argues by contradiction, +making it difficult to understand how modifications like adding another digit +or adjusting the quotient range affects the overall bound. + +All that said, Knuth remains the canonical reference. It is dense but packed +full of information and references, and the proofs are simpler than many other +presentations. The proofs above are reworkings of Knuth's to remove the +arguments by contradiction and add explanations or steps that Knuth omitted. +But beware of errors in older printings. Take the published errata with you. + +Brinch Hansen's “Multiple-length Division Revisited: a Tour of the Minefield” +starts with a blunt critique of Knuth's presentation (among others) and then +presents a more detailed and easier to follow treatment of long division, +including an implementation in Pascal. But the algorithm and implementation +work entirely in terms of 3-by-2 division, which is much less useful on modern +hardware than an algorithm using 2-by-1 division. The proofs are a bit too +focused on digit counting and seem needlessly complex, especially compared to +the ones given above. + +Burnikel and Ziegler's “Fast Recursive Division” introduced the key insight of +implementing division by an n-digit divisor using recursive calls to division +by an n/2-digit divisor, relying on Karatsuba multiplication to yield a +sub-quadratic run time. However, the presentation decisions are made almost +entirely for the purpose of simplifying the run-time analysis, rather than +simplifying the presentation. Instead of a single algorithm that loops over +quotient digits, the paper presents two mutually-recursive algorithms, for +2n-by-n and 3n-by-2n. The paper also does not present any general (n+m)-by-n +algorithm. + +The proofs in the paper are remarkably complex, especially considering that +the algorithm is at its core just long division on wide digits, so that the +usual long division proofs apply essentially unaltered. +*/ + +package big + +import "math/bits" + +// div returns q, r such that q = ⌊u/v⌋ and r = u%v = u - q·v. +// It uses z and z2 as the storage for q and r. +func (z nat) div(z2, u, v nat) (q, r nat) { + if len(v) == 0 { + panic("division by zero") + } + + if u.cmp(v) < 0 { + q = z[:0] + r = z2.set(u) + return + } + + if len(v) == 1 { + // Short division: long optimized for a single-word divisor. + // In that case, the 2-by-1 guess is all we need at each step. + var r2 Word + q, r2 = z.divW(u, v[0]) + r = z2.setWord(r2) + return + } + + q, r = z.divLarge(z2, u, v) + return +} + +// divW returns q, r such that q = ⌊x/y⌋ and r = x%y = x - q·y. +// It uses z as the storage for q. +// Note that y is a single digit (Word), not a big number. +func (z nat) divW(x nat, y Word) (q nat, r Word) { + m := len(x) + switch { + case y == 0: + panic("division by zero") + case y == 1: + q = z.set(x) // result is x + return + case m == 0: + q = z[:0] // result is 0 + return + } + // m > 0 + z = z.make(m) + r = divWVW(z, 0, x, y) + q = z.norm() + return +} + +// modW returns x % d. +func (x nat) modW(d Word) (r Word) { + // TODO(agl): we don't actually need to store the q value. + var q nat + q = q.make(len(x)) + return divWVW(q, 0, x, d) +} + +// divWVW overwrites z with ⌊x/y⌋, returning the remainder r. +// The caller must ensure that len(z) = len(x). +func divWVW(z []Word, xn Word, x []Word, y Word) (r Word) { + r = xn + if len(x) == 1 { + qq, rr := bits.Div(uint(r), uint(x[0]), uint(y)) + z[0] = Word(qq) + return Word(rr) + } + rec := reciprocalWord(y) + for i := len(z) - 1; i >= 0; i-- { + z[i], r = divWW(r, x[i], y, rec) + } + return r +} + +// div returns q, r such that q = ⌊uIn/vIn⌋ and r = uIn%vIn = uIn - q·vIn. +// It uses z and u as the storage for q and r. +// The caller must ensure that len(vIn) ≥ 2 (use divW otherwise) +// and that len(uIn) ≥ len(vIn) (the answer is 0, uIn otherwise). +func (z nat) divLarge(u, uIn, vIn nat) (q, r nat) { + n := len(vIn) + m := len(uIn) - n + + // Scale the inputs so vIn's top bit is 1 (see “Scaling Inputs” above). + // vIn is treated as a read-only input (it may be in use by another + // goroutine), so we must make a copy. + // uIn is copied to u. + shift := nlz(vIn[n-1]) + vp := getNat(n) + v := *vp + shlVU(v, vIn, shift) + u = u.make(len(uIn) + 1) + u[len(uIn)] = shlVU(u[0:len(uIn)], uIn, shift) + + // The caller should not pass aliased z and u, since those are + // the two different outputs, but correct just in case. + if alias(z, u) { + z = nil + } + q = z.make(m + 1) + + // Use basic or recursive long division depending on size. + if n < divRecursiveThreshold { + q.divBasic(u, v) + } else { + q.divRecursive(u, v) + } + putNat(vp) + + q = q.norm() + + // Undo scaling of remainder. + shrVU(u, u, shift) + r = u.norm() + + return q, r +} + +// divBasic implements long division as described above. +// It overwrites q with ⌊u/v⌋ and overwrites u with the remainder r. +// q must be large enough to hold ⌊u/v⌋. +func (q nat) divBasic(u, v nat) { + n := len(v) + m := len(u) - n + + qhatvp := getNat(n + 1) + qhatv := *qhatvp + + // Set up for divWW below, precomputing reciprocal argument. + vn1 := v[n-1] + rec := reciprocalWord(vn1) + + // Compute each digit of quotient. + for j := m; j >= 0; j-- { + // Compute the 2-by-1 guess q̂. + // The first iteration must invent a leading 0 for u. + qhat := Word(_M) + var ujn Word + if j+n < len(u) { + ujn = u[j+n] + } + + // ujn ≤ vn1, or else q̂ would be more than one digit. + // For ujn == vn1, we set q̂ to the max digit M above. + // Otherwise, we compute the 2-by-1 guess. + if ujn != vn1 { + var rhat Word + qhat, rhat = divWW(ujn, u[j+n-1], vn1, rec) + + // Refine q̂ to a 3-by-2 guess. See “Refining Guesses” above. + vn2 := v[n-2] + x1, x2 := mulWW(qhat, vn2) + ujn2 := u[j+n-2] + for greaterThan(x1, x2, rhat, ujn2) { // x1x2 > r̂ u[j+n-2] + qhat-- + prevRhat := rhat + rhat += vn1 + // If r̂ overflows, then + // r̂ u[j+n-2]v[n-1] is now definitely > x1 x2. + if rhat < prevRhat { + break + } + // TODO(rsc): No need for a full mulWW. + // x2 += vn2; if x2 overflows, x1++ + x1, x2 = mulWW(qhat, vn2) + } + } + + // Compute q̂·v. + qhatv[n] = mulAddVWW(qhatv[0:n], v, qhat, 0) + qhl := len(qhatv) + if j+qhl > len(u) && qhatv[n] == 0 { + qhl-- + } + + // Subtract q̂·v from the current section of u. + // If it underflows, q̂·v > u, which we fix up + // by decrementing q̂ and adding v back. + c := subVV(u[j:j+qhl], u[j:], qhatv) + if c != 0 { + c := addVV(u[j:j+n], u[j:], v) + // If n == qhl, the carry from subVV and the carry from addVV + // cancel out and don't affect u[j+n]. + if n < qhl { + u[j+n] += c + } + qhat-- + } + + // Save quotient digit. + // Caller may know the top digit is zero and not leave room for it. + if j == m && m == len(q) && qhat == 0 { + continue + } + q[j] = qhat + } + + putNat(qhatvp) +} + +// greaterThan reports whether the two digit numbers x1 x2 > y1 y2. +// TODO(rsc): In contradiction to most of this file, x1 is the high +// digit and x2 is the low digit. This should be fixed. +func greaterThan(x1, x2, y1, y2 Word) bool { + return x1 > y1 || x1 == y1 && x2 > y2 +} + +// divRecursiveThreshold is the number of divisor digits +// at which point divRecursive is faster than divBasic. +const divRecursiveThreshold = 100 + +// divRecursive implements recursive division as described above. +// It overwrites z with ⌊u/v⌋ and overwrites u with the remainder r. +// z must be large enough to hold ⌊u/v⌋. +// This function is just for allocating and freeing temporaries +// around divRecursiveStep, the real implementation. +func (z nat) divRecursive(u, v nat) { + // Recursion depth is (much) less than 2 log₂(len(v)). + // Allocate a slice of temporaries to be reused across recursion, + // plus one extra temporary not live across the recursion. + recDepth := 2 * bits.Len(uint(len(v))) + tmp := getNat(3 * len(v)) + temps := make([]*nat, recDepth) + + z.clear() + z.divRecursiveStep(u, v, 0, tmp, temps) + + // Free temporaries. + for _, n := range temps { + if n != nil { + putNat(n) + } + } + putNat(tmp) +} + +// divRecursiveStep is the actual implementation of recursive division. +// It adds ⌊u/v⌋ to z and overwrites u with the remainder r. +// z must be large enough to hold ⌊u/v⌋. +// It uses temps[depth] (allocating if needed) as a temporary live across +// the recursive call. It also uses tmp, but not live across the recursion. +func (z nat) divRecursiveStep(u, v nat, depth int, tmp *nat, temps []*nat) { + // u is a subsection of the original and may have leading zeros. + // TODO(rsc): The v = v.norm() is useless and should be removed. + // We know (and require) that v's top digit is ≥ B/2. + u = u.norm() + v = v.norm() + if len(u) == 0 { + z.clear() + return + } + + // Fall back to basic division if the problem is now small enough. + n := len(v) + if n < divRecursiveThreshold { + z.divBasic(u, v) + return + } + + // Nothing to do if u is shorter than v (implies u < v). + m := len(u) - n + if m < 0 { + return + } + + // We consider B digits in a row as a single wide digit. + // (See “Recursive Division” above.) + // + // TODO(rsc): rename B to Wide, to avoid confusion with _B, + // which is something entirely different. + // TODO(rsc): Look into whether using ⌈n/2⌉ is better than ⌊n/2⌋. + B := n / 2 + + // Allocate a nat for qhat below. + if temps[depth] == nil { + temps[depth] = getNat(n) // TODO(rsc): Can be just B+1. + } else { + *temps[depth] = temps[depth].make(B + 1) + } + + // Compute each wide digit of the quotient. + // + // TODO(rsc): Change the loop to be + // for j := (m+B-1)/B*B; j > 0; j -= B { + // which will make the final step a regular step, letting us + // delete what amounts to an extra copy of the loop body below. + j := m + for j > B { + // Divide u[j-B:j+n] (3 wide digits) by v (2 wide digits). + // First make the 2-by-1-wide-digit guess using a recursive call. + // Then extend the guess to the full 3-by-2 (see “Refining Guesses”). + // + // For the 2-by-1-wide-digit guess, instead of doing 2B-by-B-digit, + // we use a (2B+1)-by-(B+1) digit, which handles the possibility that + // the result has an extra leading 1 digit as well as guaranteeing + // that the computed q̂ will be off by at most 1 instead of 2. + + // s is the number of digits to drop from the 3B- and 2B-digit chunks. + // We drop B-1 to be left with 2B+1 and B+1. + s := (B - 1) + + // uu is the up-to-3B-digit section of u we are working on. + uu := u[j-B:] + + // Compute the 2-by-1 guess q̂, leaving r̂ in uu[s:B+n]. + qhat := *temps[depth] + qhat.clear() + qhat.divRecursiveStep(uu[s:B+n], v[s:], depth+1, tmp, temps) + qhat = qhat.norm() + + // Extend to a 3-by-2 quotient and remainder. + // Because divRecursiveStep overwrote the top part of uu with + // the remainder r̂, the full uu already contains the equivalent + // of r̂·B + uₙ₋₂ from the “Refining Guesses” discussion. + // Subtracting q̂·vₙ₋₂ from it will compute the full-length remainder. + // If that subtraction underflows, q̂·v > u, which we fix up + // by decrementing q̂ and adding v back, same as in long division. + + // TODO(rsc): Instead of subtract and fix-up, this code is computing + // q̂·vₙ₋₂ and decrementing q̂ until that product is ≤ u. + // But we can do the subtraction directly, as in the comment above + // and in long division, because we know that q̂ is wrong by at most one. + qhatv := tmp.make(3 * n) + qhatv.clear() + qhatv = qhatv.mul(qhat, v[:s]) + for i := 0; i < 2; i++ { + e := qhatv.cmp(uu.norm()) + if e <= 0 { + break + } + subVW(qhat, qhat, 1) + c := subVV(qhatv[:s], qhatv[:s], v[:s]) + if len(qhatv) > s { + subVW(qhatv[s:], qhatv[s:], c) + } + addAt(uu[s:], v[s:], 0) + } + if qhatv.cmp(uu.norm()) > 0 { + panic("impossible") + } + c := subVV(uu[:len(qhatv)], uu[:len(qhatv)], qhatv) + if c > 0 { + subVW(uu[len(qhatv):], uu[len(qhatv):], c) + } + addAt(z, qhat, j-B) + j -= B + } + + // TODO(rsc): Rewrite loop as described above and delete all this code. + + // Now u < (v<<B), compute lower bits in the same way. + // Choose shift = B-1 again. + s := B - 1 + qhat := *temps[depth] + qhat.clear() + qhat.divRecursiveStep(u[s:].norm(), v[s:], depth+1, tmp, temps) + qhat = qhat.norm() + qhatv := tmp.make(3 * n) + qhatv.clear() + qhatv = qhatv.mul(qhat, v[:s]) + // Set the correct remainder as before. + for i := 0; i < 2; i++ { + if e := qhatv.cmp(u.norm()); e > 0 { + subVW(qhat, qhat, 1) + c := subVV(qhatv[:s], qhatv[:s], v[:s]) + if len(qhatv) > s { + subVW(qhatv[s:], qhatv[s:], c) + } + addAt(u[s:], v[s:], 0) + } + } + if qhatv.cmp(u.norm()) > 0 { + panic("impossible") + } + c := subVV(u[0:len(qhatv)], u[0:len(qhatv)], qhatv) + if c > 0 { + c = subVW(u[len(qhatv):], u[len(qhatv):], c) + } + if c > 0 { + panic("impossible") + } + + // Done! + addAt(z, qhat.norm(), 0) +} diff --git a/libgo/go/math/bits/bits.go b/libgo/go/math/bits/bits.go index 0bfe90c..d8fd6ae 100644 --- a/libgo/go/math/bits/bits.go +++ b/libgo/go/math/bits/bits.go @@ -8,7 +8,7 @@ // functions for the predeclared unsigned integer types. package bits -const uintSize = 32 << (^uint(0) >> 32 & 1) // 32 or 64 +const uintSize = 32 << (^uint(0) >> 63) // 32 or 64 // UintSize is the size of a uint in bits. const UintSize = uintSize diff --git a/libgo/go/math/bits/bits_errors.go b/libgo/go/math/bits/bits_errors.go index f174bd1..53dc113 100644 --- a/libgo/go/math/bits/bits_errors.go +++ b/libgo/go/math/bits/bits_errors.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !compiler_bootstrap // +build !compiler_bootstrap package bits diff --git a/libgo/go/math/bits/bits_errors_bootstrap.go b/libgo/go/math/bits/bits_errors_bootstrap.go index 5df5738..4d610d3 100644 --- a/libgo/go/math/bits/bits_errors_bootstrap.go +++ b/libgo/go/math/bits/bits_errors_bootstrap.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build compiler_bootstrap // +build compiler_bootstrap // This version used only for bootstrap (on this path we want diff --git a/libgo/go/math/bits/bits_tables.go b/libgo/go/math/bits/bits_tables.go index f1e15a0..f869b8d 100644 --- a/libgo/go/math/bits/bits_tables.go +++ b/libgo/go/math/bits/bits_tables.go @@ -6,78 +6,74 @@ package bits -var ntz8tab = [256]uint8{ - 0x08, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x06, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x07, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x06, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, -} +const ntz8tab = "" + + "\x08\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + + "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + + "\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + + "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + + "\x06\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + + "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + + "\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + + "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + + "\x07\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + + "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + + "\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + + "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + + "\x06\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + + "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + + "\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + + "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" -var pop8tab = [256]uint8{ - 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, - 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, - 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, - 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, - 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, - 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, - 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, - 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, - 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, - 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, - 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, - 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, - 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, - 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, - 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, - 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08, -} +const pop8tab = "" + + "\x00\x01\x01\x02\x01\x02\x02\x03\x01\x02\x02\x03\x02\x03\x03\x04" + + "\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05" + + "\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05" + + "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + + "\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05" + + "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + + "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + + "\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07" + + "\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05" + + "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + + "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + + "\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07" + + "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + + "\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07" + + "\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07" + + "\x04\x05\x05\x06\x05\x06\x06\x07\x05\x06\x06\x07\x06\x07\x07\x08" -var rev8tab = [256]uint8{ - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, -} +const rev8tab = "" + + "\x00\x80\x40\xc0\x20\xa0\x60\xe0\x10\x90\x50\xd0\x30\xb0\x70\xf0" + + "\x08\x88\x48\xc8\x28\xa8\x68\xe8\x18\x98\x58\xd8\x38\xb8\x78\xf8" + + "\x04\x84\x44\xc4\x24\xa4\x64\xe4\x14\x94\x54\xd4\x34\xb4\x74\xf4" + + "\x0c\x8c\x4c\xcc\x2c\xac\x6c\xec\x1c\x9c\x5c\xdc\x3c\xbc\x7c\xfc" + + "\x02\x82\x42\xc2\x22\xa2\x62\xe2\x12\x92\x52\xd2\x32\xb2\x72\xf2" + + "\x0a\x8a\x4a\xca\x2a\xaa\x6a\xea\x1a\x9a\x5a\xda\x3a\xba\x7a\xfa" + + "\x06\x86\x46\xc6\x26\xa6\x66\xe6\x16\x96\x56\xd6\x36\xb6\x76\xf6" + + "\x0e\x8e\x4e\xce\x2e\xae\x6e\xee\x1e\x9e\x5e\xde\x3e\xbe\x7e\xfe" + + "\x01\x81\x41\xc1\x21\xa1\x61\xe1\x11\x91\x51\xd1\x31\xb1\x71\xf1" + + "\x09\x89\x49\xc9\x29\xa9\x69\xe9\x19\x99\x59\xd9\x39\xb9\x79\xf9" + + "\x05\x85\x45\xc5\x25\xa5\x65\xe5\x15\x95\x55\xd5\x35\xb5\x75\xf5" + + "\x0d\x8d\x4d\xcd\x2d\xad\x6d\xed\x1d\x9d\x5d\xdd\x3d\xbd\x7d\xfd" + + "\x03\x83\x43\xc3\x23\xa3\x63\xe3\x13\x93\x53\xd3\x33\xb3\x73\xf3" + + "\x0b\x8b\x4b\xcb\x2b\xab\x6b\xeb\x1b\x9b\x5b\xdb\x3b\xbb\x7b\xfb" + + "\x07\x87\x47\xc7\x27\xa7\x67\xe7\x17\x97\x57\xd7\x37\xb7\x77\xf7" + + "\x0f\x8f\x4f\xcf\x2f\xaf\x6f\xef\x1f\x9f\x5f\xdf\x3f\xbf\x7f\xff" -var len8tab = [256]uint8{ - 0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, -} +const len8tab = "" + + "\x00\x01\x02\x02\x03\x03\x03\x03\x04\x04\x04\x04\x04\x04\x04\x04" + + "\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + + "\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06" + + "\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06" + + "\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" + + "\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" + + "\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" + + "\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" + + "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + + "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + + "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + + "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + + "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + + "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + + "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" + + "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" diff --git a/libgo/go/math/bits/make_examples.go b/libgo/go/math/bits/make_examples.go index 1d3ad53..ac4004d 100644 --- a/libgo/go/math/bits/make_examples.go +++ b/libgo/go/math/bits/make_examples.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // This program generates example_test.go. diff --git a/libgo/go/math/bits/make_tables.go b/libgo/go/math/bits/make_tables.go index b068d5e..867025e 100644 --- a/libgo/go/math/bits/make_tables.go +++ b/libgo/go/math/bits/make_tables.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // This program generates bits_tables.go. @@ -47,16 +48,15 @@ func main() { } func gen(w io.Writer, name string, f func(uint8) uint8) { - fmt.Fprintf(w, "var %s = [256]uint8{", name) + // Use a const string to allow the compiler to constant-evaluate lookups at constant index. + fmt.Fprintf(w, "const %s = \"\"+\n\"", name) for i := 0; i < 256; i++ { - if i%16 == 0 { - fmt.Fprint(w, "\n\t") - } else { - fmt.Fprint(w, " ") + fmt.Fprintf(w, "\\x%02x", f(uint8(i))) + if i%16 == 15 && i != 255 { + fmt.Fprint(w, "\"+\n\"") } - fmt.Fprintf(w, "%#02x,", f(uint8(i))) } - fmt.Fprint(w, "\n}\n\n") + fmt.Fprint(w, "\"\n\n") } func ntz8(x uint8) (n uint8) { diff --git a/libgo/go/math/cmplx/huge_test.go b/libgo/go/math/cmplx/huge_test.go index f8e60c2..78b4231 100644 --- a/libgo/go/math/cmplx/huge_test.go +++ b/libgo/go/math/cmplx/huge_test.go @@ -5,6 +5,7 @@ // Disabled for s390x because it uses assembly routines that are not // accurate for huge arguments. +//go:build !s390x // +build !s390x package cmplx diff --git a/libgo/go/math/const.go b/libgo/go/math/const.go index 0fc8715..5ea935f 100644 --- a/libgo/go/math/const.go +++ b/libgo/go/math/const.go @@ -28,15 +28,19 @@ const ( // Max is the largest finite value representable by the type. // SmallestNonzero is the smallest positive, non-zero value representable by the type. const ( - MaxFloat32 = 3.40282346638528859811704183484516925440e+38 // 2**127 * (2**24 - 1) / 2**23 - SmallestNonzeroFloat32 = 1.401298464324817070923729583289916131280e-45 // 1 / 2**(127 - 1 + 23) + MaxFloat32 = 0x1p127 * (1 + (1 - 0x1p-23)) // 3.40282346638528859811704183484516925440e+38 + SmallestNonzeroFloat32 = 0x1p-126 * 0x1p-23 // 1.401298464324817070923729583289916131280e-45 - MaxFloat64 = 1.797693134862315708145274237317043567981e+308 // 2**1023 * (2**53 - 1) / 2**52 - SmallestNonzeroFloat64 = 4.940656458412465441765687928682213723651e-324 // 1 / 2**(1023 - 1 + 52) + MaxFloat64 = 0x1p1023 * (1 + (1 - 0x1p-52)) // 1.79769313486231570814527423731704356798070e+308 + SmallestNonzeroFloat64 = 0x1p-1022 * 0x1p-52 // 4.9406564584124654417656879286822137236505980e-324 ) // Integer limit values. const ( + intSize = 32 << (^uint(0) >> 63) // 32 or 64 + + MaxInt = 1<<(intSize-1) - 1 + MinInt = -1 << (intSize - 1) MaxInt8 = 1<<7 - 1 MinInt8 = -1 << 7 MaxInt16 = 1<<15 - 1 @@ -45,6 +49,7 @@ const ( MinInt32 = -1 << 31 MaxInt64 = 1<<63 - 1 MinInt64 = -1 << 63 + MaxUint = 1<<intSize - 1 MaxUint8 = 1<<8 - 1 MaxUint16 = 1<<16 - 1 MaxUint32 = 1<<32 - 1 diff --git a/libgo/go/math/const_test.go b/libgo/go/math/const_test.go new file mode 100644 index 0000000..170ba6a --- /dev/null +++ b/libgo/go/math/const_test.go @@ -0,0 +1,47 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package math_test + +import ( + "testing" + + . "math" +) + +func TestMaxUint(t *testing.T) { + if v := uint(MaxUint); v+1 != 0 { + t.Errorf("MaxUint should wrap around to zero: %d", v+1) + } + if v := uint8(MaxUint8); v+1 != 0 { + t.Errorf("MaxUint8 should wrap around to zero: %d", v+1) + } + if v := uint16(MaxUint16); v+1 != 0 { + t.Errorf("MaxUint16 should wrap around to zero: %d", v+1) + } + if v := uint32(MaxUint32); v+1 != 0 { + t.Errorf("MaxUint32 should wrap around to zero: %d", v+1) + } + if v := uint64(MaxUint64); v+1 != 0 { + t.Errorf("MaxUint64 should wrap around to zero: %d", v+1) + } +} + +func TestMaxInt(t *testing.T) { + if v := int(MaxInt); v+1 != MinInt { + t.Errorf("MaxInt should wrap around to MinInt: %d", v+1) + } + if v := int8(MaxInt8); v+1 != MinInt8 { + t.Errorf("MaxInt8 should wrap around to MinInt8: %d", v+1) + } + if v := int16(MaxInt16); v+1 != MinInt16 { + t.Errorf("MaxInt16 should wrap around to MinInt16: %d", v+1) + } + if v := int32(MaxInt32); v+1 != MinInt32 { + t.Errorf("MaxInt32 should wrap around to MinInt32: %d", v+1) + } + if v := int64(MaxInt64); v+1 != MinInt64 { + t.Errorf("MaxInt64 should wrap around to MinInt64: %d", v+1) + } +} diff --git a/libgo/go/math/dim.go b/libgo/go/math/dim.go index cf06f30..6a857bb 100644 --- a/libgo/go/math/dim.go +++ b/libgo/go/math/dim.go @@ -33,6 +33,9 @@ func Dim(x, y float64) float64 { // Max(+0, ±0) = Max(±0, +0) = +0 // Max(-0, -0) = -0 func Max(x, y float64) float64 { + if haveArchMax { + return archMax(x, y) + } return max(x, y) } @@ -62,6 +65,9 @@ func max(x, y float64) float64 { // Min(x, NaN) = Min(NaN, x) = NaN // Min(-0, ±0) = Min(±0, -0) = -0 func Min(x, y float64) float64 { + if haveArchMin { + return archMin(x, y) + } return min(x, y) } diff --git a/libgo/go/math/dim_noasm.go b/libgo/go/math/dim_noasm.go new file mode 100644 index 0000000..9a052c0 --- /dev/null +++ b/libgo/go/math/dim_noasm.go @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//-go:build !amd64 && !arm64 && !riscv64 && !s390x +// -build !amd64,!arm64,!riscv64,!s390x + +package math + +const haveArchMax = false + +func archMax(x, y float64) float64 { + panic("not implemented") +} + +const haveArchMin = false + +func archMin(x, y float64) float64 { + panic("not implemented") +} diff --git a/libgo/go/math/exp.go b/libgo/go/math/exp.go index f3d3cb6..7ab80b4 100644 --- a/libgo/go/math/exp.go +++ b/libgo/go/math/exp.go @@ -11,14 +11,13 @@ package math // Exp(NaN) = NaN // Very large values overflow to 0 or +Inf. // Very small values underflow to 1. - -//extern exp -func libc_exp(float64) float64 - func Exp(x float64) float64 { return libc_exp(x) } +//extern exp +func libc_exp(float64) float64 + // The original C code, the long comment, and the constants // below are from FreeBSD's /usr/src/lib/msun/src/e_exp.c // and came with this notice. The go code is a simplified @@ -139,6 +138,9 @@ func exp(x float64) float64 { // // Special cases are the same as Exp. func Exp2(x float64) float64 { + if haveArchExp2 { + return archExp2(x) + } return exp2(x) } diff --git a/libgo/go/math/exp2_noasm.go b/libgo/go/math/exp2_noasm.go new file mode 100644 index 0000000..9b81544 --- /dev/null +++ b/libgo/go/math/exp2_noasm.go @@ -0,0 +1,14 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//-go:build !arm64 +// -build !arm64 + +package math + +const haveArchExp2 = false + +func archExp2(x float64) float64 { + panic("not implemented") +} diff --git a/libgo/go/math/exp_asm.go b/libgo/go/math/exp_amd64.go index 11e0a61..654ccce 100644 --- a/libgo/go/math/exp_asm.go +++ b/libgo/go/math/exp_amd64.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build amd64 // +build amd64 -// +build ignore package math diff --git a/libgo/go/math/exp_noasm.go b/libgo/go/math/exp_noasm.go new file mode 100644 index 0000000..4f90604 --- /dev/null +++ b/libgo/go/math/exp_noasm.go @@ -0,0 +1,14 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//-go:build !amd64 && !arm64 && !s390x +// -build !amd64,!arm64,!s390x + +package math + +const haveArchExp = false + +func archExp(x float64) float64 { + panic("not implemented") +} diff --git a/libgo/go/math/expm1.go b/libgo/go/math/expm1.go index 9c6e080..bf685ae 100644 --- a/libgo/go/math/expm1.go +++ b/libgo/go/math/expm1.go @@ -121,10 +121,6 @@ package math // Expm1(-Inf) = -1 // Expm1(NaN) = NaN // Very large values overflow to -1 or +Inf. - -//extern expm1 -func libc_expm1(float64) float64 - func Expm1(x float64) float64 { if x == 0 { return x @@ -132,6 +128,9 @@ func Expm1(x float64) float64 { return libc_expm1(x) } +//extern expm1 +func libc_expm1(float64) float64 + func expm1(x float64) float64 { const ( Othreshold = 7.09782712893383973096e+02 // 0x40862E42FEFA39EF diff --git a/libgo/go/math/floor.go b/libgo/go/math/floor.go index 9115968..963c858 100644 --- a/libgo/go/math/floor.go +++ b/libgo/go/math/floor.go @@ -57,8 +57,10 @@ func ceil(x float64) float64 { // Trunc(±0) = ±0 // Trunc(±Inf) = ±Inf // Trunc(NaN) = NaN - func Trunc(x float64) float64 { + if haveArchTrunc { + return archTrunc(x) + } return trunc(x) } diff --git a/libgo/go/math/floor_noasm.go b/libgo/go/math/floor_noasm.go new file mode 100644 index 0000000..bcdc5b0 --- /dev/null +++ b/libgo/go/math/floor_noasm.go @@ -0,0 +1,26 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//-go:build !386 && !amd64 && !arm64 && !ppc64 && !ppc64le && !s390x && !wasm +// -build !386,!amd64,!arm64,!ppc64,!ppc64le,!s390x,!wasm + +package math + +const haveArchFloor = false + +func archFloor(x float64) float64 { + panic("not implemented") +} + +const haveArchCeil = false + +func archCeil(x float64) float64 { + panic("not implemented") +} + +const haveArchTrunc = false + +func archTrunc(x float64) float64 { + panic("not implemented") +} diff --git a/libgo/go/math/fma.go b/libgo/go/math/fma.go index db78dfa..ca0bf99 100644 --- a/libgo/go/math/fma.go +++ b/libgo/go/math/fma.go @@ -128,7 +128,7 @@ func FMA(x, y, z float64) float64 { pe -= int32(is62zero) // Swap addition operands so |p| >= |z| - if pe < ze || (pe == ze && (pm1 < zm1 || (pm1 == zm1 && pm2 < zm2))) { + if pe < ze || pe == ze && pm1 < zm1 { ps, pe, pm1, pm2, zs, ze, zm1, zm2 = zs, ze, zm1, zm2, ps, pe, pm1, pm2 } diff --git a/libgo/go/math/frexp.go b/libgo/go/math/frexp.go index 4ad0aee..3c8a909 100644 --- a/libgo/go/math/frexp.go +++ b/libgo/go/math/frexp.go @@ -14,6 +14,9 @@ package math // Frexp(±Inf) = ±Inf, 0 // Frexp(NaN) = NaN, 0 func Frexp(f float64) (frac float64, exp int) { + if haveArchFrexp { + return archFrexp(f) + } return frexp(f) } diff --git a/libgo/go/math/huge_test.go b/libgo/go/math/huge_test.go index 9448edc..ec81a4a 100644 --- a/libgo/go/math/huge_test.go +++ b/libgo/go/math/huge_test.go @@ -5,6 +5,7 @@ // Disabled for s390x because it uses assembly routines that are not // accurate for huge arguments. +//go:build !s390x // +build !s390x package math_test diff --git a/libgo/go/math/log.go b/libgo/go/math/log.go index cf242e8..f1c609d 100644 --- a/libgo/go/math/log.go +++ b/libgo/go/math/log.go @@ -77,14 +77,13 @@ package math // Log(0) = -Inf // Log(x < 0) = NaN // Log(NaN) = NaN - -//extern log -func libc_log(float64) float64 - func Log(x float64) float64 { return libc_log(x) } +//extern log +func libc_log(float64) float64 + func log(x float64) float64 { const ( Ln2Hi = 6.93147180369123816490e-01 /* 3fe62e42 fee00000 */ diff --git a/libgo/go/math/mod.go b/libgo/go/math/mod.go index 436788f..e223c7a 100644 --- a/libgo/go/math/mod.go +++ b/libgo/go/math/mod.go @@ -18,14 +18,13 @@ package math // Mod(x, 0) = NaN // Mod(x, ±Inf) = x // Mod(x, NaN) = NaN - -//extern fmod -func libc_fmod(float64, float64) float64 - func Mod(x, y float64) float64 { return libc_fmod(x, y) } +//extern fmod +func libc_fmod(float64, float64) float64 + func mod(x, y float64) float64 { if y == 0 || IsInf(x, 0) || IsNaN(x) || IsNaN(y) { return NaN() diff --git a/libgo/go/math/modf.go b/libgo/go/math/modf.go index b59d4b7..bf08dc6 100644 --- a/libgo/go/math/modf.go +++ b/libgo/go/math/modf.go @@ -11,6 +11,9 @@ package math // Modf(±Inf) = ±Inf, NaN // Modf(NaN) = NaN, NaN func Modf(f float64) (int float64, frac float64) { + if haveArchModf { + return archModf(f) + } return modf(f) } diff --git a/libgo/go/math/modf_noasm.go b/libgo/go/math/modf_noasm.go new file mode 100644 index 0000000..42d4734 --- /dev/null +++ b/libgo/go/math/modf_noasm.go @@ -0,0 +1,14 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//-go:build !arm64 && !ppc64 && !ppc64le +// -build !arm64,!ppc64,!ppc64le + +package math + +const haveArchModf = false + +func archModf(f float64) (int float64, frac float64) { + panic("not implemented") +} diff --git a/libgo/go/math/rand/export_test.go b/libgo/go/math/rand/export_test.go new file mode 100644 index 0000000..560010b --- /dev/null +++ b/libgo/go/math/rand/export_test.go @@ -0,0 +1,17 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +func Int31nForTest(r *Rand, n int32) int32 { + return r.int31n(n) +} + +func GetNormalDistributionParameters() (float64, [128]uint32, [128]float32, [128]float32) { + return rn, kn, wn, fn +} + +func GetExponentialDistributionParameters() (float64, [256]uint32, [256]float32, [256]float32) { + return re, ke, we, fe +} diff --git a/libgo/go/math/rand/gen_cooked.go b/libgo/go/math/rand/gen_cooked.go index 0afc10d..7950e09 100644 --- a/libgo/go/math/rand/gen_cooked.go +++ b/libgo/go/math/rand/gen_cooked.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // This program computes the value of rngCooked in rng.go, diff --git a/libgo/go/math/rand/race_test.go b/libgo/go/math/rand/race_test.go index 186c716..e7d1036 100644 --- a/libgo/go/math/rand/race_test.go +++ b/libgo/go/math/rand/race_test.go @@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package rand +package rand_test import ( + . "math/rand" "sync" "testing" ) diff --git a/libgo/go/math/rand/rand.go b/libgo/go/math/rand/rand.go index d6422c9..13f20ca 100644 --- a/libgo/go/math/rand/rand.go +++ b/libgo/go/math/rand/rand.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package rand implements pseudo-random number generators. +// Package rand implements pseudo-random number generators unsuitable for +// security-sensitive work. // // Random numbers are generated by a Source. Top-level functions, such as // Float64 and Int, use a default shared Source that produces a deterministic @@ -11,11 +12,9 @@ // The default Source is safe for concurrent use by multiple goroutines, but // Sources created by NewSource are not. // -// Mathematical interval notation such as [0, n) is used throughout the -// documentation for this package. -// -// For random numbers suitable for security-sensitive work, see the crypto/rand -// package. +// This package's outputs might be easily predictable regardless of how it's +// seeded. For random numbers suitable for security-sensitive work, see the +// crypto/rand package. package rand import "sync" @@ -104,7 +103,7 @@ func (r *Rand) Int() int { return int(u << 1 >> 1) // clear sign bit if int == int32 } -// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n). +// Int63n returns, as an int64, a non-negative pseudo-random number in the half-open interval [0,n). // It panics if n <= 0. func (r *Rand) Int63n(n int64) int64 { if n <= 0 { @@ -121,7 +120,7 @@ func (r *Rand) Int63n(n int64) int64 { return v % n } -// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n). +// Int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n). // It panics if n <= 0. func (r *Rand) Int31n(n int32) int32 { if n <= 0 { @@ -138,7 +137,7 @@ func (r *Rand) Int31n(n int32) int32 { return v % n } -// int31n returns, as an int32, a non-negative pseudo-random number in [0,n). +// int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n). // n must be > 0, but int31n does not check this; the caller must ensure it. // int31n exists because Int31n is inefficient, but Go 1 compatibility // requires that the stream of values produced by math/rand remain unchanged. @@ -162,7 +161,7 @@ func (r *Rand) int31n(n int32) int32 { return int32(prod >> 32) } -// Intn returns, as an int, a non-negative pseudo-random number in [0,n). +// Intn returns, as an int, a non-negative pseudo-random number in the half-open interval [0,n). // It panics if n <= 0. func (r *Rand) Intn(n int) int { if n <= 0 { @@ -174,7 +173,7 @@ func (r *Rand) Intn(n int) int { return int(r.Int63n(int64(n))) } -// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0). +// Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0). func (r *Rand) Float64() float64 { // A clearer, simpler implementation would be: // return float64(r.Int63n(1<<53)) / (1<<53) @@ -200,7 +199,7 @@ again: return f } -// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0). +// Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0). func (r *Rand) Float32() float32 { // Same rationale as in Float64: we want to preserve the Go 1 value // stream except we want to fix it not to return 1.0 @@ -213,7 +212,8 @@ again: return f } -// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n). +// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers +// in the half-open interval [0,n). func (r *Rand) Perm(n int) []int { m := make([]int, n) // In the following loop, the iteration when i=0 always swaps m[0] with m[0]. @@ -321,31 +321,31 @@ func Int31() int32 { return globalRand.Int31() } // Int returns a non-negative pseudo-random int from the default Source. func Int() int { return globalRand.Int() } -// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n) +// Int63n returns, as an int64, a non-negative pseudo-random number in the half-open interval [0,n) // from the default Source. // It panics if n <= 0. func Int63n(n int64) int64 { return globalRand.Int63n(n) } -// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n) +// Int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n) // from the default Source. // It panics if n <= 0. func Int31n(n int32) int32 { return globalRand.Int31n(n) } -// Intn returns, as an int, a non-negative pseudo-random number in [0,n) +// Intn returns, as an int, a non-negative pseudo-random number in the half-open interval [0,n) // from the default Source. // It panics if n <= 0. func Intn(n int) int { return globalRand.Intn(n) } -// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0) +// Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0) // from the default Source. func Float64() float64 { return globalRand.Float64() } -// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0) +// Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0) // from the default Source. func Float32() float32 { return globalRand.Float32() } -// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n) -// from the default Source. +// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers +// in the half-open interval [0,n) from the default Source. func Perm(n int) []int { return globalRand.Perm(n) } // Shuffle pseudo-randomizes the order of elements using the default Source. diff --git a/libgo/go/math/rand/rand_test.go b/libgo/go/math/rand/rand_test.go index e037aae..462de8b 100644 --- a/libgo/go/math/rand/rand_test.go +++ b/libgo/go/math/rand/rand_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package rand +package rand_test import ( "bytes" @@ -11,6 +11,7 @@ import ( "internal/testenv" "io" "math" + . "math/rand" "os" "runtime" "testing" @@ -21,6 +22,9 @@ const ( numTestSamples = 10000 ) +var rn, kn, wn, fn = GetNormalDistributionParameters() +var re, ke, we, fe = GetExponentialDistributionParameters() + type statsResults struct { mean float64 stddev float64 @@ -503,7 +507,7 @@ func TestUniformFactorial(t *testing.T) { fn func() int }{ {name: "Int31n", fn: func() int { return int(r.Int31n(int32(nfact))) }}, - {name: "int31n", fn: func() int { return int(r.int31n(int32(nfact))) }}, + {name: "int31n", fn: func() int { return int(Int31nForTest(r, int32(nfact))) }}, {name: "Perm", fn: func() int { return encodePerm(r.Perm(n)) }}, {name: "Shuffle", fn: func() int { // Generate permutation using Shuffle. diff --git a/libgo/go/math/remainder.go b/libgo/go/math/remainder.go index 0e2903e..bf8bfd5 100644 --- a/libgo/go/math/remainder.go +++ b/libgo/go/math/remainder.go @@ -35,6 +35,9 @@ package math // Remainder(x, ±Inf) = x // Remainder(x, NaN) = NaN func Remainder(x, y float64) float64 { + if haveArchRemainder { + return archRemainder(x, y) + } return remainder(x, y) } diff --git a/libgo/go/math/sin.go b/libgo/go/math/sin.go index 03fd14c..bd8b9a7 100644 --- a/libgo/go/math/sin.go +++ b/libgo/go/math/sin.go @@ -114,14 +114,13 @@ var _cos = [...]float64{ // Special cases are: // Cos(±Inf) = NaN // Cos(NaN) = NaN - -//extern cos -func libc_cos(float64) float64 - func Cos(x float64) float64 { return libc_cos(x) } +//extern cos +func libc_cos(float64) float64 + func cos(x float64) float64 { const ( PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts @@ -181,14 +180,13 @@ func cos(x float64) float64 { // Sin(±0) = ±0 // Sin(±Inf) = NaN // Sin(NaN) = NaN - -//extern sin -func libc_sin(float64) float64 - func Sin(x float64) float64 { return libc_sin(x) } +//extern sin +func libc_sin(float64) float64 + func sin(x float64) float64 { const ( PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts diff --git a/libgo/go/math/sinh.go b/libgo/go/math/sinh.go index 993424d..9fe9b4e 100644 --- a/libgo/go/math/sinh.go +++ b/libgo/go/math/sinh.go @@ -23,6 +23,13 @@ package math // Sinh(±Inf) = ±Inf // Sinh(NaN) = NaN func Sinh(x float64) float64 { + if haveArchSinh { + return archSinh(x) + } + return sinh(x) +} + +func sinh(x float64) float64 { // The coefficients are #2029 from Hart & Cheney. (20.36D) const ( P0 = -0.6307673640497716991184787251e+6 @@ -68,6 +75,13 @@ func Sinh(x float64) float64 { // Cosh(±Inf) = +Inf // Cosh(NaN) = NaN func Cosh(x float64) float64 { + if haveArchCosh { + return archCosh(x) + } + return cosh(x) +} + +func cosh(x float64) float64 { x = Abs(x) if x > 21 { return Exp(x) * 0.5 diff --git a/libgo/go/math/stubs.go b/libgo/go/math/stubs.go new file mode 100644 index 0000000..fe56800 --- /dev/null +++ b/libgo/go/math/stubs.go @@ -0,0 +1,161 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//-go:build !s390x +// -build !s390x + +// This is a large group of functions that most architectures don't +// implement in assembly. + +package math + +const haveArchAcos = false + +func archAcos(x float64) float64 { + panic("not implemented") +} + +const haveArchAcosh = false + +func archAcosh(x float64) float64 { + panic("not implemented") +} + +const haveArchAsin = false + +func archAsin(x float64) float64 { + panic("not implemented") +} + +const haveArchAsinh = false + +func archAsinh(x float64) float64 { + panic("not implemented") +} + +const haveArchAtan = false + +func archAtan(x float64) float64 { + panic("not implemented") +} + +const haveArchAtan2 = false + +func archAtan2(y, x float64) float64 { + panic("not implemented") +} + +const haveArchAtanh = false + +func archAtanh(x float64) float64 { + panic("not implemented") +} + +const haveArchCbrt = false + +func archCbrt(x float64) float64 { + panic("not implemented") +} + +const haveArchCos = false + +func archCos(x float64) float64 { + panic("not implemented") +} + +const haveArchCosh = false + +func archCosh(x float64) float64 { + panic("not implemented") +} + +const haveArchErf = false + +func archErf(x float64) float64 { + panic("not implemented") +} + +const haveArchErfc = false + +func archErfc(x float64) float64 { + panic("not implemented") +} + +const haveArchExpm1 = false + +func archExpm1(x float64) float64 { + panic("not implemented") +} + +const haveArchFrexp = false + +func archFrexp(x float64) (float64, int) { + panic("not implemented") +} + +const haveArchLdexp = false + +func archLdexp(frac float64, exp int) float64 { + panic("not implemented") +} + +const haveArchLog10 = false + +func archLog10(x float64) float64 { + panic("not implemented") +} + +const haveArchLog2 = false + +func archLog2(x float64) float64 { + panic("not implemented") +} + +const haveArchLog1p = false + +func archLog1p(x float64) float64 { + panic("not implemented") +} + +const haveArchMod = false + +func archMod(x, y float64) float64 { + panic("not implemented") +} + +const haveArchPow = false + +func archPow(x, y float64) float64 { + panic("not implemented") +} + +const haveArchRemainder = false + +func archRemainder(x, y float64) float64 { + panic("not implemented") +} + +const haveArchSin = false + +func archSin(x float64) float64 { + panic("not implemented") +} + +const haveArchSinh = false + +func archSinh(x float64) float64 { + panic("not implemented") +} + +const haveArchTan = false + +func archTan(x float64) float64 { + panic("not implemented") +} + +const haveArchTanh = false + +func archTanh(x float64) float64 { + panic("not implemented") +} diff --git a/libgo/go/math/tan.go b/libgo/go/math/tan.go index ca91d71..eea29d3 100644 --- a/libgo/go/math/tan.go +++ b/libgo/go/math/tan.go @@ -79,14 +79,13 @@ var _tanQ = [...]float64{ // Tan(±0) = ±0 // Tan(±Inf) = NaN // Tan(NaN) = NaN - -//extern tan -func libc_tan(float64) float64 - func Tan(x float64) float64 { return libc_tan(x) } +//extern tan +func libc_tan(float64) float64 + func tan(x float64) float64 { const ( PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts diff --git a/libgo/go/math/tanh.go b/libgo/go/math/tanh.go index 009a206..a825678 100644 --- a/libgo/go/math/tanh.go +++ b/libgo/go/math/tanh.go @@ -72,6 +72,13 @@ var tanhQ = [...]float64{ // Tanh(±Inf) = ±1 // Tanh(NaN) = NaN func Tanh(x float64) float64 { + if haveArchTanh { + return archTanh(x) + } + return tanh(x) +} + +func tanh(x float64) float64 { const MAXLOG = 8.8029691931113054295988e+01 // log(2**127) z := Abs(x) switch { diff --git a/libgo/go/mime/multipart/multipart.go b/libgo/go/mime/multipart/multipart.go index cb8bf393..81bf722 100644 --- a/libgo/go/mime/multipart/multipart.go +++ b/libgo/go/mime/multipart/multipart.go @@ -20,6 +20,7 @@ import ( "mime" "mime/quotedprintable" "net/textproto" + "path/filepath" "strings" ) @@ -67,13 +68,20 @@ func (p *Part) FormName() string { return p.dispositionParams["name"] } -// FileName returns the filename parameter of the Part's -// Content-Disposition header. +// FileName returns the filename parameter of the Part's Content-Disposition +// header. If not empty, the filename is passed through filepath.Base (which is +// platform dependent) before being returned. func (p *Part) FileName() string { if p.dispositionParams == nil { p.parseContentDisposition() } - return p.dispositionParams["filename"] + filename := p.dispositionParams["filename"] + if filename == "" { + return "" + } + // RFC 7578, Section 4.2 requires that if a filename is provided, the + // directory path information must not be used. + return filepath.Base(filename) } func (p *Part) parseContentDisposition() { diff --git a/libgo/go/mime/testdata/test.types.globs2 b/libgo/go/mime/testdata/test.types.globs2 new file mode 100644 index 0000000..cb5b789 --- /dev/null +++ b/libgo/go/mime/testdata/test.types.globs2 @@ -0,0 +1,9 @@ +# Copyright 2021 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + + +# mime package test for globs2 +50:document/test:*.t3 +50:example/test:*.t4 +30:example/do-not-use:*.t4 diff --git a/libgo/go/mime/type.go b/libgo/go/mime/type.go index 6d2b89e..2642433 100644 --- a/libgo/go/mime/type.go +++ b/libgo/go/mime/type.go @@ -58,6 +58,7 @@ func setMimeTypes(lowerExt, mixExt map[string]string) { } var builtinTypesLower = map[string]string{ + ".avif": "image/avif", ".css": "text/css; charset=utf-8", ".gif": "image/gif", ".htm": "text/html; charset=utf-8", @@ -95,9 +96,11 @@ func initMime() { // Extensions are looked up first case-sensitively, then case-insensitively. // // The built-in table is small but on unix it is augmented by the local -// system's mime.types file(s) if available under one or more of these -// names: +// system's MIME-info database or mime.types file(s) if available under one or +// more of these names: // +// /usr/local/share/mime/globs2 +// /usr/share/mime/globs2 // /etc/mime.types // /etc/apache2/mime.types // /etc/apache/mime.types diff --git a/libgo/go/mime/type_unix.go b/libgo/go/mime/type_unix.go index 6ac056c..753e989 100644 --- a/libgo/go/mime/type_unix.go +++ b/libgo/go/mime/type_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package mime @@ -16,6 +17,14 @@ func init() { osInitMime = initMimeUnix } +// See https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-0.21.html +// for the FreeDesktop Shared MIME-info Database specification. +var mimeGlobs = []string{ + "/usr/local/share/mime/globs2", + "/usr/share/mime/globs2", +} + +// Common locations for mime.types files on unix. var typeFiles = []string{ "/etc/mime.types", "/etc/apache2/mime.types", @@ -23,6 +32,39 @@ var typeFiles = []string{ "/etc/httpd/conf/mime.types", } +func loadMimeGlobsFile(filename string) error { + f, err := os.Open(filename) + if err != nil { + return err + } + defer f.Close() + + scanner := bufio.NewScanner(f) + for scanner.Scan() { + // Each line should be of format: weight:mimetype:*.ext + fields := strings.Split(scanner.Text(), ":") + if len(fields) < 3 || len(fields[0]) < 1 || len(fields[2]) < 2 { + continue + } else if fields[0][0] == '#' || fields[2][0] != '*' { + continue + } + + extension := fields[2][1:] + if _, ok := mimeTypes.Load(extension); ok { + // We've already seen this extension. + // The file is in weight order, so we keep + // the first entry that we see. + continue + } + + setExtensionType(extension, fields[1]) + } + if err := scanner.Err(); err != nil { + panic(err) + } + return nil +} + func loadMimeFile(filename string) { f, err := os.Open(filename) if err != nil { @@ -50,12 +92,20 @@ func loadMimeFile(filename string) { } func initMimeUnix() { + for _, filename := range mimeGlobs { + if err := loadMimeGlobsFile(filename); err == nil { + return // Stop checking more files if mimetype database is found. + } + } + + // Fallback if no system-generated mimetype database exists. for _, filename := range typeFiles { loadMimeFile(filename) } } func initMimeForTests() map[string]string { + mimeGlobs = []string{""} typeFiles = []string{"testdata/test.types"} return map[string]string{ ".T1": "application/test", diff --git a/libgo/go/mime/type_unix_test.go b/libgo/go/mime/type_unix_test.go new file mode 100644 index 0000000..6e29882 --- /dev/null +++ b/libgo/go/mime/type_unix_test.go @@ -0,0 +1,39 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris +// +build aix darwin dragonfly freebsd js,wasm linux netbsd openbsd solaris + +package mime + +import ( + "testing" +) + +func initMimeUnixTest(t *testing.T) { + err := loadMimeGlobsFile("testdata/test.types.globs2") + if err != nil { + t.Fatal(err) + } + + loadMimeFile("testdata/test.types") +} + +func TestTypeByExtensionUNIX(t *testing.T) { + initMimeUnixTest(t) + typeTests := map[string]string{ + ".T1": "application/test", + ".t2": "text/test; charset=utf-8", + ".t3": "document/test", + ".t4": "example/test", + ".png": "image/png", + } + + for ext, want := range typeTests { + val := TypeByExtension(ext) + if val != want { + t.Errorf("TypeByExtension(%q) = %q, want %q", ext, val, want) + } + } +} diff --git a/libgo/go/net/addrselect.go b/libgo/go/net/addrselect.go index 6fb6baf..4603c55 100644 --- a/libgo/go/net/addrselect.go +++ b/libgo/go/net/addrselect.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris // Minimal RFC 6724 address selection. diff --git a/libgo/go/net/addrselect_test.go b/libgo/go/net/addrselect_test.go index a43ac5e..18784fe 100644 --- a/libgo/go/net/addrselect_test.go +++ b/libgo/go/net/addrselect_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build darwin dragonfly freebsd hurd linux netbsd openbsd solaris package net diff --git a/libgo/go/net/cgo_aix.go b/libgo/go/net/cgo_aix.go index 4f23d9b..577649f 100644 --- a/libgo/go/net/cgo_aix.go +++ b/libgo/go/net/cgo_aix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cgo && !netgo // +build cgo,!netgo package net diff --git a/libgo/go/net/cgo_android.go b/libgo/go/net/cgo_android.go index ab0368d..4b1a2e3 100644 --- a/libgo/go/net/cgo_android.go +++ b/libgo/go/net/cgo_android.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cgo && !netgo // +build cgo,!netgo package net diff --git a/libgo/go/net/cgo_bsd.go b/libgo/go/net/cgo_bsd.go index c1adf20..1268c89 100644 --- a/libgo/go/net/cgo_bsd.go +++ b/libgo/go/net/cgo_bsd.go @@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build cgo,!netgo +//go:build cgo && !netgo && (darwin || dragonfly || freebsd) +// +build cgo +// +build !netgo // +build darwin dragonfly freebsd package net diff --git a/libgo/go/net/cgo_linux.go b/libgo/go/net/cgo_linux.go index 36bac34..4b45dad 100644 --- a/libgo/go/net/cgo_linux.go +++ b/libgo/go/net/cgo_linux.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !android && cgo && !netgo // +build !android,cgo,!netgo package net diff --git a/libgo/go/net/cgo_netbsd.go b/libgo/go/net/cgo_netbsd.go index 1ce0139..e23899d 100644 --- a/libgo/go/net/cgo_netbsd.go +++ b/libgo/go/net/cgo_netbsd.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cgo && !netgo // +build cgo,!netgo package net diff --git a/libgo/go/net/cgo_openbsd.go b/libgo/go/net/cgo_openbsd.go index 4610246..3714793 100644 --- a/libgo/go/net/cgo_openbsd.go +++ b/libgo/go/net/cgo_openbsd.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cgo && !netgo // +build cgo,!netgo package net diff --git a/libgo/go/net/cgo_resnew.go b/libgo/go/net/cgo_resnew.go index 8bc1c1c..6611fd7 100644 --- a/libgo/go/net/cgo_resnew.go +++ b/libgo/go/net/cgo_resnew.go @@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build cgo,!netgo +//go:build cgo && !netgo && (aix || darwin || hurd || (linux && !android) || netbsd || solaris) +// +build cgo +// +build !netgo // +build aix darwin hurd linux,!android netbsd solaris package net diff --git a/libgo/go/net/cgo_resold.go b/libgo/go/net/cgo_resold.go index 8e13e41..33f664c 100644 --- a/libgo/go/net/cgo_resold.go +++ b/libgo/go/net/cgo_resold.go @@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build cgo,!netgo +//go:build cgo && !netgo && (android || freebsd || dragonfly || openbsd) +// +build cgo +// +build !netgo // +build android freebsd dragonfly openbsd package net diff --git a/libgo/go/net/cgo_socknew.go b/libgo/go/net/cgo_socknew.go index 9dcd158..84b40c9 100644 --- a/libgo/go/net/cgo_socknew.go +++ b/libgo/go/net/cgo_socknew.go @@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build cgo,!netgo +//go:build cgo && !netgo && (android || linux || solaris) +// +build cgo +// +build !netgo // +build android linux solaris package net diff --git a/libgo/go/net/cgo_sockold.go b/libgo/go/net/cgo_sockold.go index f514679..703b41b 100644 --- a/libgo/go/net/cgo_sockold.go +++ b/libgo/go/net/cgo_sockold.go @@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build cgo,!netgo +//go:build cgo && !netgo && (aix || darwin || dragonfly || freebsd || hurd || netbsd || openbsd) +// +build cgo +// +build !netgo // +build aix darwin dragonfly freebsd hurd netbsd openbsd package net diff --git a/libgo/go/net/cgo_solaris.go b/libgo/go/net/cgo_solaris.go index bd1e8f3..95d5db5 100644 --- a/libgo/go/net/cgo_solaris.go +++ b/libgo/go/net/cgo_solaris.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cgo && !netgo // +build cgo,!netgo package net diff --git a/libgo/go/net/cgo_stub.go b/libgo/go/net/cgo_stub.go index 041f8af..039e4be 100644 --- a/libgo/go/net/cgo_stub.go +++ b/libgo/go/net/cgo_stub.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !cgo || netgo // +build !cgo netgo package net diff --git a/libgo/go/net/cgo_unix.go b/libgo/go/net/cgo_unix.go index 0c9a488..462bf12 100644 --- a/libgo/go/net/cgo_unix.go +++ b/libgo/go/net/cgo_unix.go @@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build cgo,!netgo +//go:build cgo && !netgo && (aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris) +// +build cgo +// +build !netgo // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package net diff --git a/libgo/go/net/cgo_unix_test.go b/libgo/go/net/cgo_unix_test.go index e844ef5..98b3b4a 100644 --- a/libgo/go/net/cgo_unix_test.go +++ b/libgo/go/net/cgo_unix_test.go @@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build cgo,!netgo +//go:build cgo && !netgo && (aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris) +// +build cgo +// +build !netgo // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package net diff --git a/libgo/go/net/cgo_windows.go b/libgo/go/net/cgo_windows.go index 8968b75..1fd1f297 100644 --- a/libgo/go/net/cgo_windows.go +++ b/libgo/go/net/cgo_windows.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cgo && !netgo // +build cgo,!netgo package net diff --git a/libgo/go/net/conf.go b/libgo/go/net/conf.go index b0f1b79..fe7ebf1 100644 --- a/libgo/go/net/conf.go +++ b/libgo/go/net/conf.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package net diff --git a/libgo/go/net/conf_netcgo.go b/libgo/go/net/conf_netcgo.go index abc33ce..c705152 100644 --- a/libgo/go/net/conf_netcgo.go +++ b/libgo/go/net/conf_netcgo.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build netcgo // +build netcgo package net diff --git a/libgo/go/net/conf_test.go b/libgo/go/net/conf_test.go index a8e1807..f5e4d86 100644 --- a/libgo/go/net/conf_test.go +++ b/libgo/go/net/conf_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build darwin dragonfly freebsd hurd linux netbsd openbsd solaris package net diff --git a/libgo/go/net/conn_test.go b/libgo/go/net/conn_test.go index 771cabc..45e271c 100644 --- a/libgo/go/net/conn_test.go +++ b/libgo/go/net/conn_test.go @@ -5,6 +5,7 @@ // This file implements API tests across platforms and will never have a build // tag. +//go:build !js // +build !js package net diff --git a/libgo/go/net/dial.go b/libgo/go/net/dial.go index 13a312a..486ced0 100644 --- a/libgo/go/net/dial.go +++ b/libgo/go/net/dial.go @@ -344,6 +344,9 @@ type sysDialer struct { // // See func Dial for a description of the network and address // parameters. +// +// Dial uses context.Background internally; to specify the context, use +// DialContext. func (d *Dialer) Dial(network, address string) (Conn, error) { return d.DialContext(context.Background(), network, address) } @@ -701,6 +704,9 @@ type sysListener struct { // // See func Dial for a description of the network and address // parameters. +// +// Listen uses context.Background internally; to specify the context, use +// ListenConfig.Listen. func Listen(network, address string) (Listener, error) { var lc ListenConfig return lc.Listen(context.Background(), network, address) @@ -728,6 +734,9 @@ func Listen(network, address string) (Listener, error) { // // See func Dial for a description of the network and address // parameters. +// +// ListenPacket uses context.Background internally; to specify the context, use +// ListenConfig.ListenPacket. func ListenPacket(network, address string) (PacketConn, error) { var lc ListenConfig return lc.ListenPacket(context.Background(), network, address) diff --git a/libgo/go/net/dial_test.go b/libgo/go/net/dial_test.go index 57cf555..723038c 100644 --- a/libgo/go/net/dial_test.go +++ b/libgo/go/net/dial_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net @@ -154,40 +155,27 @@ func slowDialTCP(ctx context.Context, network string, laddr, raddr *TCPAddr) (*T return c, err } -func dialClosedPort(t *testing.T) (actual, expected time.Duration) { - // Estimate the expected time for this platform. - // On Windows, dialing a closed port takes roughly 1 second, - // but other platforms should be instantaneous. - if runtime.GOOS == "windows" { - expected = 1500 * time.Millisecond - } else if runtime.GOOS == "darwin" || runtime.GOOS == "ios" { - expected = 150 * time.Millisecond - } else { - expected = 95 * time.Millisecond - } +func dialClosedPort(t *testing.T) (dialLatency time.Duration) { + // On most platforms, dialing a closed port should be nearly instantaneous — + // less than a few hundred milliseconds. However, on some platforms it may be + // much slower: on Windows and OpenBSD, it has been observed to take up to a + // few seconds. l, err := Listen("tcp", "127.0.0.1:0") if err != nil { - t.Logf("dialClosedPort: Listen failed: %v", err) - return 999 * time.Hour, expected + t.Fatalf("dialClosedPort: Listen failed: %v", err) } addr := l.Addr().String() l.Close() - // On OpenBSD, interference from TestTCPSelfConnect is mysteriously - // causing the first attempt to hang for a few seconds, so we throw - // away the first result and keep the second. - for i := 1; ; i++ { - startTime := time.Now() - c, err := Dial("tcp", addr) - if err == nil { - c.Close() - } - elapsed := time.Now().Sub(startTime) - if i == 2 { - t.Logf("dialClosedPort: measured delay %v", elapsed) - return elapsed, expected - } + + startTime := time.Now() + c, err := Dial("tcp", addr) + if err == nil { + c.Close() } + elapsed := time.Now().Sub(startTime) + t.Logf("dialClosedPort: measured delay %v", elapsed) + return elapsed } func TestDialParallel(t *testing.T) { @@ -197,10 +185,7 @@ func TestDialParallel(t *testing.T) { t.Skip("both IPv4 and IPv6 are required") } - closedPortDelay, expectClosedPortDelay := dialClosedPort(t) - if closedPortDelay > expectClosedPortDelay { - t.Errorf("got %v; want <= %v", closedPortDelay, expectClosedPortDelay) - } + closedPortDelay := dialClosedPort(t) const instant time.Duration = 0 const fallbackDelay = 200 * time.Millisecond @@ -655,15 +640,7 @@ func TestDialerLocalAddr(t *testing.T) { } c, err := d.Dial(tt.network, addr) if err == nil && tt.error != nil || err != nil && tt.error == nil { - // A suspected kernel bug in macOS 10.12 occasionally results in - // timeout errors when dialing address ::1. The errors have not - // been observed on newer versions of the OS, so we don't plan to work - // around them. See https://golang.org/issue/22019. - if tt.raddr == "::1" && os.Getenv("GO_BUILDER_NAME") == "darwin-amd64-10_12" && os.IsTimeout(err) { - t.Logf("ignoring timeout error on Darwin; see https://golang.org/issue/22019") - } else { - t.Errorf("%s %v->%s: got %v; want %v", tt.network, tt.laddr, tt.raddr, err, tt.error) - } + t.Errorf("%s %v->%s: got %v; want %v", tt.network, tt.laddr, tt.raddr, err, tt.error) } if err != nil { if perr := parseDialError(err); perr != nil { @@ -682,10 +659,7 @@ func TestDialerDualStack(t *testing.T) { t.Skip("both IPv4 and IPv6 are required") } - closedPortDelay, expectClosedPortDelay := dialClosedPort(t) - if closedPortDelay > expectClosedPortDelay { - t.Errorf("got %v; want <= %v", closedPortDelay, expectClosedPortDelay) - } + closedPortDelay := dialClosedPort(t) origTestHookLookupIP := testHookLookupIP defer func() { testHookLookupIP = origTestHookLookupIP }() diff --git a/libgo/go/net/dial_unix_test.go b/libgo/go/net/dial_unix_test.go index 1891d8c..4b9bc27 100644 --- a/libgo/go/net/dial_unix_test.go +++ b/libgo/go/net/dial_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package net diff --git a/libgo/go/net/dnsclient.go b/libgo/go/net/dnsclient.go index e9c7384..1bbe396 100644 --- a/libgo/go/net/dnsclient.go +++ b/libgo/go/net/dnsclient.go @@ -5,6 +5,7 @@ package net import ( + "internal/itoa" "sort" "golang.org/x/net/dns/dnsmessage" @@ -33,7 +34,7 @@ func reverseaddr(addr string) (arpa string, err error) { return "", &DNSError{Err: "unrecognized address", Name: addr} } if ip.To4() != nil { - return uitoa(uint(ip[15])) + "." + uitoa(uint(ip[14])) + "." + uitoa(uint(ip[13])) + "." + uitoa(uint(ip[12])) + ".in-addr.arpa.", nil + return itoa.Uitoa(uint(ip[15])) + "." + itoa.Uitoa(uint(ip[14])) + "." + itoa.Uitoa(uint(ip[13])) + "." + itoa.Uitoa(uint(ip[12])) + ".in-addr.arpa.", nil } // Must be IPv6 buf := make([]byte, 0, len(ip)*4+len("ip6.arpa.")) diff --git a/libgo/go/net/dnsclient_unix.go b/libgo/go/net/dnsclient_unix.go index c5bfab9..a326319 100644 --- a/libgo/go/net/dnsclient_unix.go +++ b/libgo/go/net/dnsclient_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris // DNS client: see RFC 1035. @@ -17,6 +18,7 @@ package net import ( "context" "errors" + "internal/itoa" "io" "os" "sync" @@ -509,7 +511,7 @@ func (o hostLookupOrder) String() string { if s, ok := lookupOrderName[o]; ok { return s } - return "hostLookupOrder=" + itoa(int(o)) + "??" + return "hostLookupOrder=" + itoa.Itoa(int(o)) + "??" } // goLookupHost is the native Go implementation of LookupHost. @@ -530,7 +532,7 @@ func (r *Resolver) goLookupHostOrder(ctx context.Context, name string, order hos return } } - ips, _, err := r.goLookupIPCNAMEOrder(ctx, name, order) + ips, _, err := r.goLookupIPCNAMEOrder(ctx, "ip", name, order) if err != nil { return } @@ -556,13 +558,13 @@ func goLookupIPFiles(name string) (addrs []IPAddr) { // goLookupIP is the native Go implementation of LookupIP. // The libc versions are in cgo_*.go. -func (r *Resolver) goLookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) { +func (r *Resolver) goLookupIP(ctx context.Context, network, host string) (addrs []IPAddr, err error) { order := systemConf().hostLookupOrder(r, host) - addrs, _, err = r.goLookupIPCNAMEOrder(ctx, host, order) + addrs, _, err = r.goLookupIPCNAMEOrder(ctx, network, host, order) return } -func (r *Resolver) goLookupIPCNAMEOrder(ctx context.Context, name string, order hostLookupOrder) (addrs []IPAddr, cname dnsmessage.Name, err error) { +func (r *Resolver) goLookupIPCNAMEOrder(ctx context.Context, network, name string, order hostLookupOrder) (addrs []IPAddr, cname dnsmessage.Name, err error) { if order == hostLookupFilesDNS || order == hostLookupFiles { addrs = goLookupIPFiles(name) if len(addrs) > 0 || order == hostLookupFiles { @@ -583,7 +585,13 @@ func (r *Resolver) goLookupIPCNAMEOrder(ctx context.Context, name string, order error } lane := make(chan result, 1) - qtypes := [...]dnsmessage.Type{dnsmessage.TypeA, dnsmessage.TypeAAAA} + qtypes := []dnsmessage.Type{dnsmessage.TypeA, dnsmessage.TypeAAAA} + switch ipVersion(network) { + case '4': + qtypes = []dnsmessage.Type{dnsmessage.TypeA} + case '6': + qtypes = []dnsmessage.Type{dnsmessage.TypeAAAA} + } var queryFn func(fqdn string, qtype dnsmessage.Type) var responseFn func(fqdn string, qtype dnsmessage.Type) result if conf.singleRequest { @@ -728,7 +736,7 @@ func (r *Resolver) goLookupIPCNAMEOrder(ctx context.Context, name string, order // goLookupCNAME is the native Go (non-cgo) implementation of LookupCNAME. func (r *Resolver) goLookupCNAME(ctx context.Context, host string) (string, error) { order := systemConf().hostLookupOrder(r, host) - _, cname, err := r.goLookupIPCNAMEOrder(ctx, host, order) + _, cname, err := r.goLookupIPCNAMEOrder(ctx, "ip", host, order) return cname.String(), err } diff --git a/libgo/go/net/dnsclient_unix_test.go b/libgo/go/net/dnsclient_unix_test.go index 3c9ada3..ce1a4f3 100644 --- a/libgo/go/net/dnsclient_unix_test.go +++ b/libgo/go/net/dnsclient_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package net @@ -600,14 +601,14 @@ func TestGoLookupIPOrderFallbackToFile(t *testing.T) { name := fmt.Sprintf("order %v", order) // First ensure that we get an error when contacting a non-existent host. - _, _, err := r.goLookupIPCNAMEOrder(context.Background(), "notarealhost", order) + _, _, err := r.goLookupIPCNAMEOrder(context.Background(), "ip", "notarealhost", order) if err == nil { t.Errorf("%s: expected error while looking up name not in hosts file", name) continue } // Now check that we get an address when the name appears in the hosts file. - addrs, _, err := r.goLookupIPCNAMEOrder(context.Background(), "thor", order) // entry is in "testdata/hosts" + addrs, _, err := r.goLookupIPCNAMEOrder(context.Background(), "ip", "thor", order) // entry is in "testdata/hosts" if err != nil { t.Errorf("%s: expected to successfully lookup host entry", name) continue @@ -1845,6 +1846,17 @@ func TestCVE202133195(t *testing.T) { Target: dnsmessage.MustNewName("<html>.golang.org."), }, }, + dnsmessage.Resource{ + Header: dnsmessage.ResourceHeader{ + Name: n, + Type: dnsmessage.TypeSRV, + Class: dnsmessage.ClassINET, + Length: 4, + }, + Body: &dnsmessage.SRVResource{ + Target: dnsmessage.MustNewName("good.golang.org."), + }, + }, ) case dnsmessage.TypeMX: r.Answers = append(r.Answers, @@ -1859,6 +1871,17 @@ func TestCVE202133195(t *testing.T) { MX: dnsmessage.MustNewName("<html>.golang.org."), }, }, + dnsmessage.Resource{ + Header: dnsmessage.ResourceHeader{ + Name: dnsmessage.MustNewName("good.golang.org."), + Type: dnsmessage.TypeMX, + Class: dnsmessage.ClassINET, + Length: 4, + }, + Body: &dnsmessage.MXResource{ + MX: dnsmessage.MustNewName("good.golang.org."), + }, + }, ) case dnsmessage.TypeNS: r.Answers = append(r.Answers, @@ -1873,6 +1896,17 @@ func TestCVE202133195(t *testing.T) { NS: dnsmessage.MustNewName("<html>.golang.org."), }, }, + dnsmessage.Resource{ + Header: dnsmessage.ResourceHeader{ + Name: dnsmessage.MustNewName("good.golang.org."), + Type: dnsmessage.TypeNS, + Class: dnsmessage.ClassINET, + Length: 4, + }, + Body: &dnsmessage.NSResource{ + NS: dnsmessage.MustNewName("good.golang.org."), + }, + }, ) case dnsmessage.TypePTR: r.Answers = append(r.Answers, @@ -1887,6 +1921,17 @@ func TestCVE202133195(t *testing.T) { PTR: dnsmessage.MustNewName("<html>.golang.org."), }, }, + dnsmessage.Resource{ + Header: dnsmessage.ResourceHeader{ + Name: dnsmessage.MustNewName("good.golang.org."), + Type: dnsmessage.TypePTR, + Class: dnsmessage.ClassINET, + Length: 4, + }, + Body: &dnsmessage.PTRResource{ + PTR: dnsmessage.MustNewName("good.golang.org."), + }, + }, ) } return r, nil @@ -1902,57 +1947,177 @@ func TestCVE202133195(t *testing.T) { defer func(orig string) { testHookHostsPath = orig }(testHookHostsPath) testHookHostsPath = "testdata/hosts" - _, err := r.LookupCNAME(context.Background(), "golang.org") - if expected := "lookup golang.org: CNAME target is invalid"; err == nil || err.Error() != expected { - t.Errorf("Resolver.LookupCNAME returned unexpected error, got %q, want %q", err, expected) - } - _, err = LookupCNAME("golang.org") - if expected := "lookup golang.org: CNAME target is invalid"; err == nil || err.Error() != expected { - t.Errorf("LookupCNAME returned unexpected error, got %q, want %q", err, expected) - } - - _, _, 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) + tests := []struct { + name string + f func(*testing.T) + }{ + { + name: "CNAME", + f: func(t *testing.T) { + expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "golang.org"} + _, err := r.LookupCNAME(context.Background(), "golang.org") + if err.Error() != expectedErr.Error() { + t.Fatalf("unexpected error: %s", err) + } + _, err = LookupCNAME("golang.org") + if err.Error() != expectedErr.Error() { + t.Fatalf("unexpected error: %s", err) + } + }, + }, + { + name: "SRV (bad record)", + f: func(t *testing.T) { + expected := []*SRV{ + { + Target: "good.golang.org.", + }, + } + expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "golang.org"} + _, records, err := r.LookupSRV(context.Background(), "target", "tcp", "golang.org") + if err.Error() != expectedErr.Error() { + t.Fatalf("unexpected error: %s", err) + } + if !reflect.DeepEqual(records, expected) { + t.Error("Unexpected record set") + } + _, records, err = LookupSRV("target", "tcp", "golang.org") + if err.Error() != expectedErr.Error() { + t.Errorf("unexpected error: %s", err) + } + if !reflect.DeepEqual(records, expected) { + t.Error("Unexpected record set") + } + }, + }, + { + name: "SRV (bad header)", + f: func(t *testing.T) { + _, _, err := r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org.") + if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected { + t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected) + } + _, _, err = LookupSRV("hdr", "tcp", "golang.org.") + if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected { + t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected) + } + }, + }, + { + name: "MX", + f: func(t *testing.T) { + expected := []*MX{ + { + Host: "good.golang.org.", + }, + } + expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "golang.org"} + records, err := r.LookupMX(context.Background(), "golang.org") + if err.Error() != expectedErr.Error() { + t.Fatalf("unexpected error: %s", err) + } + if !reflect.DeepEqual(records, expected) { + t.Error("Unexpected record set") + } + records, err = LookupMX("golang.org") + if err.Error() != expectedErr.Error() { + t.Fatalf("unexpected error: %s", err) + } + if !reflect.DeepEqual(records, expected) { + t.Error("Unexpected record set") + } + }, + }, + { + name: "NS", + f: func(t *testing.T) { + expected := []*NS{ + { + Host: "good.golang.org.", + }, + } + expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "golang.org"} + records, err := r.LookupNS(context.Background(), "golang.org") + if err.Error() != expectedErr.Error() { + t.Fatalf("unexpected error: %s", err) + } + if !reflect.DeepEqual(records, expected) { + t.Error("Unexpected record set") + } + records, err = LookupNS("golang.org") + if err.Error() != expectedErr.Error() { + t.Fatalf("unexpected error: %s", err) + } + if !reflect.DeepEqual(records, expected) { + t.Error("Unexpected record set") + } + }, + }, + { + name: "Addr", + f: func(t *testing.T) { + expected := []string{"good.golang.org."} + expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "192.0.2.42"} + records, err := r.LookupAddr(context.Background(), "192.0.2.42") + if err.Error() != expectedErr.Error() { + t.Fatalf("unexpected error: %s", err) + } + if !reflect.DeepEqual(records, expected) { + t.Error("Unexpected record set") + } + records, err = LookupAddr("192.0.2.42") + if err.Error() != expectedErr.Error() { + t.Fatalf("unexpected error: %s", err) + } + if !reflect.DeepEqual(records, expected) { + t.Error("Unexpected record set") + } + }, + }, } - _, _, err = r.LookupSRV(context.Background(), "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) + for _, tc := range tests { + t.Run(tc.name, tc.f) } - _, 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) +func TestNullMX(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, + }, + Questions: q.Questions, + Answers: []dnsmessage.Resource{ + { + Header: dnsmessage.ResourceHeader{ + Name: q.Questions[0].Name, + Type: dnsmessage.TypeMX, + Class: dnsmessage.ClassINET, + }, + Body: &dnsmessage.MXResource{ + MX: dnsmessage.MustNewName("."), + }, + }, + }, + } + return r, nil + }, } - - _, 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) + r := Resolver{PreferGo: true, Dial: fake.DialContext} + rrset, err := r.LookupMX(context.Background(), "golang.org") + if err != nil { + t.Fatalf("LookupMX: %v", err) } - _, 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) + if want := []*MX{&MX{Host: "."}}; !reflect.DeepEqual(rrset, want) { + records := []string{} + for _, rr := range rrset { + records = append(records, fmt.Sprintf("%v", rr)) + } + t.Errorf("records = [%v]; want [%v]", strings.Join(records, " "), want[0]) } } diff --git a/libgo/go/net/dnsconfig_unix.go b/libgo/go/net/dnsconfig_unix.go index b76b32f..4b11602 100644 --- a/libgo/go/net/dnsconfig_unix.go +++ b/libgo/go/net/dnsconfig_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris // Read system DNS config from /etc/resolv.conf diff --git a/libgo/go/net/dnsconfig_unix_test.go b/libgo/go/net/dnsconfig_unix_test.go index f6edffc..59e21d6 100644 --- a/libgo/go/net/dnsconfig_unix_test.go +++ b/libgo/go/net/dnsconfig_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package net diff --git a/libgo/go/net/dnsname_test.go b/libgo/go/net/dnsname_test.go index 2964982..d851bf7 100644 --- a/libgo/go/net/dnsname_test.go +++ b/libgo/go/net/dnsname_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net diff --git a/libgo/go/net/error_posix.go b/libgo/go/net/error_posix.go index c13d5bc..017f2cb 100644 --- a/libgo/go/net/error_posix.go +++ b/libgo/go/net/error_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows package net diff --git a/libgo/go/net/error_posix_test.go b/libgo/go/net/error_posix_test.go index b411a37..ea52a45 100644 --- a/libgo/go/net/error_posix_test.go +++ b/libgo/go/net/error_posix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 // +build !plan9 package net diff --git a/libgo/go/net/error_test.go b/libgo/go/net/error_test.go index 556eb8c..c304390 100644 --- a/libgo/go/net/error_test.go +++ b/libgo/go/net/error_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net diff --git a/libgo/go/net/error_unix.go b/libgo/go/net/error_unix.go index 415e928..3de4e76 100644 --- a/libgo/go/net/error_unix.go +++ b/libgo/go/net/error_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || js || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js linux netbsd openbsd solaris package net diff --git a/libgo/go/net/error_unix_test.go b/libgo/go/net/error_unix_test.go index 9ce9e12..533a45e 100644 --- a/libgo/go/net/error_unix_test.go +++ b/libgo/go/net/error_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 && !windows // +build !plan9,!windows package net diff --git a/libgo/go/net/external_test.go b/libgo/go/net/external_test.go index f3c69c4..b8753cc 100644 --- a/libgo/go/net/external_test.go +++ b/libgo/go/net/external_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net diff --git a/libgo/go/net/fcntl_libc_test.go b/libgo/go/net/fcntl_libc_test.go new file mode 100644 index 0000000..02511c5 --- /dev/null +++ b/libgo/go/net/fcntl_libc_test.go @@ -0,0 +1,27 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || solaris +// +build aix darwin solaris + +package net + +import "syscall" + +// Use a helper function to call fcntl. This is defined in C in +// libgo/runtime. +//extern __go_fcntl_uintptr +func libc_fcntl(uintptr, uintptr, uintptr) (uintptr, uintptr) + +// Implemented in the syscall package. +//go:linkname fcntl syscall.fcntl +func fcntl(fd int, cmd int, arg int) (int, error) { + syscall.Entersyscall() + r, e := libc_fcntl(uintptr(fd), uintptr(cmd), uintptr(arg)) + syscall.Exitsyscall() + if e != 0 { + return int(r), syscall.Errno(e) + } + return int(r), nil +} diff --git a/libgo/go/net/fcntl_syscall_test.go b/libgo/go/net/fcntl_syscall_test.go new file mode 100644 index 0000000..59ba1a1 --- /dev/null +++ b/libgo/go/net/fcntl_syscall_test.go @@ -0,0 +1,27 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build dragonfly || freebsd || linux || netbsd || openbsd +// +build dragonfly freebsd linux netbsd openbsd + +package net + +import ( + "syscall" +) + +// Use a helper function to call fcntl. This is defined in C in +// libgo/runtime. +//extern __go_fcntl_uintptr +func libc_fcntl(uintptr, uintptr, uintptr) (uintptr, uintptr) + +func fcntl(fd int, cmd int, arg int) (int, error) { + syscall.Entersyscall() + r, e := libc_fcntl(uintptr(fd), uintptr(cmd), uintptr(arg)) + syscall.Exitsyscall() + if e != 0 { + return int(r), syscall.Errno(e) + } + return int(r), nil +} diff --git a/libgo/go/net/fd_posix.go b/libgo/go/net/fd_posix.go index b2f99bc..a0f1f5a 100644 --- a/libgo/go/net/fd_posix.go +++ b/libgo/go/net/fd_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows package net @@ -63,10 +64,10 @@ func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) { return n, sa, wrapSyscallError(readFromSyscallName, err) } -func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { - n, oobn, flags, sa, err = fd.pfd.ReadMsg(p, oob) +func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int, sa syscall.Sockaddr, err error) { + n, oobn, retflags, sa, err = fd.pfd.ReadMsg(p, oob, flags) runtime.KeepAlive(fd) - return n, oobn, flags, sa, wrapSyscallError(readMsgSyscallName, err) + return n, oobn, retflags, sa, wrapSyscallError(readMsgSyscallName, err) } func (fd *netFD) Write(p []byte) (nn int, err error) { diff --git a/libgo/go/net/fd_unix.go b/libgo/go/net/fd_unix.go index ad79c06..e2db165 100644 --- a/libgo/go/net/fd_unix.go +++ b/libgo/go/net/fd_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package net diff --git a/libgo/go/net/file_stub.go b/libgo/go/net/file_stub.go index bfb8100..9f988fe 100644 --- a/libgo/go/net/file_stub.go +++ b/libgo/go/net/file_stub.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package net diff --git a/libgo/go/net/file_test.go b/libgo/go/net/file_test.go index 8c09c0d..a70ef1b 100644 --- a/libgo/go/net/file_test.go +++ b/libgo/go/net/file_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net diff --git a/libgo/go/net/file_unix.go b/libgo/go/net/file_unix.go index 25caafb..d36a881 100644 --- a/libgo/go/net/file_unix.go +++ b/libgo/go/net/file_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package net diff --git a/libgo/go/net/hook_unix.go b/libgo/go/net/hook_unix.go index 780b23c..618c6c2 100644 --- a/libgo/go/net/hook_unix.go +++ b/libgo/go/net/hook_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package net diff --git a/libgo/go/net/hosts_test.go b/libgo/go/net/hosts_test.go index f850e2f..19c4399 100644 --- a/libgo/go/net/hosts_test.go +++ b/libgo/go/net/hosts_test.go @@ -36,7 +36,7 @@ var lookupStaticHostTests = []struct { }, }, { - "testdata/ipv4-hosts", // see golang.org/issue/8996 + "testdata/ipv4-hosts", []staticHostEntry{ {"localhost", []string{"127.0.0.1", "127.0.0.2", "127.0.0.3"}}, {"localhost.localdomain", []string{"127.0.0.3"}}, @@ -102,7 +102,7 @@ var lookupStaticAddrTests = []struct { }, }, { - "testdata/ipv4-hosts", // see golang.org/issue/8996 + "testdata/ipv4-hosts", []staticHostEntry{ {"127.0.0.1", []string{"localhost"}}, {"127.0.0.2", []string{"localhost"}}, diff --git a/libgo/go/net/http/cgi/integration_test.go b/libgo/go/net/http/cgi/integration_test.go index 76cbca8..ef2eaf7 100644 --- a/libgo/go/net/http/cgi/integration_test.go +++ b/libgo/go/net/http/cgi/integration_test.go @@ -95,12 +95,6 @@ func (w *limitWriter) Write(p []byte) (n int, err error) { func TestKillChildAfterCopyError(t *testing.T) { testenv.MustHaveExec(t) - defer func() { testHookStartProcess = nil }() - proc := make(chan *os.Process, 1) - testHookStartProcess = func(p *os.Process) { - proc <- p - } - h := &Handler{ Path: os.Args[0], Root: "/test.go", @@ -112,26 +106,9 @@ func TestKillChildAfterCopyError(t *testing.T) { const writeLen = 50 << 10 rw := &customWriterRecorder{&limitWriter{&out, writeLen}, rec} - donec := make(chan bool, 1) - go func() { - h.ServeHTTP(rw, req) - donec <- true - }() - - select { - case <-donec: - if out.Len() != writeLen || out.Bytes()[0] != 'a' { - t.Errorf("unexpected output: %q", out.Bytes()) - } - case <-time.After(5 * time.Second): - t.Errorf("timeout. ServeHTTP hung and didn't kill the child process?") - select { - case p := <-proc: - p.Kill() - t.Logf("killed process") - default: - t.Logf("didn't kill process") - } + h.ServeHTTP(rw, req) + if out.Len() != writeLen || out.Bytes()[0] != 'a' { + t.Errorf("unexpected output: %q", out.Bytes()) } } diff --git a/libgo/go/net/http/cgi/posix_test.go b/libgo/go/net/http/cgi/posix_test.go index 9396ce0..bc58ea9 100644 --- a/libgo/go/net/http/cgi/posix_test.go +++ b/libgo/go/net/http/cgi/posix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 // +build !plan9 package cgi diff --git a/libgo/go/net/http/client.go b/libgo/go/net/http/client.go index 88e2028..4d380c6 100644 --- a/libgo/go/net/http/client.go +++ b/libgo/go/net/http/client.go @@ -17,6 +17,7 @@ import ( "fmt" "io" "log" + "net/http/internal/ascii" "net/url" "reflect" "sort" @@ -432,8 +433,7 @@ func basicAuth(username, password string) string { // An error is returned if there were too many redirects or if there // was an HTTP protocol error. A non-2xx response doesn't cause an // error. Any returned error will be of type *url.Error. The url.Error -// value's Timeout method will report true if request timed out or was -// canceled. +// value's Timeout method will report true if the request timed out. // // When err is nil, resp always contains a non-nil resp.Body. // Caller should close resp.Body when done reading from it. @@ -442,6 +442,9 @@ func basicAuth(username, password string) string { // // To make a request with custom headers, use NewRequest and // DefaultClient.Do. +// +// To make a request with a specified context.Context, use NewRequestWithContext +// and DefaultClient.Do. func Get(url string) (resp *Response, err error) { return DefaultClient.Get(url) } @@ -466,6 +469,9 @@ func Get(url string) (resp *Response, err error) { // Caller should close resp.Body when done reading from it. // // To make a request with custom headers, use NewRequest and Client.Do. +// +// To make a request with a specified context.Context, use NewRequestWithContext +// and Client.Do. func (c *Client) Get(url string) (resp *Response, err error) { req, err := NewRequest("GET", url, nil) if err != nil { @@ -541,7 +547,10 @@ func urlErrorOp(method string) string { if method == "" { return "Get" } - return method[:1] + strings.ToLower(method[1:]) + if lowerMethod, ok := ascii.ToLower(method); ok { + return method[:1] + lowerMethod[1:] + } + return method } // Do sends an HTTP request and returns an HTTP response, following @@ -579,8 +588,7 @@ func urlErrorOp(method string) string { // standard library body types. // // Any returned error will be of type *url.Error. The url.Error -// value's Timeout method will report true if request timed out or was -// canceled. +// value's Timeout method will report true if the request timed out. func (c *Client) Do(req *Request) (*Response, error) { return c.do(req) } @@ -719,7 +727,6 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) { reqBodyClosed = true if !deadline.IsZero() && didTimeout() { err = &httpError{ - // TODO: early in cycle: s/Client.Timeout exceeded/timeout or context cancellation/ err: err.Error() + " (Client.Timeout exceeded while awaiting headers)", timeout: true, } @@ -821,6 +828,9 @@ func defaultCheckRedirect(req *Request, via []*Request) error { // // See the Client.Do method documentation for details on how redirects // are handled. +// +// To make a request with a specified context.Context, use NewRequestWithContext +// and DefaultClient.Do. func Post(url, contentType string, body io.Reader) (resp *Response, err error) { return DefaultClient.Post(url, contentType, body) } @@ -834,6 +844,9 @@ func Post(url, contentType string, body io.Reader) (resp *Response, err error) { // // To set custom headers, use NewRequest and Client.Do. // +// To make a request with a specified context.Context, use NewRequestWithContext +// and Client.Do. +// // See the Client.Do method documentation for details on how redirects // are handled. func (c *Client) Post(url, contentType string, body io.Reader) (resp *Response, err error) { @@ -858,6 +871,9 @@ func (c *Client) Post(url, contentType string, body io.Reader) (resp *Response, // // See the Client.Do method documentation for details on how redirects // are handled. +// +// To make a request with a specified context.Context, use NewRequestWithContext +// and DefaultClient.Do. func PostForm(url string, data url.Values) (resp *Response, err error) { return DefaultClient.PostForm(url, data) } @@ -873,6 +889,9 @@ func PostForm(url string, data url.Values) (resp *Response, err error) { // // See the Client.Do method documentation for details on how redirects // are handled. +// +// To make a request with a specified context.Context, use NewRequestWithContext +// and Client.Do. func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error) { return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) } @@ -888,6 +907,9 @@ func (c *Client) PostForm(url string, data url.Values) (resp *Response, err erro // 308 (Permanent Redirect) // // Head is a wrapper around DefaultClient.Head +// +// To make a request with a specified context.Context, use NewRequestWithContext +// and DefaultClient.Do. func Head(url string) (resp *Response, err error) { return DefaultClient.Head(url) } @@ -901,6 +923,9 @@ func Head(url string) (resp *Response, err error) { // 303 (See Other) // 307 (Temporary Redirect) // 308 (Permanent Redirect) +// +// To make a request with a specified context.Context, use NewRequestWithContext +// and Client.Do. func (c *Client) Head(url string) (resp *Response, err error) { req, err := NewRequest("HEAD", url, nil) if err != nil { @@ -926,7 +951,7 @@ func (c *Client) CloseIdleConnections() { } // cancelTimerBody is an io.ReadCloser that wraps rc with two features: -// 1) on Read error or close, the stop func is called. +// 1) On Read error or close, the stop func is called. // 2) On Read failure, if reqDidTimeout is true, the error is wrapped and // marked as net.Error that hit its timeout. type cancelTimerBody struct { diff --git a/libgo/go/net/http/client_test.go b/libgo/go/net/http/client_test.go index d90b484..01d605c 100644 --- a/libgo/go/net/http/client_test.go +++ b/libgo/go/net/http/client_test.go @@ -257,12 +257,12 @@ func TestClientRedirects(t *testing.T) { t.Fatalf("Get error: %v", err) } res.Body.Close() - finalUrl := res.Request.URL.String() + finalURL := res.Request.URL.String() if e, g := "<nil>", fmt.Sprintf("%v", err); e != g { t.Errorf("with custom client, expected error %q, got %q", e, g) } - if !strings.HasSuffix(finalUrl, "/?n=15") { - t.Errorf("expected final url to end in /?n=15; got url %q", finalUrl) + if !strings.HasSuffix(finalURL, "/?n=15") { + t.Errorf("expected final url to end in /?n=15; got url %q", finalURL) } if e, g := 15, len(lastVia); e != g { t.Errorf("expected lastVia to have contained %d elements; got %d", e, g) @@ -1945,7 +1945,7 @@ func TestClientDoCanceledVsTimeout_h2(t *testing.T) { } // Issue 33545: lock-in the behavior promised by Client.Do's -// docs about request cancelation vs timing out. +// docs about request cancellation vs timing out. func testClientDoCanceledVsTimeout(t *testing.T, h2 bool) { defer afterTest(t) cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { diff --git a/libgo/go/net/http/cookie.go b/libgo/go/net/http/cookie.go index 141bc94..ca2c1c2 100644 --- a/libgo/go/net/http/cookie.go +++ b/libgo/go/net/http/cookie.go @@ -7,6 +7,7 @@ package http import ( "log" "net" + "net/http/internal/ascii" "net/textproto" "strconv" "strings" @@ -93,15 +94,23 @@ func readSetCookies(h Header) []*Cookie { if j := strings.Index(attr, "="); j >= 0 { attr, val = attr[:j], attr[j+1:] } - lowerAttr := strings.ToLower(attr) + lowerAttr, isASCII := ascii.ToLower(attr) + if !isASCII { + continue + } val, ok = parseCookieValue(val, false) if !ok { c.Unparsed = append(c.Unparsed, parts[i]) continue } + switch lowerAttr { case "samesite": - lowerVal := strings.ToLower(val) + lowerVal, ascii := ascii.ToLower(val) + if !ascii { + c.SameSite = SameSiteDefaultMode + continue + } switch lowerVal { case "lax": c.SameSite = SameSiteLaxMode diff --git a/libgo/go/net/http/cookiejar/jar.go b/libgo/go/net/http/cookiejar/jar.go index 9f19917..e6583da 100644 --- a/libgo/go/net/http/cookiejar/jar.go +++ b/libgo/go/net/http/cookiejar/jar.go @@ -10,6 +10,7 @@ import ( "fmt" "net" "net/http" + "net/http/internal/ascii" "net/url" "sort" "strings" @@ -296,7 +297,6 @@ func (j *Jar) setCookies(u *url.URL, cookies []*http.Cookie, now time.Time) { // host name. func canonicalHost(host string) (string, error) { var err error - host = strings.ToLower(host) if hasPort(host) { host, _, err = net.SplitHostPort(host) if err != nil { @@ -307,7 +307,13 @@ func canonicalHost(host string) (string, error) { // Strip trailing dot from fully qualified domain names. host = host[:len(host)-1] } - return toASCII(host) + encoded, err := toASCII(host) + if err != nil { + return "", err + } + // We know this is ascii, no need to check. + lower, _ := ascii.ToLower(encoded) + return lower, nil } // hasPort reports whether host contains a port number. host may be a host @@ -469,7 +475,12 @@ func (j *Jar) domainAndType(host, domain string) (string, bool, error) { // both are illegal. return "", false, errMalformedDomain } - domain = strings.ToLower(domain) + + domain, isASCII := ascii.ToLower(domain) + if !isASCII { + // Received non-ASCII domain, e.g. "perché.com" instead of "xn--perch-fsa.com" + return "", false, errMalformedDomain + } if domain[len(domain)-1] == '.' { // We received stuff like "Domain=www.example.com.". diff --git a/libgo/go/net/http/cookiejar/punycode.go b/libgo/go/net/http/cookiejar/punycode.go index a9cc666..c7f438d 100644 --- a/libgo/go/net/http/cookiejar/punycode.go +++ b/libgo/go/net/http/cookiejar/punycode.go @@ -8,6 +8,7 @@ package cookiejar import ( "fmt" + "net/http/internal/ascii" "strings" "unicode/utf8" ) @@ -133,12 +134,12 @@ const acePrefix = "xn--" // toASCII("bücher.example.com") is "xn--bcher-kva.example.com", and // toASCII("golang") is "golang". func toASCII(s string) (string, error) { - if ascii(s) { + if ascii.Is(s) { return s, nil } labels := strings.Split(s, ".") for i, label := range labels { - if !ascii(label) { + if !ascii.Is(label) { a, err := encode(acePrefix, label) if err != nil { return "", err @@ -148,12 +149,3 @@ func toASCII(s string) (string, error) { } return strings.Join(labels, "."), nil } - -func ascii(s string) bool { - for i := 0; i < len(s); i++ { - if s[i] >= utf8.RuneSelf { - return false - } - } - return true -} diff --git a/libgo/go/net/http/example_test.go b/libgo/go/net/http/example_test.go index c677d52..2f411d1 100644 --- a/libgo/go/net/http/example_test.go +++ b/libgo/go/net/http/example_test.go @@ -45,12 +45,15 @@ func ExampleGet() { if err != nil { log.Fatal(err) } - robots, err := io.ReadAll(res.Body) + body, err := io.ReadAll(res.Body) res.Body.Close() + if res.StatusCode > 299 { + log.Fatalf("Response failed with status code: %d and\nbody: %s\n", res.StatusCode, body) + } if err != nil { log.Fatal(err) } - fmt.Printf("%s", robots) + fmt.Printf("%s", body) } func ExampleFileServer() { diff --git a/libgo/go/net/http/fcgi/child.go b/libgo/go/net/http/fcgi/child.go index 756722b..dc82bf7 100644 --- a/libgo/go/net/http/fcgi/child.go +++ b/libgo/go/net/http/fcgi/child.go @@ -16,7 +16,6 @@ import ( "net/http/cgi" "os" "strings" - "sync" "time" ) @@ -154,7 +153,6 @@ type child struct { conn *conn handler http.Handler - mu sync.Mutex // protects requests: requests map[uint16]*request // keyed by request ID } @@ -193,9 +191,7 @@ var ErrRequestAborted = errors.New("fcgi: request aborted by web server") var ErrConnClosed = errors.New("fcgi: connection to web server closed") func (c *child) handleRecord(rec *record) error { - c.mu.Lock() req, ok := c.requests[rec.h.Id] - c.mu.Unlock() if !ok && rec.h.Type != typeBeginRequest && rec.h.Type != typeGetValues { // The spec says to ignore unknown request IDs. return nil @@ -218,9 +214,7 @@ func (c *child) handleRecord(rec *record) error { return nil } req = newRequest(rec.h.Id, br.flags) - c.mu.Lock() c.requests[rec.h.Id] = req - c.mu.Unlock() return nil case typeParams: // NOTE(eds): Technically a key-value pair can straddle the boundary @@ -248,8 +242,11 @@ func (c *child) handleRecord(rec *record) error { // TODO(eds): This blocks until the handler reads from the pipe. // If the handler takes a long time, it might be a problem. req.pw.Write(content) - } else if req.pw != nil { - req.pw.Close() + } else { + delete(c.requests, req.reqId) + if req.pw != nil { + req.pw.Close() + } } return nil case typeGetValues: @@ -260,9 +257,7 @@ func (c *child) handleRecord(rec *record) error { // If the filter role is implemented, read the data stream here. return nil case typeAbortRequest: - c.mu.Lock() delete(c.requests, rec.h.Id) - c.mu.Unlock() c.conn.writeEndRequest(rec.h.Id, 0, statusRequestComplete) if req.pw != nil { req.pw.CloseWithError(ErrRequestAborted) @@ -309,9 +304,6 @@ func (c *child) serveRequest(req *request, body io.ReadCloser) { // Make sure we serve something even if nothing was written to r r.Write(nil) r.Close() - c.mu.Lock() - delete(c.requests, req.reqId) - c.mu.Unlock() c.conn.writeEndRequest(req.reqId, 0, statusRequestComplete) // Consume the entire body, so the host isn't still writing to @@ -330,8 +322,6 @@ func (c *child) serveRequest(req *request, body io.ReadCloser) { } func (c *child) cleanUp() { - c.mu.Lock() - defer c.mu.Unlock() for _, req := range c.requests { if req.pw != nil { // race with call to Close in c.serveRequest doesn't matter because diff --git a/libgo/go/net/http/fcgi/fcgi_test.go b/libgo/go/net/http/fcgi/fcgi_test.go index b58111d..5888783 100644 --- a/libgo/go/net/http/fcgi/fcgi_test.go +++ b/libgo/go/net/http/fcgi/fcgi_test.go @@ -11,6 +11,7 @@ import ( "net/http" "strings" "testing" + "time" ) var sizeTests = []struct { @@ -399,3 +400,55 @@ func TestResponseWriterSniffsContentType(t *testing.T) { }) } } + +type signallingNopCloser struct { + io.Reader + closed chan bool +} + +func (*signallingNopCloser) Write(buf []byte) (int, error) { + return len(buf), nil +} + +func (rc *signallingNopCloser) Close() error { + close(rc.closed) + return nil +} + +// Test whether server properly closes connection when processing slow +// requests +func TestSlowRequest(t *testing.T) { + pr, pw := io.Pipe() + go func(w io.Writer) { + for _, buf := range [][]byte{ + streamBeginTypeStdin, + makeRecord(typeStdin, 1, nil), + } { + pw.Write(buf) + time.Sleep(100 * time.Millisecond) + } + }(pw) + + rc := &signallingNopCloser{pr, make(chan bool)} + handlerDone := make(chan bool) + + c := newChild(rc, http.HandlerFunc(func( + w http.ResponseWriter, + r *http.Request, + ) { + w.WriteHeader(200) + close(handlerDone) + })) + go c.serve() + defer c.cleanUp() + + timeout := time.After(2 * time.Second) + + <-handlerDone + select { + case <-rc.closed: + t.Log("FastCGI child closed connection") + case <-timeout: + t.Error("FastCGI child did not close socket after handling request") + } +} diff --git a/libgo/go/net/http/filetransport_test.go b/libgo/go/net/http/filetransport_test.go index b58888d..77fc8ee 100644 --- a/libgo/go/net/http/filetransport_test.go +++ b/libgo/go/net/http/filetransport_test.go @@ -23,12 +23,10 @@ func checker(t *testing.T) func(string, error) { func TestFileTransport(t *testing.T) { check := checker(t) - dname, err := os.MkdirTemp("", "") - check("TempDir", err) + dname := t.TempDir() fname := filepath.Join(dname, "foo.txt") - err = os.WriteFile(fname, []byte("Bar"), 0644) + err := os.WriteFile(fname, []byte("Bar"), 0644) check("WriteFile", err) - defer os.Remove(dname) defer os.Remove(fname) tr := &Transport{} diff --git a/libgo/go/net/http/fs.go b/libgo/go/net/http/fs.go index a28ae85..57e731e 100644 --- a/libgo/go/net/http/fs.go +++ b/libgo/go/net/http/fs.go @@ -46,7 +46,7 @@ type Dir string // to a possibly better non-nil error. In particular, it turns OS-specific errors // about opening files in non-directories into fs.ErrNotExist. See Issue 18984. func mapDirOpenError(originalErr error, name string) error { - if os.IsNotExist(originalErr) || os.IsPermission(originalErr) { + if errors.Is(originalErr, fs.ErrNotExist) || errors.Is(originalErr, fs.ErrPermission) { return originalErr } @@ -670,10 +670,10 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec // and historically Go's ServeContent always returned just "404 Not Found" for // all errors. We don't want to start leaking information in error messages. func toHTTPError(err error) (msg string, httpStatus int) { - if os.IsNotExist(err) { + if errors.Is(err, fs.ErrNotExist) { return "404 page not found", StatusNotFound } - if os.IsPermission(err) { + if errors.Is(err, fs.ErrPermission) { return "403 Forbidden", StatusForbidden } // Default: diff --git a/libgo/go/net/http/fs_test.go b/libgo/go/net/http/fs_test.go index 2499051..b42ade1 100644 --- a/libgo/go/net/http/fs_test.go +++ b/libgo/go/net/http/fs_test.go @@ -11,7 +11,6 @@ import ( "fmt" "io" "io/fs" - "io/ioutil" "mime" "mime/multipart" "net" @@ -379,11 +378,7 @@ func mustRemoveAll(dir string) { func TestFileServerImplicitLeadingSlash(t *testing.T) { defer afterTest(t) - tempDir, err := os.MkdirTemp("", "") - if err != nil { - t.Fatalf("TempDir: %v", err) - } - defer mustRemoveAll(tempDir) + tempDir := t.TempDir() if err := os.WriteFile(filepath.Join(tempDir, "foo.txt"), []byte("Hello world"), 0644); err != nil { t.Fatalf("WriteFile: %v", err) } @@ -593,7 +588,7 @@ func TestServeIndexHtml(t *testing.T) { if err != nil { t.Fatal(err) } - b, err := ioutil.ReadAll(res.Body) + b, err := io.ReadAll(res.Body) if err != nil { t.Fatal("reading Body:", err) } @@ -1270,16 +1265,18 @@ func TestFileServerNotDirError(t *testing.T) { if err == nil { t.Fatal("err == nil; want != nil") } - if !os.IsNotExist(err) { - t.Errorf("err = %v; os.IsNotExist(err) = %v; want true", err, os.IsNotExist(err)) + if !errors.Is(err, fs.ErrNotExist) { + t.Errorf("err = %v; errors.Is(err, fs.ErrNotExist) = %v; want true", err, + errors.Is(err, fs.ErrNotExist)) } _, err = dir.Open("/index.html/not-a-dir/not-a-file") if err == nil { t.Fatal("err == nil; want != nil") } - if !os.IsNotExist(err) { - t.Errorf("err = %v; os.IsNotExist(err) = %v; want true", err, os.IsNotExist(err)) + if !errors.Is(err, fs.ErrNotExist) { + t.Errorf("err = %v; errors.Is(err, fs.ErrNotExist) = %v; want true", err, + errors.Is(err, fs.ErrNotExist)) } }) } diff --git a/libgo/go/net/http/h2_bundle.go b/libgo/go/net/http/h2_bundle.go index e13c661..0e5fbf8 100644 --- a/libgo/go/net/http/h2_bundle.go +++ b/libgo/go/net/http/h2_bundle.go @@ -1,3 +1,4 @@ +//go:build !nethttpomithttp2 // +build !nethttpomithttp2 // Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT. @@ -52,6 +53,48 @@ import ( "golang.org/x/net/idna" ) +// asciiEqualFold is strings.EqualFold, ASCII only. It reports whether s and t +// are equal, ASCII-case-insensitively. +func http2asciiEqualFold(s, t string) bool { + if len(s) != len(t) { + return false + } + for i := 0; i < len(s); i++ { + if http2lower(s[i]) != http2lower(t[i]) { + return false + } + } + return true +} + +// lower returns the ASCII lowercase version of b. +func http2lower(b byte) byte { + if 'A' <= b && b <= 'Z' { + return b + ('a' - 'A') + } + return b +} + +// isASCIIPrint returns whether s is ASCII and printable according to +// https://tools.ietf.org/html/rfc20#section-4.2. +func http2isASCIIPrint(s string) bool { + for i := 0; i < len(s); i++ { + if s[i] < ' ' || s[i] > '~' { + return false + } + } + return true +} + +// asciiToLower returns the lowercase version of s if s is ASCII and printable, +// and whether or not it was. +func http2asciiToLower(s string) (lower string, ok bool) { + if !http2isASCIIPrint(s) { + return "", false + } + return strings.ToLower(s), true +} + // A list of the possible cipher suite ids. Taken from // https://www.iana.org/assignments/tls-parameters/tls-parameters.txt @@ -754,61 +797,69 @@ func (p *http2clientConnPool) getClientConn(req *Request, addr string, dialOnMis // It gets its own connection. http2traceGetConn(req, addr) const singleUse = true - cc, err := p.t.dialClientConn(addr, singleUse) + cc, err := p.t.dialClientConn(req.Context(), addr, singleUse) if err != nil { return nil, err } return cc, nil } - p.mu.Lock() - for _, cc := range p.conns[addr] { - if st := cc.idleState(); st.canTakeNewRequest { - if p.shouldTraceGetConn(st) { - http2traceGetConn(req, addr) + for { + p.mu.Lock() + for _, cc := range p.conns[addr] { + if st := cc.idleState(); st.canTakeNewRequest { + if p.shouldTraceGetConn(st) { + http2traceGetConn(req, addr) + } + p.mu.Unlock() + return cc, nil } + } + if !dialOnMiss { p.mu.Unlock() - return cc, nil + return nil, http2ErrNoCachedConn } - } - if !dialOnMiss { + http2traceGetConn(req, addr) + call := p.getStartDialLocked(req.Context(), addr) p.mu.Unlock() - return nil, http2ErrNoCachedConn + <-call.done + if http2shouldRetryDial(call, req) { + continue + } + return call.res, call.err } - http2traceGetConn(req, addr) - call := p.getStartDialLocked(addr) - p.mu.Unlock() - <-call.done - return call.res, call.err } // dialCall is an in-flight Transport dial call to a host. type http2dialCall struct { - _ http2incomparable - p *http2clientConnPool + _ http2incomparable + p *http2clientConnPool + // the context associated with the request + // that created this dialCall + ctx context.Context done chan struct{} // closed when done res *http2ClientConn // valid after done is closed err error // valid after done is closed } // requires p.mu is held. -func (p *http2clientConnPool) getStartDialLocked(addr string) *http2dialCall { +func (p *http2clientConnPool) getStartDialLocked(ctx context.Context, addr string) *http2dialCall { if call, ok := p.dialing[addr]; ok { // A dial is already in-flight. Don't start another. return call } - call := &http2dialCall{p: p, done: make(chan struct{})} + call := &http2dialCall{p: p, done: make(chan struct{}), ctx: ctx} if p.dialing == nil { p.dialing = make(map[string]*http2dialCall) } p.dialing[addr] = call - go call.dial(addr) + go call.dial(call.ctx, addr) return call } // run in its own goroutine. -func (c *http2dialCall) dial(addr string) { +func (c *http2dialCall) dial(ctx context.Context, addr string) { const singleUse = false // shared conn - c.res, c.err = c.p.t.dialClientConn(addr, singleUse) + c.res, c.err = c.p.t.dialClientConn(ctx, addr, singleUse) close(c.done) c.p.mu.Lock() @@ -953,6 +1004,31 @@ func (p http2noDialClientConnPool) GetClientConn(req *Request, addr string) (*ht return p.getClientConn(req, addr, http2noDialOnMiss) } +// shouldRetryDial reports whether the current request should +// retry dialing after the call finished unsuccessfully, for example +// if the dial was canceled because of a context cancellation or +// deadline expiry. +func http2shouldRetryDial(call *http2dialCall, req *Request) bool { + if call.err == nil { + // No error, no need to retry + return false + } + if call.ctx == req.Context() { + // If the call has the same context as the request, the dial + // should not be retried, since any cancellation will have come + // from this request. + return false + } + if !errors.Is(call.err, context.Canceled) && !errors.Is(call.err, context.DeadlineExceeded) { + // If the call error is not because of a context cancellation or a deadline expiry, + // the dial should not be retried. + return false + } + // Only retry if the error is a context cancellation error or deadline expiry + // and the context associated with the call was canceled or expired. + return call.ctx.Err() != nil +} + // Buffer chunks are allocated from a pool to reduce pressure on GC. // The maximum wasted space per dataBuffer is 2x the largest size class, // which happens when the dataBuffer has multiple chunks and there is @@ -2873,6 +2949,20 @@ func http2traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textpr return nil } +// dialTLSWithContext uses tls.Dialer, added in Go 1.15, to open a TLS +// connection. +func (t *http2Transport) dialTLSWithContext(ctx context.Context, network, addr string, cfg *tls.Config) (*tls.Conn, error) { + dialer := &tls.Dialer{ + Config: cfg, + } + cn, err := dialer.DialContext(ctx, network, addr) + if err != nil { + return nil, err + } + tlsCn := cn.(*tls.Conn) // DialContext comment promises this will always succeed + return tlsCn, nil +} + var http2DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1" type http2goroutineLock uint64 @@ -3094,12 +3184,12 @@ func http2buildCommonHeaderMaps() { } } -func http2lowerHeader(v string) string { +func http2lowerHeader(v string) (lower string, ascii bool) { http2buildCommonHeaderMapsOnce() if s, ok := http2commonLowerHeader[v]; ok { - return s + return s, true } - return strings.ToLower(v) + return http2asciiToLower(v) } var ( @@ -3797,13 +3887,12 @@ func http2ConfigureServer(s *Server, conf *http2Server) error { if s.TLSConfig == nil { s.TLSConfig = new(tls.Config) - } else if s.TLSConfig.CipherSuites != nil { - // If they already provided a CipherSuite list, return - // an error if it has a bad order or is missing - // ECDHE_RSA_WITH_AES_128_GCM_SHA256 or ECDHE_ECDSA_WITH_AES_128_GCM_SHA256. + } else if s.TLSConfig.CipherSuites != nil && s.TLSConfig.MinVersion < tls.VersionTLS13 { + // If they already provided a TLS 1.0–1.2 CipherSuite list, return an + // error if it is missing ECDHE_RSA_WITH_AES_128_GCM_SHA256 or + // ECDHE_ECDSA_WITH_AES_128_GCM_SHA256. haveRequired := false - sawBad := false - for i, cs := range s.TLSConfig.CipherSuites { + for _, cs := range s.TLSConfig.CipherSuites { switch cs { case tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, // Alternative MTI cipher to not discourage ECDSA-only servers. @@ -3811,14 +3900,9 @@ func http2ConfigureServer(s *Server, conf *http2Server) error { tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: haveRequired = true } - if http2isBadCipher(cs) { - sawBad = true - } else if sawBad { - return fmt.Errorf("http2: TLSConfig.CipherSuites index %d contains an HTTP/2-approved cipher suite (%#04x), but it comes after unapproved cipher suites. With this configuration, clients that don't support previous, approved cipher suites may be given an unapproved one and reject the connection.", i, cs) - } } if !haveRequired { - return fmt.Errorf("http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher (need at least one of TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 or TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256).") + return fmt.Errorf("http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher (need at least one of TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 or TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)") } } @@ -4864,7 +4948,9 @@ func (sc *http2serverConn) startGracefulShutdown() { sc.shutdownOnce.Do(func() { sc.sendServeMsg(http2gracefulShutdownMsg) }) } -// After sending GOAWAY, the connection will close after goAwayTimeout. +// After sending GOAWAY with an error code (non-graceful shutdown), the +// connection will close after goAwayTimeout. +// // If we close the connection immediately after sending GOAWAY, there may // be unsent data in our kernel receive buffer, which will cause the kernel // to send a TCP RST on close() instead of a FIN. This RST will abort the @@ -5200,23 +5286,37 @@ func (sc *http2serverConn) processSettingInitialWindowSize(val uint32) error { func (sc *http2serverConn) processData(f *http2DataFrame) error { sc.serveG.check() - if sc.inGoAway && sc.goAwayCode != http2ErrCodeNo { + id := f.Header().StreamID + if sc.inGoAway && (sc.goAwayCode != http2ErrCodeNo || id > sc.maxClientStreamID) { + // Discard all DATA frames if the GOAWAY is due to an + // error, or: + // + // Section 6.8: After sending a GOAWAY frame, the sender + // can discard frames for streams initiated by the + // receiver with identifiers higher than the identified + // last stream. return nil } - data := f.Data() - // "If a DATA frame is received whose stream is not in "open" - // or "half closed (local)" state, the recipient MUST respond - // with a stream error (Section 5.4.2) of type STREAM_CLOSED." - id := f.Header().StreamID + data := f.Data() state, st := sc.state(id) if id == 0 || state == http2stateIdle { + // Section 6.1: "DATA frames MUST be associated with a + // stream. If a DATA frame is received whose stream + // identifier field is 0x0, the recipient MUST respond + // with a connection error (Section 5.4.1) of type + // PROTOCOL_ERROR." + // // Section 5.1: "Receiving any frame other than HEADERS // or PRIORITY on a stream in this state MUST be // treated as a connection error (Section 5.4.1) of // type PROTOCOL_ERROR." return http2ConnectionError(http2ErrCodeProtocol) } + + // "If a DATA frame is received whose stream is not in "open" + // or "half closed (local)" state, the recipient MUST respond + // with a stream error (Section 5.4.2) of type STREAM_CLOSED." if st == nil || state != http2stateOpen || st.gotTrailerHeader || st.resetQueued { // This includes sending a RST_STREAM if the stream is // in stateHalfClosedLocal (which currently means that @@ -6344,8 +6444,12 @@ func (w *http2responseWriter) Push(target string, opts *PushOptions) error { // but PUSH_PROMISE requests cannot have a body. // http://tools.ietf.org/html/rfc7540#section-8.2 // Also disallow Host, since the promised URL must be absolute. - switch strings.ToLower(k) { - case "content-length", "content-encoding", "trailer", "te", "expect", "host": + if http2asciiEqualFold(k, "content-length") || + http2asciiEqualFold(k, "content-encoding") || + http2asciiEqualFold(k, "trailer") || + http2asciiEqualFold(k, "te") || + http2asciiEqualFold(k, "expect") || + http2asciiEqualFold(k, "host") { return fmt.Errorf("promised request headers cannot include %q", k) } } @@ -7067,12 +7171,12 @@ func http2canRetryError(err error) bool { return false } -func (t *http2Transport) dialClientConn(addr string, singleUse bool) (*http2ClientConn, error) { +func (t *http2Transport) dialClientConn(ctx context.Context, addr string, singleUse bool) (*http2ClientConn, error) { host, _, err := net.SplitHostPort(addr) if err != nil { return nil, err } - tconn, err := t.dialTLS()("tcp", addr, t.newTLSConfig(host)) + tconn, err := t.dialTLS(ctx)("tcp", addr, t.newTLSConfig(host)) if err != nil { return nil, err } @@ -7093,34 +7197,24 @@ func (t *http2Transport) newTLSConfig(host string) *tls.Config { return cfg } -func (t *http2Transport) dialTLS() func(string, string, *tls.Config) (net.Conn, error) { +func (t *http2Transport) dialTLS(ctx context.Context) func(string, string, *tls.Config) (net.Conn, error) { if t.DialTLS != nil { return t.DialTLS } - return t.dialTLSDefault -} - -func (t *http2Transport) dialTLSDefault(network, addr string, cfg *tls.Config) (net.Conn, error) { - cn, err := tls.Dial(network, addr, cfg) - if err != nil { - return nil, err - } - if err := cn.Handshake(); err != nil { - return nil, err - } - if !cfg.InsecureSkipVerify { - if err := cn.VerifyHostname(cfg.ServerName); err != nil { + return func(network, addr string, cfg *tls.Config) (net.Conn, error) { + tlsCn, err := t.dialTLSWithContext(ctx, network, addr, cfg) + if err != nil { return nil, err } + state := tlsCn.ConnectionState() + if p := state.NegotiatedProtocol; p != http2NextProtoTLS { + return nil, fmt.Errorf("http2: unexpected ALPN protocol %q; want %q", p, http2NextProtoTLS) + } + if !state.NegotiatedProtocolIsMutual { + return nil, errors.New("http2: could not negotiate protocol mutually") + } + return tlsCn, nil } - state := cn.ConnectionState() - if p := state.NegotiatedProtocol; p != http2NextProtoTLS { - return nil, fmt.Errorf("http2: unexpected ALPN protocol %q; want %q", p, http2NextProtoTLS) - } - if !state.NegotiatedProtocolIsMutual { - return nil, errors.New("http2: could not negotiate protocol mutually") - } - return cn, nil } // disableKeepAlives reports whether connections should be closed as @@ -7508,7 +7602,7 @@ func http2checkConnHeaders(req *Request) error { if vv := req.Header["Transfer-Encoding"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "chunked") { return fmt.Errorf("http2: invalid Transfer-Encoding request header: %q", vv) } - if vv := req.Header["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && !strings.EqualFold(vv[0], "close") && !strings.EqualFold(vv[0], "keep-alive")) { + if vv := req.Header["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && !http2asciiEqualFold(vv[0], "close") && !http2asciiEqualFold(vv[0], "keep-alive")) { return fmt.Errorf("http2: invalid Connection request header: %q", vv) } return nil @@ -8049,19 +8143,21 @@ func (cc *http2ClientConn) encodeHeaders(req *Request, addGzipHeader bool, trail var didUA bool for k, vv := range req.Header { - if strings.EqualFold(k, "host") || strings.EqualFold(k, "content-length") { + if http2asciiEqualFold(k, "host") || http2asciiEqualFold(k, "content-length") { // Host is :authority, already sent. // Content-Length is automatic, set below. continue - } else if strings.EqualFold(k, "connection") || strings.EqualFold(k, "proxy-connection") || - strings.EqualFold(k, "transfer-encoding") || strings.EqualFold(k, "upgrade") || - strings.EqualFold(k, "keep-alive") { + } else if http2asciiEqualFold(k, "connection") || + http2asciiEqualFold(k, "proxy-connection") || + http2asciiEqualFold(k, "transfer-encoding") || + http2asciiEqualFold(k, "upgrade") || + http2asciiEqualFold(k, "keep-alive") { // Per 8.1.2.2 Connection-Specific Header // Fields, don't send connection-specific // fields. We have already checked if any // are error-worthy so just ignore the rest. continue - } else if strings.EqualFold(k, "user-agent") { + } else if http2asciiEqualFold(k, "user-agent") { // Match Go's http1 behavior: at most one // User-Agent. If set to nil or empty string, // then omit it. Otherwise if not mentioned, @@ -8074,7 +8170,7 @@ func (cc *http2ClientConn) encodeHeaders(req *Request, addGzipHeader bool, trail if vv[0] == "" { continue } - } else if strings.EqualFold(k, "cookie") { + } else if http2asciiEqualFold(k, "cookie") { // Per 8.1.2.5 To allow for better compression efficiency, the // Cookie header field MAY be split into separate header fields, // each with one or more cookie-pairs. @@ -8133,7 +8229,12 @@ func (cc *http2ClientConn) encodeHeaders(req *Request, addGzipHeader bool, trail // Header list size is ok. Write the headers. enumerateHeaders(func(name, value string) { - name = strings.ToLower(name) + name, ascii := http2asciiToLower(name) + if !ascii { + // Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header + // field names have to be ASCII characters (just as in HTTP/1.x). + return + } cc.writeHeader(name, value) if traceHeaders { http2traceWroteHeaderField(trace, name, value) @@ -8181,9 +8282,14 @@ func (cc *http2ClientConn) encodeTrailers(req *Request) ([]byte, error) { } for k, vv := range req.Trailer { + lowKey, ascii := http2asciiToLower(k) + if !ascii { + // Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header + // field names have to be ASCII characters (just as in HTTP/1.x). + continue + } // Transfer-Encoding, etc.. have already been filtered at the // start of RoundTrip - lowKey := strings.ToLower(k) for _, v := range vv { cc.writeHeader(lowKey, v) } @@ -9606,7 +9712,12 @@ func http2encodeHeaders(enc *hpack.Encoder, h Header, keys []string) { } for _, k := range keys { vv := h[k] - k = http2lowerHeader(k) + k, ascii := http2lowerHeader(k) + if !ascii { + // Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header + // field names have to be ASCII characters (just as in HTTP/1.x). + continue + } if !http2validWireHeaderFieldName(k) { // Skip it as backup paranoia. Per // golang.org/issue/14048, these should diff --git a/libgo/go/net/http/header.go b/libgo/go/net/http/header.go index b9b5391..4c72dcb 100644 --- a/libgo/go/net/http/header.go +++ b/libgo/go/net/http/header.go @@ -7,6 +7,7 @@ package http import ( "io" "net/http/httptrace" + "net/http/internal/ascii" "net/textproto" "sort" "strings" @@ -251,7 +252,7 @@ func hasToken(v, token string) bool { if endPos := sp + len(token); endPos != len(v) && !isTokenBoundary(v[endPos]) { continue } - if strings.EqualFold(v[sp:sp+len(token)], token) { + if ascii.EqualFold(v[sp:sp+len(token)], token) { return true } } diff --git a/libgo/go/net/http/http.go b/libgo/go/net/http/http.go index 4c5054b..101799f 100644 --- a/libgo/go/net/http/http.go +++ b/libgo/go/net/http/http.go @@ -62,15 +62,6 @@ func isNotToken(r rune) bool { return !httpguts.IsTokenRune(r) } -func isASCII(s string) bool { - for i := 0; i < len(s); i++ { - if s[i] >= utf8.RuneSelf { - return false - } - } - return true -} - // stringContainsCTLByte reports whether s contains any ASCII control character. func stringContainsCTLByte(s string) bool { for i := 0; i < len(s); i++ { diff --git a/libgo/go/net/http/http_test.go b/libgo/go/net/http/http_test.go index 3f1d7ce..0d92fe5 100644 --- a/libgo/go/net/http/http_test.go +++ b/libgo/go/net/http/http_test.go @@ -9,9 +9,13 @@ package http import ( "bytes" "internal/testenv" + "io/fs" "net/url" + "os" "os/exec" "reflect" + "regexp" + "strings" "testing" ) @@ -156,3 +160,61 @@ func BenchmarkCopyValues(b *testing.B) { b.Fatal("Benchmark wasn't run") } } + +var forbiddenStringsFunctions = map[string]bool{ + // Functions that use Unicode-aware case folding. + "EqualFold": true, + "Title": true, + "ToLower": true, + "ToLowerSpecial": true, + "ToTitle": true, + "ToTitleSpecial": true, + "ToUpper": true, + "ToUpperSpecial": true, + + // Functions that use Unicode-aware spaces. + "Fields": true, + "TrimSpace": true, +} + +// TestNoUnicodeStrings checks that nothing in net/http uses the Unicode-aware +// strings and bytes package functions. HTTP is mostly ASCII based, and doing +// Unicode-aware case folding or space stripping can introduce vulnerabilities. +func TestNoUnicodeStrings(t *testing.T) { + if !testenv.HasSrc() { + t.Skip("source code not available") + } + + re := regexp.MustCompile(`(strings|bytes).([A-Za-z]+)`) + if err := fs.WalkDir(os.DirFS("."), ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + t.Fatal(err) + } + + if path == "internal/ascii" { + return fs.SkipDir + } + if !strings.HasSuffix(path, ".go") || + strings.HasSuffix(path, "_test.go") || + path == "h2_bundle.go" || d.IsDir() { + return nil + } + + contents, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + for lineNum, line := range strings.Split(string(contents), "\n") { + for _, match := range re.FindAllStringSubmatch(line, -1) { + if !forbiddenStringsFunctions[match[2]] { + continue + } + t.Errorf("disallowed call to %s at %s:%d", match[0], path, lineNum+1) + } + } + + return nil + }); err != nil { + t.Fatal(err) + } +} diff --git a/libgo/go/net/http/httptest/recorder.go b/libgo/go/net/http/httptest/recorder.go index 2428482..1b712ef 100644 --- a/libgo/go/net/http/httptest/recorder.go +++ b/libgo/go/net/http/httptest/recorder.go @@ -122,11 +122,30 @@ func (rw *ResponseRecorder) WriteString(str string) (int, error) { return len(str), nil } +func checkWriteHeaderCode(code int) { + // Issue 22880: require valid WriteHeader status codes. + // For now we only enforce that it's three digits. + // In the future we might block things over 599 (600 and above aren't defined + // at https://httpwg.org/specs/rfc7231.html#status.codes) + // and we might block under 200 (once we have more mature 1xx support). + // But for now any three digits. + // + // We used to send "HTTP/1.1 000 0" on the wire in responses but there's + // no equivalent bogus thing we can realistically send in HTTP/2, + // so we'll consistently panic instead and help people find their bugs + // early. (We can't return an error from WriteHeader even if we wanted to.) + if code < 100 || code > 999 { + panic(fmt.Sprintf("invalid WriteHeader code %v", code)) + } +} + // WriteHeader implements http.ResponseWriter. func (rw *ResponseRecorder) WriteHeader(code int) { if rw.wroteHeader { return } + + checkWriteHeaderCode(code) rw.Code = code rw.wroteHeader = true if rw.HeaderMap == nil { diff --git a/libgo/go/net/http/httptest/recorder_test.go b/libgo/go/net/http/httptest/recorder_test.go index a865e87..8cb32dd 100644 --- a/libgo/go/net/http/httptest/recorder_test.go +++ b/libgo/go/net/http/httptest/recorder_test.go @@ -345,3 +345,28 @@ func TestParseContentLength(t *testing.T) { } } } + +// Ensure that httptest.Recorder panics when given a non-3 digit (XXX) +// status HTTP code. See https://golang.org/issues/45353 +func TestRecorderPanicsOnNonXXXStatusCode(t *testing.T) { + badCodes := []int{ + -100, 0, 99, 1000, 20000, + } + for _, badCode := range badCodes { + badCode := badCode + t.Run(fmt.Sprintf("Code=%d", badCode), func(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Fatal("Expected a panic") + } + }() + + handler := func(rw http.ResponseWriter, _ *http.Request) { + rw.WriteHeader(badCode) + } + r, _ := http.NewRequest("GET", "http://example.org/", nil) + rw := NewRecorder() + handler(rw, r) + }) + } +} diff --git a/libgo/go/net/http/httptest/server.go b/libgo/go/net/http/httptest/server.go index 8ebf681..a9faa9a 100644 --- a/libgo/go/net/http/httptest/server.go +++ b/libgo/go/net/http/httptest/server.go @@ -14,7 +14,7 @@ import ( "log" "net" "net/http" - "net/http/internal" + "net/http/internal/testcert" "os" "strings" "sync" @@ -144,7 +144,7 @@ func (s *Server) StartTLS() { if s.client == nil { s.client = &http.Client{Transport: &http.Transport{}} } - cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey) + cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey) if err != nil { panic(fmt.Sprintf("httptest: NewTLSServer: %v", err)) } @@ -316,6 +316,13 @@ func (s *Server) wrap() { s.Config.ConnState = func(c net.Conn, cs http.ConnState) { s.mu.Lock() defer s.mu.Unlock() + + // Keep Close from returning until the user's ConnState hook + // (if any) finishes. Without this, the call to forgetConn + // below might send the count to 0 before we run the hook. + s.wg.Add(1) + defer s.wg.Done() + switch cs { case http.StateNew: s.wg.Add(1) diff --git a/libgo/go/net/http/httptrace/trace.go b/libgo/go/net/http/httptrace/trace.go index 6a5cbac..5777c91 100644 --- a/libgo/go/net/http/httptrace/trace.go +++ b/libgo/go/net/http/httptrace/trace.go @@ -127,7 +127,7 @@ type ClientTrace struct { // ConnectDone is called when a new connection's Dial // completes. The provided err indicates whether the - // connection completedly successfully. + // connection completed successfully. // If net.Dialer.DualStack ("Happy Eyeballs") support is // enabled, this may be called multiple times. ConnectDone func(network, addr string, err error) diff --git a/libgo/go/net/http/httputil/dump_test.go b/libgo/go/net/http/httputil/dump_test.go index 8168b2e..366cc82 100644 --- a/libgo/go/net/http/httputil/dump_test.go +++ b/libgo/go/net/http/httputil/dump_test.go @@ -478,7 +478,7 @@ func TestDumpResponse(t *testing.T) { } } -// Issue 38352: Check for deadlock on cancelled requests. +// Issue 38352: Check for deadlock on canceled requests. func TestDumpRequestOutIssue38352(t *testing.T) { if testing.Short() { return diff --git a/libgo/go/net/http/httputil/reverseproxy.go b/libgo/go/net/http/httputil/reverseproxy.go index ccb8456..8b63368 100644 --- a/libgo/go/net/http/httputil/reverseproxy.go +++ b/libgo/go/net/http/httputil/reverseproxy.go @@ -13,6 +13,7 @@ import ( "log" "net" "net/http" + "net/http/internal/ascii" "net/textproto" "net/url" "strings" @@ -234,6 +235,15 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if req.ContentLength == 0 { outreq.Body = nil // Issue 16036: nil Body for http.Transport retries } + if outreq.Body != nil { + // Reading from the request body after returning from a handler is not + // allowed, and the RoundTrip goroutine that reads the Body can outlive + // this handler. This can lead to a crash if the handler panics (see + // Issue 46866). Although calling Close doesn't guarantee there isn't + // any Read in flight after the handle returns, in practice it's safe to + // read after closing it. + defer outreq.Body.Close() + } if outreq.Header == nil { outreq.Header = make(http.Header) // Issue 33142: historical behavior was to always allocate } @@ -242,6 +252,10 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { outreq.Close = false reqUpType := upgradeType(outreq.Header) + if !ascii.IsPrint(reqUpType) { + p.getErrorHandler()(rw, req, fmt.Errorf("client tried to switch to invalid protocol %q", reqUpType)) + return + } removeConnectionHeaders(outreq.Header) // Remove hop-by-hop headers to the backend. Especially @@ -534,13 +548,16 @@ func upgradeType(h http.Header) string { if !httpguts.HeaderValuesContainsToken(h["Connection"], "Upgrade") { return "" } - return strings.ToLower(h.Get("Upgrade")) + return h.Get("Upgrade") } func (p *ReverseProxy) handleUpgradeResponse(rw http.ResponseWriter, req *http.Request, res *http.Response) { reqUpType := upgradeType(req.Header) resUpType := upgradeType(res.Header) - if reqUpType != resUpType { + if !ascii.IsPrint(resUpType) { // We know reqUpType is ASCII, it's checked by the caller. + p.getErrorHandler()(rw, req, fmt.Errorf("backend tried to switch to invalid protocol %q", resUpType)) + } + if !ascii.EqualFold(reqUpType, resUpType) { p.getErrorHandler()(rw, req, fmt.Errorf("backend tried to switch protocol %q when %q was requested", resUpType, reqUpType)) return } @@ -558,7 +575,7 @@ func (p *ReverseProxy) handleUpgradeResponse(rw http.ResponseWriter, req *http.R backConnCloseCh := make(chan bool) go func() { - // Ensure that the cancelation of a request closes the backend. + // Ensure that the cancellation of a request closes the backend. // See issue https://golang.org/issue/35559. select { case <-req.Context().Done(): diff --git a/libgo/go/net/http/httputil/reverseproxy_test.go b/libgo/go/net/http/httputil/reverseproxy_test.go index 3211463..4b6ad77 100644 --- a/libgo/go/net/http/httputil/reverseproxy_test.go +++ b/libgo/go/net/http/httputil/reverseproxy_test.go @@ -16,6 +16,7 @@ import ( "log" "net/http" "net/http/httptest" + "net/http/internal/ascii" "net/url" "os" "reflect" @@ -1121,6 +1122,45 @@ func TestReverseProxy_PanicBodyError(t *testing.T) { rproxy.ServeHTTP(httptest.NewRecorder(), req) } +// Issue #46866: panic without closing incoming request body causes a panic +func TestReverseProxy_PanicClosesIncomingBody(t *testing.T) { + backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + out := "this call was relayed by the reverse proxy" + // Coerce a wrong content length to induce io.ErrUnexpectedEOF + w.Header().Set("Content-Length", fmt.Sprintf("%d", len(out)*2)) + fmt.Fprintln(w, out) + })) + defer backend.Close() + backendURL, err := url.Parse(backend.URL) + if err != nil { + t.Fatal(err) + } + proxyHandler := NewSingleHostReverseProxy(backendURL) + proxyHandler.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests + frontend := httptest.NewServer(proxyHandler) + defer frontend.Close() + frontendClient := frontend.Client() + + var wg sync.WaitGroup + for i := 0; i < 2; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for j := 0; j < 10; j++ { + const reqLen = 6 * 1024 * 1024 + req, _ := http.NewRequest("POST", frontend.URL, &io.LimitedReader{R: neverEnding('x'), N: reqLen}) + req.ContentLength = reqLen + resp, _ := frontendClient.Transport.RoundTrip(req) + if resp != nil { + io.Copy(io.Discard, resp.Body) + resp.Body.Close() + } + } + }() + } + wg.Wait() +} + func TestSelectFlushInterval(t *testing.T) { tests := []struct { name string @@ -1242,7 +1282,7 @@ func TestReverseProxyWebSocket(t *testing.T) { t.Errorf("Header(XHeader) = %q; want %q", got, want) } - if upgradeType(res.Header) != "websocket" { + if !ascii.EqualFold(upgradeType(res.Header), "websocket") { t.Fatalf("not websocket upgrade; got %#v", res.Header) } rwc, ok := res.Body.(io.ReadWriteCloser) @@ -1267,7 +1307,7 @@ func TestReverseProxyWebSocket(t *testing.T) { } } -func TestReverseProxyWebSocketCancelation(t *testing.T) { +func TestReverseProxyWebSocketCancellation(t *testing.T) { n := 5 triggerCancelCh := make(chan bool, n) nthResponse := func(i int) string { @@ -1359,7 +1399,7 @@ func TestReverseProxyWebSocketCancelation(t *testing.T) { t.Errorf("X-Header mismatch\n\tgot: %q\n\twant: %q", g, w) } - if g, w := upgradeType(res.Header), "websocket"; g != w { + if g, w := upgradeType(res.Header), "websocket"; !ascii.EqualFold(g, w) { t.Fatalf("Upgrade header mismatch\n\tgot: %q\n\twant: %q", g, w) } diff --git a/libgo/go/net/http/internal/ascii/print.go b/libgo/go/net/http/internal/ascii/print.go new file mode 100644 index 0000000..585e5ba --- /dev/null +++ b/libgo/go/net/http/internal/ascii/print.go @@ -0,0 +1,61 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ascii + +import ( + "strings" + "unicode" +) + +// EqualFold is strings.EqualFold, ASCII only. It reports whether s and t +// are equal, ASCII-case-insensitively. +func EqualFold(s, t string) bool { + if len(s) != len(t) { + return false + } + for i := 0; i < len(s); i++ { + if lower(s[i]) != lower(t[i]) { + return false + } + } + return true +} + +// lower returns the ASCII lowercase version of b. +func lower(b byte) byte { + if 'A' <= b && b <= 'Z' { + return b + ('a' - 'A') + } + return b +} + +// IsPrint returns whether s is ASCII and printable according to +// https://tools.ietf.org/html/rfc20#section-4.2. +func IsPrint(s string) bool { + for i := 0; i < len(s); i++ { + if s[i] < ' ' || s[i] > '~' { + return false + } + } + return true +} + +// Is returns whether s is ASCII. +func Is(s string) bool { + for i := 0; i < len(s); i++ { + if s[i] > unicode.MaxASCII { + return false + } + } + return true +} + +// ToLower returns the lowercase version of s if s is ASCII and printable. +func ToLower(s string) (lower string, ok bool) { + if !IsPrint(s) { + return "", false + } + return strings.ToLower(s), true +} diff --git a/libgo/go/net/http/internal/ascii/print_test.go b/libgo/go/net/http/internal/ascii/print_test.go new file mode 100644 index 0000000..0b7767ca --- /dev/null +++ b/libgo/go/net/http/internal/ascii/print_test.go @@ -0,0 +1,95 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ascii + +import "testing" + +func TestEqualFold(t *testing.T) { + var tests = []struct { + name string + a, b string + want bool + }{ + { + name: "empty", + want: true, + }, + { + name: "simple match", + a: "CHUNKED", + b: "chunked", + want: true, + }, + { + name: "same string", + a: "chunked", + b: "chunked", + want: true, + }, + { + name: "Unicode Kelvin symbol", + a: "chunKed", // This "K" is 'KELVIN SIGN' (\u212A) + b: "chunked", + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := EqualFold(tt.a, tt.b); got != tt.want { + t.Errorf("AsciiEqualFold(%q,%q): got %v want %v", tt.a, tt.b, got, tt.want) + } + }) + } +} + +func TestIsPrint(t *testing.T) { + var tests = []struct { + name string + in string + want bool + }{ + { + name: "empty", + want: true, + }, + { + name: "ASCII low", + in: "This is a space: ' '", + want: true, + }, + { + name: "ASCII high", + in: "This is a tilde: '~'", + want: true, + }, + { + name: "ASCII low non-print", + in: "This is a unit separator: \x1F", + want: false, + }, + { + name: "Ascii high non-print", + in: "This is a Delete: \x7F", + want: false, + }, + { + name: "Unicode letter", + in: "Today it's 280K outside: it's freezing!", // This "K" is 'KELVIN SIGN' (\u212A) + want: false, + }, + { + name: "Unicode emoji", + in: "Gophers like 🧀", + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IsPrint(tt.in); got != tt.want { + t.Errorf("IsASCIIPrint(%q): got %v want %v", tt.in, got, tt.want) + } + }) + } +} diff --git a/libgo/go/net/http/internal/testcert.go b/libgo/go/net/http/internal/testcert/testcert.go index 2284a83..5f94704 100644 --- a/libgo/go/net/http/internal/testcert.go +++ b/libgo/go/net/http/internal/testcert/testcert.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package internal +// Package testcert contains a test-only localhost certificate. +package testcert import "strings" @@ -25,7 +26,7 @@ h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM fblo6RBxUQ== -----END CERTIFICATE-----`) -// LocalhostKey is the private key for localhostCert. +// LocalhostKey is the private key for LocalhostCert. var LocalhostKey = []byte(testingKey(`-----BEGIN RSA TESTING KEY----- MIICXgIBAAKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9 SjY1bIw4iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZB diff --git a/libgo/go/net/http/omithttp2.go b/libgo/go/net/http/omithttp2.go index 30c6e48..79599d0 100644 --- a/libgo/go/net/http/omithttp2.go +++ b/libgo/go/net/http/omithttp2.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build nethttpomithttp2 // +build nethttpomithttp2 package http diff --git a/libgo/go/net/http/pprof/pprof.go b/libgo/go/net/http/pprof/pprof.go index 5389a38..888ea35 100644 --- a/libgo/go/net/http/pprof/pprof.go +++ b/libgo/go/net/http/pprof/pprof.go @@ -287,7 +287,7 @@ func (name handler) serveDeltaProfile(w http.ResponseWriter, r *http.Request, p err := r.Context().Err() if err == context.DeadlineExceeded { serveError(w, http.StatusRequestTimeout, err.Error()) - } else { // TODO: what's a good status code for cancelled requests? 400? + } else { // TODO: what's a good status code for canceled requests? 400? serveError(w, http.StatusInternalServerError, err.Error()) } return @@ -431,7 +431,7 @@ Types of profiles available: b.WriteString(`</table> <a href="goroutine?debug=2">full goroutine stack dump</a> -<br/> +<br> <p> Profile Descriptions: <ul> diff --git a/libgo/go/net/http/request.go b/libgo/go/net/http/request.go index adba540..09cb0c7 100644 --- a/libgo/go/net/http/request.go +++ b/libgo/go/net/http/request.go @@ -19,6 +19,7 @@ import ( "mime/multipart" "net" "net/http/httptrace" + "net/http/internal/ascii" "net/textproto" "net/url" urlpkg "net/url" @@ -723,7 +724,7 @@ func idnaASCII(v string) (string, error) { // version does not. // Note that for correct ASCII IDNs ToASCII will only do considerably more // work, but it will not cause an allocation. - if isASCII(v) { + if ascii.Is(v) { return v, nil } return idna.Lookup.ToASCII(v) @@ -779,7 +780,8 @@ func removeZone(host string) string { } // ParseHTTPVersion parses an HTTP version string. -// "HTTP/1.0" returns (1, 0, true). +// "HTTP/1.0" returns (1, 0, true). Note that strings without +// a minor version, such as "HTTP/2", are not valid. func ParseHTTPVersion(vers string) (major, minor int, ok bool) { const Big = 1000000 // arbitrary upper bound switch vers { @@ -823,7 +825,7 @@ func validMethod(method string) bool { return len(method) > 0 && strings.IndexFunc(method, isNotToken) == -1 } -// NewRequest wraps NewRequestWithContext using the background context. +// NewRequest wraps NewRequestWithContext using context.Background. func NewRequest(method, url string, body io.Reader) (*Request, error) { return NewRequestWithContext(context.Background(), method, url, body) } @@ -947,7 +949,7 @@ func (r *Request) BasicAuth() (username, password string, ok bool) { func parseBasicAuth(auth string) (username, password string, ok bool) { const prefix = "Basic " // Case insensitive prefix match. See Issue 22736. - if len(auth) < len(prefix) || !strings.EqualFold(auth[:len(prefix)], prefix) { + if len(auth) < len(prefix) || !ascii.EqualFold(auth[:len(prefix)], prefix) { return } c, err := base64.StdEncoding.DecodeString(auth[len(prefix):]) @@ -1009,16 +1011,16 @@ func putTextprotoReader(r *textproto.Reader) { // requests and handle them via the Handler interface. ReadRequest // only supports HTTP/1.x requests. For HTTP/2, use golang.org/x/net/http2. func ReadRequest(b *bufio.Reader) (*Request, error) { - return readRequest(b, deleteHostHeader) -} + req, err := readRequest(b) + if err != nil { + return nil, err + } -// Constants for readRequest's deleteHostHeader parameter. -const ( - deleteHostHeader = true - keepHostHeader = false -) + delete(req.Header, "Host") + return req, err +} -func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err error) { +func readRequest(b *bufio.Reader) (req *Request, err error) { tp := newTextprotoReader(b) req = new(Request) @@ -1076,6 +1078,9 @@ func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err erro return nil, err } req.Header = Header(mimeHeader) + if len(req.Header["Host"]) > 1 { + return nil, fmt.Errorf("too many Host headers") + } // RFC 7230, section 5.3: Must treat // GET /index.html HTTP/1.1 @@ -1088,9 +1093,6 @@ func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err erro if req.Host == "" { req.Host = req.Header.get("Host") } - if deleteHostHeader { - delete(req.Header, "Host") - } fixPragmaCacheControl(req.Header) @@ -1123,6 +1125,9 @@ func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err erro // MaxBytesReader prevents clients from accidentally or maliciously // sending a large request and wasting server resources. func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser { + if n < 0 { // Treat negative limits as equivalent to 0. + n = 0 + } return &maxBytesReader{w: w, r: r, n: n} } @@ -1288,16 +1293,18 @@ func (r *Request) ParseForm() error { // its file parts are stored in memory, with the remainder stored on // disk in temporary files. // ParseMultipartForm calls ParseForm if necessary. +// If ParseForm returns an error, ParseMultipartForm returns it but also +// continues parsing the request body. // After one call to ParseMultipartForm, subsequent calls have no effect. func (r *Request) ParseMultipartForm(maxMemory int64) error { if r.MultipartForm == multipartByReader { return errors.New("http: multipart handled by MultipartReader") } + var parseFormErr error if r.Form == nil { - err := r.ParseForm() - if err != nil { - return err - } + // Let errors in ParseForm fall through, and just + // return it at the end. + parseFormErr = r.ParseForm() } if r.MultipartForm != nil { return nil @@ -1324,7 +1331,7 @@ func (r *Request) ParseMultipartForm(maxMemory int64) error { r.MultipartForm = f - return nil + return parseFormErr } // FormValue returns the first value for the named component of the query. @@ -1452,5 +1459,5 @@ func requestMethodUsuallyLacksBody(method string) bool { // an HTTP/1 connection. func (r *Request) requiresHTTP1() bool { return hasToken(r.Header.Get("Connection"), "upgrade") && - strings.EqualFold(r.Header.Get("Upgrade"), "websocket") + ascii.EqualFold(r.Header.Get("Upgrade"), "websocket") } diff --git a/libgo/go/net/http/request_test.go b/libgo/go/net/http/request_test.go index 29297b0..4e0c4ba 100644 --- a/libgo/go/net/http/request_test.go +++ b/libgo/go/net/http/request_test.go @@ -32,9 +32,26 @@ func TestQuery(t *testing.T) { } } +// Issue #25192: Test that ParseForm fails but still parses the form when an URL +// containing a semicolon is provided. +func TestParseFormSemicolonSeparator(t *testing.T) { + for _, method := range []string{"POST", "PATCH", "PUT", "GET"} { + req, _ := NewRequest(method, "http://www.google.com/search?q=foo;q=bar&a=1", + strings.NewReader("q")) + err := req.ParseForm() + if err == nil { + t.Fatalf(`for method %s, ParseForm expected an error, got success`, method) + } + wantForm := url.Values{"a": []string{"1"}} + if !reflect.DeepEqual(req.Form, wantForm) { + t.Fatalf("for method %s, ParseForm expected req.Form = %v, want %v", method, req.Form, wantForm) + } + } +} + func TestParseFormQuery(t *testing.T) { req, _ := NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x&prio=1&orphan=nope&empty=not", - strings.NewReader("z=post&both=y&prio=2&=nokey&orphan;empty=&")) + strings.NewReader("z=post&both=y&prio=2&=nokey&orphan&empty=&")) req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value") if q := req.FormValue("q"); q != "foo" { @@ -245,6 +262,29 @@ func TestParseMultipartForm(t *testing.T) { } } +// Issue 45789: multipart form should not include directory path in filename +func TestParseMultipartFormFilename(t *testing.T) { + postData := + `--xxx +Content-Disposition: form-data; name="file"; filename="../usr/foobar.txt/" +Content-Type: text/plain + +--xxx-- +` + req := &Request{ + Method: "POST", + Header: Header{"Content-Type": {`multipart/form-data; boundary=xxx`}}, + Body: io.NopCloser(strings.NewReader(postData)), + } + _, hdr, err := req.FormFile("file") + if err != nil { + t.Fatal(err) + } + if hdr.Filename != "foobar.txt" { + t.Errorf("expected only the last element of the path, got %q", hdr.Filename) + } +} + // Issue #40430: Test that if maxMemory for ParseMultipartForm when combined with // the payload size and the internal leeway buffer size of 10MiB overflows, that we // correctly return an error. @@ -342,6 +382,18 @@ func TestMultipartRequest(t *testing.T) { validateTestMultipartContents(t, req, false) } +// Issue #25192: Test that ParseMultipartForm fails but still parses the +// multi-part form when an URL containing a semicolon is provided. +func TestParseMultipartFormSemicolonSeparator(t *testing.T) { + req := newTestMultipartRequest(t) + req.URL = &url.URL{RawQuery: "q=foo;q=bar"} + if err := req.ParseMultipartForm(25); err == nil { + t.Fatal("ParseMultipartForm expected error due to invalid semicolon, got nil") + } + defer req.MultipartForm.RemoveAll() + validateTestMultipartContents(t, req, false) +} + func TestMultipartRequestAuto(t *testing.T) { // Test that FormValue and FormFile automatically invoke // ParseMultipartForm and return the right values. @@ -469,6 +521,10 @@ var readRequestErrorTests = []struct { in: "HEAD / HTTP/1.1\r\nContent-Length:0\r\nContent-Length: 0\r\n\r\n", header: Header{"Content-Length": {"0"}}, }, + 11: { + in: "HEAD / HTTP/1.1\r\nHost: foo\r\nHost: bar\r\n\r\n\r\n\r\n", + err: "too many Host headers", + }, } func TestReadRequestErrors(t *testing.T) { @@ -850,6 +906,92 @@ func TestMaxBytesReaderStickyError(t *testing.T) { } } +// Issue 45101: maxBytesReader's Read panicked when n < -1. This test +// also ensures that Read treats negative limits as equivalent to 0. +func TestMaxBytesReaderDifferentLimits(t *testing.T) { + const testStr = "1234" + tests := [...]struct { + limit int64 + lenP int + wantN int + wantErr bool + }{ + 0: { + limit: -123, + lenP: 0, + wantN: 0, + wantErr: false, // Ensure we won't return an error when the limit is negative, but we don't need to read. + }, + 1: { + limit: -100, + lenP: 32 * 1024, + wantN: 0, + wantErr: true, + }, + 2: { + limit: -2, + lenP: 1, + wantN: 0, + wantErr: true, + }, + 3: { + limit: -1, + lenP: 2, + wantN: 0, + wantErr: true, + }, + 4: { + limit: 0, + lenP: 3, + wantN: 0, + wantErr: true, + }, + 5: { + limit: 1, + lenP: 4, + wantN: 1, + wantErr: true, + }, + 6: { + limit: 2, + lenP: 5, + wantN: 2, + wantErr: true, + }, + 7: { + limit: 3, + lenP: 2, + wantN: 2, + wantErr: false, + }, + 8: { + limit: int64(len(testStr)), + lenP: len(testStr), + wantN: len(testStr), + wantErr: false, + }, + 9: { + limit: 100, + lenP: 6, + wantN: len(testStr), + wantErr: false, + }, + } + for i, tt := range tests { + rc := MaxBytesReader(nil, io.NopCloser(strings.NewReader(testStr)), tt.limit) + + n, err := rc.Read(make([]byte, tt.lenP)) + + if n != tt.wantN { + t.Errorf("%d. n: %d, want n: %d", i, n, tt.wantN) + } + + if (err != nil) != tt.wantErr { + t.Errorf("%d. error: %v", i, err) + } + } +} + func TestWithContextDeepCopiesURL(t *testing.T) { req, err := NewRequest("POST", "https://golang.org/", nil) if err != nil { diff --git a/libgo/go/net/http/roundtrip.go b/libgo/go/net/http/roundtrip.go index 2ec736b..eef7c79 100644 --- a/libgo/go/net/http/roundtrip.go +++ b/libgo/go/net/http/roundtrip.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js || !wasm // +build !js !wasm package http diff --git a/libgo/go/net/http/roundtrip_js.go b/libgo/go/net/http/roundtrip_js.go index c6a221a..74c83a9 100644 --- a/libgo/go/net/http/roundtrip_js.go +++ b/libgo/go/net/http/roundtrip_js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package http diff --git a/libgo/go/net/http/serve_test.go b/libgo/go/net/http/serve_test.go index f868741..6394da3 100644 --- a/libgo/go/net/http/serve_test.go +++ b/libgo/go/net/http/serve_test.go @@ -25,6 +25,7 @@ import ( "net/http/httptest" "net/http/httputil" "net/http/internal" + "net/http/internal/testcert" "net/url" "os" "os/exec" @@ -1475,7 +1476,7 @@ func TestServeTLS(t *testing.T) { defer afterTest(t) defer SetTestHookServerServe(nil) - cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey) + cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey) if err != nil { t.Fatal(err) } @@ -1599,7 +1600,7 @@ func TestAutomaticHTTP2_Serve_WithTLSConfig(t *testing.T) { } func TestAutomaticHTTP2_ListenAndServe(t *testing.T) { - cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey) + cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey) if err != nil { t.Fatal(err) } @@ -1609,7 +1610,7 @@ func TestAutomaticHTTP2_ListenAndServe(t *testing.T) { } func TestAutomaticHTTP2_ListenAndServe_GetCertificate(t *testing.T) { - cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey) + cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey) if err != nil { t.Fatal(err) } @@ -6507,3 +6508,104 @@ func TestDisableKeepAliveUpgrade(t *testing.T) { t.Fatalf("unexpected value read from body:\ngot: %q\nwant: %q", b, "hello") } } + +func TestMuxRedirectRelative(t *testing.T) { + setParallel(t) + req, err := ReadRequest(bufio.NewReader(strings.NewReader("GET http://example.com HTTP/1.1\r\nHost: test\r\n\r\n"))) + if err != nil { + t.Errorf("%s", err) + } + mux := NewServeMux() + resp := httptest.NewRecorder() + mux.ServeHTTP(resp, req) + if got, want := resp.Header().Get("Location"), "/"; got != want { + t.Errorf("Location header expected %q; got %q", want, got) + } + if got, want := resp.Code, StatusMovedPermanently; got != want { + t.Errorf("Expected response code %d; got %d", want, got) + } +} + +// TestQuerySemicolon tests the behavior of semicolons in queries. See Issue 25192. +func TestQuerySemicolon(t *testing.T) { + t.Cleanup(func() { afterTest(t) }) + + tests := []struct { + query string + xNoSemicolons string + xWithSemicolons string + warning bool + }{ + {"?a=1;x=bad&x=good", "good", "bad", true}, + {"?a=1;b=bad&x=good", "good", "good", true}, + {"?a=1%3Bx=bad&x=good%3B", "good;", "good;", false}, + {"?a=1;x=good;x=bad", "", "good", true}, + } + + for _, tt := range tests { + t.Run(tt.query+"/allow=false", func(t *testing.T) { + allowSemicolons := false + testQuerySemicolon(t, tt.query, tt.xNoSemicolons, allowSemicolons, tt.warning) + }) + t.Run(tt.query+"/allow=true", func(t *testing.T) { + allowSemicolons, expectWarning := true, false + testQuerySemicolon(t, tt.query, tt.xWithSemicolons, allowSemicolons, expectWarning) + }) + } +} + +func testQuerySemicolon(t *testing.T, query string, wantX string, allowSemicolons, expectWarning bool) { + setParallel(t) + + writeBackX := func(w ResponseWriter, r *Request) { + x := r.URL.Query().Get("x") + if expectWarning { + if err := r.ParseForm(); err == nil || !strings.Contains(err.Error(), "semicolon") { + t.Errorf("expected error mentioning semicolons from ParseForm, got %v", err) + } + } else { + if err := r.ParseForm(); err != nil { + t.Errorf("expected no error from ParseForm, got %v", err) + } + } + if got := r.FormValue("x"); x != got { + t.Errorf("got %q from FormValue, want %q", got, x) + } + fmt.Fprintf(w, "%s", x) + } + + h := Handler(HandlerFunc(writeBackX)) + if allowSemicolons { + h = AllowQuerySemicolons(h) + } + + ts := httptest.NewUnstartedServer(h) + logBuf := &bytes.Buffer{} + ts.Config.ErrorLog = log.New(logBuf, "", 0) + ts.Start() + defer ts.Close() + + req, _ := NewRequest("GET", ts.URL+query, nil) + res, err := ts.Client().Do(req) + if err != nil { + t.Fatal(err) + } + slurp, _ := io.ReadAll(res.Body) + res.Body.Close() + if got, want := res.StatusCode, 200; got != want { + t.Errorf("Status = %d; want = %d", got, want) + } + if got, want := string(slurp), wantX; got != want { + t.Errorf("Body = %q; want = %q", got, want) + } + + if expectWarning { + if !strings.Contains(logBuf.String(), "semicolon") { + t.Errorf("got %q from ErrorLog, expected a mention of semicolons", logBuf.String()) + } + } else { + if strings.Contains(logBuf.String(), "semicolon") { + t.Errorf("got %q from ErrorLog, expected no mention of semicolons", logBuf.String()) + } + } +} diff --git a/libgo/go/net/http/server.go b/libgo/go/net/http/server.go index 33aadd6..ce39933 100644 --- a/libgo/go/net/http/server.go +++ b/libgo/go/net/http/server.go @@ -333,7 +333,7 @@ func (c *conn) hijackLocked() (rwc net.Conn, buf *bufio.ReadWriter, err error) { const bufferBeforeChunkingSize = 2048 // chunkWriter writes to a response's conn buffer, and is the writer -// wrapped by the response.bufw buffered writer. +// wrapped by the response.w buffered writer. // // chunkWriter also is responsible for finalizing the Header, including // conditionally setting the Content-Type and setting a Content-Length @@ -577,37 +577,17 @@ func (w *response) ReadFrom(src io.Reader) (n int64, err error) { return io.CopyBuffer(writerOnly{w}, src, buf) } - // sendfile path: - - // Do not start actually writing response until src is readable. - // If body length is <= sniffLen, sendfile/splice path will do - // little anyway. This small read also satisfies sniffing the - // body in case Content-Type is missing. - nr, er := src.Read(buf[:sniffLen]) - atEOF := errors.Is(er, io.EOF) - n += int64(nr) - - if nr > 0 { - // Write the small amount read normally. - nw, ew := w.Write(buf[:nr]) - if ew != nil { - err = ew - } else if nr != nw { - err = io.ErrShortWrite + // Copy the first sniffLen bytes before switching to ReadFrom. + // This ensures we don't start writing the response before the + // source is available (see golang.org/issue/5660) and provides + // enough bytes to perform Content-Type sniffing when required. + if !w.cw.wroteHeader { + n0, err := io.CopyBuffer(writerOnly{w}, io.LimitReader(src, sniffLen), buf) + n += n0 + if err != nil || n0 < sniffLen { + return n, err } } - if err == nil && er != nil && !atEOF { - err = er - } - - // Do not send StatusOK in the error case where nothing has been written. - if err == nil && !w.wroteHeader { - w.WriteHeader(StatusOK) // nr == 0, no error (or EOF) - } - - if err != nil || atEOF { - return n, err - } w.w.Flush() // get rid of any previous writes w.cw.flush() // make sure Header is written; flush data to rwc @@ -620,7 +600,7 @@ func (w *response) ReadFrom(src io.Reader) (n int64, err error) { return n, err } - n0, err := io.Copy(writerOnly{w}, src) + n0, err := io.CopyBuffer(writerOnly{w}, src, buf) n += n0 return n, err } @@ -964,14 +944,14 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) { hdrDeadline time.Time // or zero if none ) t0 := time.Now() - if d := c.server.readHeaderTimeout(); d != 0 { + if d := c.server.readHeaderTimeout(); d > 0 { hdrDeadline = t0.Add(d) } - if d := c.server.ReadTimeout; d != 0 { + if d := c.server.ReadTimeout; d > 0 { wholeReqDeadline = t0.Add(d) } c.rwc.SetReadDeadline(hdrDeadline) - if d := c.server.WriteTimeout; d != 0 { + if d := c.server.WriteTimeout; d > 0 { defer func() { c.rwc.SetWriteDeadline(time.Now().Add(d)) }() @@ -983,7 +963,7 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) { peek, _ := c.bufr.Peek(4) // ReadRequest will get err below c.bufr.Discard(numLeadingCRorLF(peek)) } - req, err := readRequest(c.bufr, keepHostHeader) + req, err := readRequest(c.bufr) if err != nil { if c.r.hitReadLimit() { return nil, errTooLarge @@ -1003,9 +983,6 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) { if req.ProtoAtLeast(1, 1) && (!haveHost || len(hosts) == 0) && !isH2Upgrade && req.Method != "CONNECT" { return nil, badRequestError("missing required Host header") } - if len(hosts) > 1 { - return nil, badRequestError("too many Host headers") - } if len(hosts) == 1 && !httpguts.ValidHostHeader(hosts[0]) { return nil, badRequestError("malformed Host header") } @@ -1557,12 +1534,12 @@ func (w *response) bodyAllowed() bool { // The Writers are wired together like: // // 1. *response (the ResponseWriter) -> -// 2. (*response).w, a *bufio.Writer of bufferBeforeChunkingSize bytes +// 2. (*response).w, a *bufio.Writer of bufferBeforeChunkingSize bytes -> // 3. chunkWriter.Writer (whose writeHeader finalizes Content-Length/Type) -// and which writes the chunk headers, if needed. -// 4. conn.buf, a bufio.Writer of default (4kB) bytes, writing to -> +// and which writes the chunk headers, if needed -> +// 4. conn.bufw, a *bufio.Writer of default (4kB) bytes, writing to -> // 5. checkConnErrorWriter{c}, which notes any non-nil error on Write -// and populates c.werr with it if so. but otherwise writes to: +// and populates c.werr with it if so, but otherwise writes to -> // 6. the rwc, the net.Conn. // // TODO(bradfitz): short-circuit some of the buffering when the @@ -1836,13 +1813,13 @@ func (c *conn) serve(ctx context.Context) { }() if tlsConn, ok := c.rwc.(*tls.Conn); ok { - if d := c.server.ReadTimeout; d != 0 { + if d := c.server.ReadTimeout; d > 0 { c.rwc.SetReadDeadline(time.Now().Add(d)) } - if d := c.server.WriteTimeout; d != 0 { + if d := c.server.WriteTimeout; d > 0 { c.rwc.SetWriteDeadline(time.Now().Add(d)) } - if err := tlsConn.Handshake(); err != nil { + if err := tlsConn.HandshakeContext(ctx); err != nil { // If the handshake failed due to the client not speaking // TLS, assume they're speaking plaintext HTTP and write a // 400 response on the TLS conn's underlying net.Conn. @@ -2412,9 +2389,8 @@ func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) { if path != r.URL.Path { _, pattern = mux.handler(host, path) - url := *r.URL - url.Path = path - return RedirectHandler(url.String(), StatusMovedPermanently), pattern + u := &url.URL{Path: path, RawQuery: r.URL.RawQuery} + return RedirectHandler(u.String(), StatusMovedPermanently), pattern } return mux.handler(host, r.URL.Path) @@ -2572,7 +2548,8 @@ type Server struct { TLSConfig *tls.Config // ReadTimeout is the maximum duration for reading the entire - // request, including the body. + // request, including the body. A zero or negative value means + // there will be no timeout. // // Because ReadTimeout does not let Handlers make per-request // decisions on each request body's acceptable deadline or @@ -2592,6 +2569,7 @@ type Server struct { // writes of the response. It is reset whenever a new // request's header is read. Like ReadTimeout, it does not // let Handlers make decisions on a per-request basis. + // A zero or negative value means there will be no timeout. WriteTimeout time.Duration // IdleTimeout is the maximum amount of time to wait for the @@ -2643,7 +2621,7 @@ type Server struct { // value. ConnContext func(ctx context.Context, c net.Conn) context.Context - inShutdown atomicBool // true when when server is in shutdown + inShutdown atomicBool // true when server is in shutdown disableKeepAlives int32 // accessed atomically. nextProtoOnce sync.Once // guards setupHTTP2_* init @@ -2889,9 +2867,51 @@ func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) { if req.RequestURI == "*" && req.Method == "OPTIONS" { handler = globalOptionsHandler{} } + + if req.URL != nil && strings.Contains(req.URL.RawQuery, ";") { + var allowQuerySemicolonsInUse int32 + req = req.WithContext(context.WithValue(req.Context(), silenceSemWarnContextKey, func() { + atomic.StoreInt32(&allowQuerySemicolonsInUse, 1) + })) + defer func() { + if atomic.LoadInt32(&allowQuerySemicolonsInUse) == 0 { + sh.srv.logf("http: URL query contains semicolon, which is no longer a supported separator; parts of the query may be stripped when parsed; see golang.org/issue/25192") + } + }() + } + handler.ServeHTTP(rw, req) } +var silenceSemWarnContextKey = &contextKey{"silence-semicolons"} + +// AllowQuerySemicolons returns a handler that serves requests by converting any +// unescaped semicolons in the URL query to ampersands, and invoking the handler h. +// +// This restores the pre-Go 1.17 behavior of splitting query parameters on both +// semicolons and ampersands. (See golang.org/issue/25192). Note that this +// behavior doesn't match that of many proxies, and the mismatch can lead to +// security issues. +// +// AllowQuerySemicolons should be invoked before Request.ParseForm is called. +func AllowQuerySemicolons(h Handler) Handler { + return HandlerFunc(func(w ResponseWriter, r *Request) { + if silenceSemicolonsWarning, ok := r.Context().Value(silenceSemWarnContextKey).(func()); ok { + silenceSemicolonsWarning() + } + if strings.Contains(r.URL.RawQuery, ";") { + r2 := new(Request) + *r2 = *r + r2.URL = new(url.URL) + *r2.URL = *r.URL + r2.URL.RawQuery = strings.ReplaceAll(r.URL.RawQuery, ";", "&") + h.ServeHTTP(w, r2) + } else { + h.ServeHTTP(w, r) + } + }) +} + // ListenAndServe listens on the TCP network address srv.Addr and then // calls Serve to handle requests on incoming connections. // Accepted connections are configured to enable TCP keep-alives. diff --git a/libgo/go/net/http/sniff_test.go b/libgo/go/net/http/sniff_test.go index 8d53503..e913357 100644 --- a/libgo/go/net/http/sniff_test.go +++ b/libgo/go/net/http/sniff_test.go @@ -157,9 +157,25 @@ func testServerIssue5953(t *testing.T, h2 bool) { resp.Body.Close() } -func TestContentTypeWithCopy_h1(t *testing.T) { testContentTypeWithCopy(t, h1Mode) } -func TestContentTypeWithCopy_h2(t *testing.T) { testContentTypeWithCopy(t, h2Mode) } -func testContentTypeWithCopy(t *testing.T, h2 bool) { +type byteAtATimeReader struct { + buf []byte +} + +func (b *byteAtATimeReader) Read(p []byte) (n int, err error) { + if len(p) < 1 { + return 0, nil + } + if len(b.buf) == 0 { + return 0, io.EOF + } + p[0] = b.buf[0] + b.buf = b.buf[1:] + return 1, nil +} + +func TestContentTypeWithVariousSources_h1(t *testing.T) { testContentTypeWithVariousSources(t, h1Mode) } +func TestContentTypeWithVariousSources_h2(t *testing.T) { testContentTypeWithVariousSources(t, h2Mode) } +func testContentTypeWithVariousSources(t *testing.T, h2 bool) { defer afterTest(t) const ( @@ -167,30 +183,86 @@ func testContentTypeWithCopy(t *testing.T, h2 bool) { expected = "text/html; charset=utf-8" ) - cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { - // Use io.Copy from a bytes.Buffer to trigger ReadFrom. - buf := bytes.NewBuffer([]byte(input)) - n, err := io.Copy(w, buf) - if int(n) != len(input) || err != nil { - t.Errorf("io.Copy(w, %q) = %v, %v want %d, nil", input, n, err, len(input)) - } - })) - defer cst.close() + for _, test := range []struct { + name string + handler func(ResponseWriter, *Request) + }{{ + name: "write", + handler: func(w ResponseWriter, r *Request) { + // Write the whole input at once. + n, err := w.Write([]byte(input)) + if int(n) != len(input) || err != nil { + t.Errorf("w.Write(%q) = %v, %v want %d, nil", input, n, err, len(input)) + } + }, + }, { + name: "write one byte at a time", + handler: func(w ResponseWriter, r *Request) { + // Write the input one byte at a time. + buf := []byte(input) + for i := range buf { + n, err := w.Write(buf[i : i+1]) + if n != 1 || err != nil { + t.Errorf("w.Write(%q) = %v, %v want 1, nil", input, n, err) + } + } + }, + }, { + name: "copy from Reader", + handler: func(w ResponseWriter, r *Request) { + // Use io.Copy from a plain Reader. + type readerOnly struct{ io.Reader } + buf := bytes.NewBuffer([]byte(input)) + n, err := io.Copy(w, readerOnly{buf}) + if int(n) != len(input) || err != nil { + t.Errorf("io.Copy(w, %q) = %v, %v want %d, nil", input, n, err, len(input)) + } + }, + }, { + name: "copy from bytes.Buffer", + handler: func(w ResponseWriter, r *Request) { + // Use io.Copy from a bytes.Buffer to trigger ReadFrom. + buf := bytes.NewBuffer([]byte(input)) + n, err := io.Copy(w, buf) + if int(n) != len(input) || err != nil { + t.Errorf("io.Copy(w, %q) = %v, %v want %d, nil", input, n, err, len(input)) + } + }, + }, { + name: "copy one byte at a time", + handler: func(w ResponseWriter, r *Request) { + // Use io.Copy from a Reader that returns one byte at a time. + n, err := io.Copy(w, &byteAtATimeReader{[]byte(input)}) + if int(n) != len(input) || err != nil { + t.Errorf("io.Copy(w, %q) = %v, %v want %d, nil", input, n, err, len(input)) + } + }, + }} { + t.Run(test.name, func(t *testing.T) { + cst := newClientServerTest(t, h2, HandlerFunc(test.handler)) + defer cst.close() + + resp, err := cst.c.Get(cst.ts.URL) + if err != nil { + t.Fatalf("Get: %v", err) + } + if ct := resp.Header.Get("Content-Type"); ct != expected { + t.Errorf("Content-Type = %q, want %q", ct, expected) + } + if want, got := resp.Header.Get("Content-Length"), fmt.Sprint(len(input)); want != got { + t.Errorf("Content-Length = %q, want %q", want, got) + } + data, err := io.ReadAll(resp.Body) + if err != nil { + t.Errorf("reading body: %v", err) + } else if !bytes.Equal(data, []byte(input)) { + t.Errorf("data is %q, want %q", data, input) + } + resp.Body.Close() + + }) - resp, err := cst.c.Get(cst.ts.URL) - if err != nil { - t.Fatalf("Get: %v", err) - } - if ct := resp.Header.Get("Content-Type"); ct != expected { - t.Errorf("Content-Type = %q, want %q", ct, expected) - } - data, err := io.ReadAll(resp.Body) - if err != nil { - t.Errorf("reading body: %v", err) - } else if !bytes.Equal(data, []byte(input)) { - t.Errorf("data is %q, want %q", data, input) } - resp.Body.Close() } func TestSniffWriteSize_h1(t *testing.T) { testSniffWriteSize(t, h1Mode) } diff --git a/libgo/go/net/http/transfer.go b/libgo/go/net/http/transfer.go index fbb0c39..85c2e5a 100644 --- a/libgo/go/net/http/transfer.go +++ b/libgo/go/net/http/transfer.go @@ -12,6 +12,7 @@ import ( "io" "net/http/httptrace" "net/http/internal" + "net/http/internal/ascii" "net/textproto" "reflect" "sort" @@ -638,7 +639,7 @@ func (t *transferReader) parseTransferEncoding() error { if len(raw) != 1 { return &unsupportedTEError{fmt.Sprintf("too many transfer encodings: %q", raw)} } - if strings.ToLower(textproto.TrimString(raw[0])) != "chunked" { + if !ascii.EqualFold(textproto.TrimString(raw[0]), "chunked") { return &unsupportedTEError{fmt.Sprintf("unsupported transfer encoding: %q", raw[0])} } diff --git a/libgo/go/net/http/transport.go b/libgo/go/net/http/transport.go index 0aa4827..309194e 100644 --- a/libgo/go/net/http/transport.go +++ b/libgo/go/net/http/transport.go @@ -21,6 +21,7 @@ import ( "log" "net" "net/http/httptrace" + "net/http/internal/ascii" "net/textproto" "net/url" "os" @@ -426,6 +427,7 @@ func (t *Transport) onceSetNextProtoDefaults() { // // The environment values may be either a complete URL or a // "host[:port]", in which case the "http" scheme is assumed. +// The schemes "http", "https", and "socks5" are supported. // An error is returned if the value is a different form. // // A nil URL and nil error are returned if no proxy is defined in the @@ -786,10 +788,12 @@ func (t *Transport) CancelRequest(req *Request) { // Cancel an in-flight request, recording the error value. // Returns whether the request was canceled. func (t *Transport) cancelRequest(key cancelKey, err error) bool { + // This function must not return until the cancel func has completed. + // See: https://golang.org/issue/34658 t.reqMu.Lock() + defer t.reqMu.Unlock() cancel := t.reqCanceler[key] delete(t.reqCanceler, key) - t.reqMu.Unlock() if cancel != nil { cancel(err) } @@ -1185,7 +1189,7 @@ type wantConn struct { // hooks for testing to know when dials are done // beforeDial is called in the getConn goroutine when the dial is queued. - // afterDial is called when the dial is completed or cancelled. + // afterDial is called when the dial is completed or canceled. beforeDial func() afterDial func() @@ -1373,7 +1377,7 @@ func (t *Transport) getConn(treq *transportRequest, cm connectMethod) (pc *persi trace.GotConn(httptrace.GotConnInfo{Conn: w.pc.conn, Reused: w.pc.isReused()}) } if w.err != nil { - // If the request has been cancelled, that's probably + // If the request has been canceled, that's probably // what caused w.err; if so, prefer to return the // cancellation error (see golang.org/issue/16049). select { @@ -1435,7 +1439,7 @@ func (t *Transport) queueForDial(w *wantConn) { // dialConnFor dials on behalf of w and delivers the result to w. // dialConnFor has received permission to dial w.cm and is counted in t.connCount[w.cm.key()]. -// If the dial is cancelled or unsuccessful, dialConnFor decrements t.connCount[w.cm.key()]. +// If the dial is canceled or unsuccessful, dialConnFor decrements t.connCount[w.cm.key()]. func (t *Transport) dialConnFor(w *wantConn) { defer w.afterDial() @@ -1505,7 +1509,7 @@ func (t *Transport) decConnsPerHost(key connectMethodKey) { // Add TLS to a persistent connection, i.e. negotiate a TLS session. If pconn is already a TLS // tunnel, this function establishes a nested TLS session inside the encrypted channel. // The remote endpoint's name may be overridden by TLSClientConfig.ServerName. -func (pconn *persistConn) addTLS(name string, trace *httptrace.ClientTrace) error { +func (pconn *persistConn) addTLS(ctx context.Context, name string, trace *httptrace.ClientTrace) error { // Initiate TLS and check remote host name against certificate. cfg := cloneTLSConfig(pconn.t.TLSClientConfig) if cfg.ServerName == "" { @@ -1527,7 +1531,7 @@ func (pconn *persistConn) addTLS(name string, trace *httptrace.ClientTrace) erro if trace != nil && trace.TLSHandshakeStart != nil { trace.TLSHandshakeStart() } - err := tlsConn.Handshake() + err := tlsConn.HandshakeContext(ctx) if timer != nil { timer.Stop() } @@ -1583,7 +1587,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers if trace != nil && trace.TLSHandshakeStart != nil { trace.TLSHandshakeStart() } - if err := tc.Handshake(); err != nil { + if err := tc.HandshakeContext(ctx); err != nil { go pconn.conn.Close() if trace != nil && trace.TLSHandshakeDone != nil { trace.TLSHandshakeDone(tls.ConnectionState{}, err) @@ -1607,7 +1611,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers if firstTLSHost, _, err = net.SplitHostPort(cm.addr()); err != nil { return nil, wrapErr(err) } - if err = pconn.addTLS(firstTLSHost, trace); err != nil { + if err = pconn.addTLS(ctx, firstTLSHost, trace); err != nil { return nil, wrapErr(err) } } @@ -1721,7 +1725,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers } if cm.proxyURL != nil && cm.targetScheme == "https" { - if err := pconn.addTLS(cm.tlsHost(), trace); err != nil { + if err := pconn.addTLS(ctx, cm.tlsHost(), trace); err != nil { return nil, err } } @@ -2183,7 +2187,7 @@ func (pc *persistConn) readLoop() { } resp.Body = body - if rc.addedGzip && strings.EqualFold(resp.Header.Get("Content-Encoding"), "gzip") { + if rc.addedGzip && ascii.EqualFold(resp.Header.Get("Content-Encoding"), "gzip") { resp.Body = &gzipReader{body: body} resp.Header.Del("Content-Encoding") resp.Header.Del("Content-Length") diff --git a/libgo/go/net/http/transport_internal_test.go b/libgo/go/net/http/transport_internal_test.go index 1097ffd..1cce272 100644 --- a/libgo/go/net/http/transport_internal_test.go +++ b/libgo/go/net/http/transport_internal_test.go @@ -12,7 +12,7 @@ import ( "errors" "io" "net" - "net/http/internal" + "net/http/internal/testcert" "strings" "testing" ) @@ -191,7 +191,7 @@ func (f roundTripFunc) RoundTrip(r *Request) (*Response, error) { // Issue 25009 func TestTransportBodyAltRewind(t *testing.T) { - cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey) + cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey) if err != nil { t.Fatal(err) } diff --git a/libgo/go/net/http/transport_test.go b/libgo/go/net/http/transport_test.go index d0202c0..cae5464 100644 --- a/libgo/go/net/http/transport_test.go +++ b/libgo/go/net/http/transport_test.go @@ -30,7 +30,7 @@ import ( "net/http/httptest" "net/http/httptrace" "net/http/httputil" - "net/http/internal" + "net/http/internal/testcert" "net/textproto" "net/url" "os" @@ -626,12 +626,15 @@ func TestTransportMaxConnsPerHost(t *testing.T) { t.Fatalf("ExportHttp2ConfigureTransport: %v", err) } - connCh := make(chan net.Conn, 1) + mu := sync.Mutex{} + var conns []net.Conn var dialCnt, gotConnCnt, tlsHandshakeCnt int32 tr.Dial = func(network, addr string) (net.Conn, error) { atomic.AddInt32(&dialCnt, 1) c, err := net.Dial(network, addr) - connCh <- c + mu.Lock() + defer mu.Unlock() + conns = append(conns, c) return c, err } @@ -685,7 +688,12 @@ func TestTransportMaxConnsPerHost(t *testing.T) { t.FailNow() } - (<-connCh).Close() + mu.Lock() + for _, c := range conns { + c.Close() + } + conns = nil + mu.Unlock() tr.CloseIdleConnections() doReq() @@ -3738,7 +3746,7 @@ func TestTransportDialTLSContext(t *testing.T) { if err != nil { return nil, err } - return c, c.Handshake() + return c, c.HandshakeContext(ctx) } req, err := NewRequest("GET", ts.URL, nil) @@ -4295,7 +4303,7 @@ func TestTransportReuseConnEmptyResponseBody(t *testing.T) { // Issue 13839 func TestNoCrashReturningTransportAltConn(t *testing.T) { - cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey) + cert, err := tls.X509KeyPair(testcert.LocalhostCert, testcert.LocalhostKey) if err != nil { t.Fatal(err) } diff --git a/libgo/go/net/http/triv.go b/libgo/go/net/http/triv.go index 23e65d5..4dc6240 100644 --- a/libgo/go/net/http/triv.go +++ b/libgo/go/net/http/triv.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package main diff --git a/libgo/go/net/interface.go b/libgo/go/net/interface.go index 914aaa0..0e5d320 100644 --- a/libgo/go/net/interface.go +++ b/libgo/go/net/interface.go @@ -6,6 +6,7 @@ package net import ( "errors" + "internal/itoa" "sync" "time" ) @@ -230,7 +231,7 @@ func (zc *ipv6ZoneCache) name(index int) string { zoneCache.RUnlock() } if !ok { // last resort - name = uitoa(uint(index)) + name = itoa.Uitoa(uint(index)) } return name } diff --git a/libgo/go/net/interface_bsd.go b/libgo/go/net/interface_bsd.go index d791cb3..7578b1a 100644 --- a/libgo/go/net/interface_bsd.go +++ b/libgo/go/net/interface_bsd.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || netbsd || openbsd // +build darwin dragonfly freebsd netbsd openbsd package net diff --git a/libgo/go/net/interface_bsd_test.go b/libgo/go/net/interface_bsd_test.go index 947dde7..8d0d9c3 100644 --- a/libgo/go/net/interface_bsd_test.go +++ b/libgo/go/net/interface_bsd_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || netbsd || openbsd // +build darwin dragonfly freebsd netbsd openbsd package net diff --git a/libgo/go/net/interface_bsdvar.go b/libgo/go/net/interface_bsdvar.go index a809b5f..6230e0b 100644 --- a/libgo/go/net/interface_bsdvar.go +++ b/libgo/go/net/interface_bsdvar.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build dragonfly || netbsd || openbsd // +build dragonfly netbsd openbsd package net diff --git a/libgo/go/net/interface_freebsd.go b/libgo/go/net/interface_freebsd.go index 45badd6..2b51fcb 100644 --- a/libgo/go/net/interface_freebsd.go +++ b/libgo/go/net/interface_freebsd.go @@ -16,9 +16,9 @@ func interfaceMessages(ifindex int) ([]route.Message, error) { if err != nil { typ = route.RIBType(syscall.NET_RT_IFLIST) rib, err = route.FetchRIB(syscall.AF_UNSPEC, typ, ifindex) - } - if err != nil { - return nil, err + if err != nil { + return nil, err + } } return route.ParseRIB(typ, rib) } diff --git a/libgo/go/net/interface_plan9.go b/libgo/go/net/interface_plan9.go index 31bbaca..957975c 100644 --- a/libgo/go/net/interface_plan9.go +++ b/libgo/go/net/interface_plan9.go @@ -6,6 +6,7 @@ package net import ( "errors" + "internal/itoa" "os" ) @@ -38,8 +39,8 @@ func interfaceTable(ifindex int) ([]Interface, error) { func readInterface(i int) (*Interface, error) { ifc := &Interface{ - Index: i + 1, // Offset the index by one to suit the contract - Name: netdir + "/ipifc/" + itoa(i), // Name is the full path to the interface path in plan9 + Index: i + 1, // Offset the index by one to suit the contract + Name: netdir + "/ipifc/" + itoa.Itoa(i), // Name is the full path to the interface path in plan9 } ifcstat := ifc.Name + "/status" diff --git a/libgo/go/net/interface_stub.go b/libgo/go/net/interface_stub.go index 437b9eb..1075e36 100644 --- a/libgo/go/net/interface_stub.go +++ b/libgo/go/net/interface_stub.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build hurd || (js && wasm) // +build hurd js,wasm package net diff --git a/libgo/go/net/interface_test.go b/libgo/go/net/interface_test.go index b2ef21e..754db36 100644 --- a/libgo/go/net/interface_test.go +++ b/libgo/go/net/interface_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net diff --git a/libgo/go/net/interface_unix_test.go b/libgo/go/net/interface_unix_test.go index bf41a0fb..0d69fa5 100644 --- a/libgo/go/net/interface_unix_test.go +++ b/libgo/go/net/interface_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd // +build darwin dragonfly freebsd linux netbsd openbsd package net diff --git a/libgo/go/net/internal/socktest/main_test.go b/libgo/go/net/internal/socktest/main_test.go index 3b0a48a..8af85d3 100644 --- a/libgo/go/net/internal/socktest/main_test.go +++ b/libgo/go/net/internal/socktest/main_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js && !plan9 // +build !js,!plan9 package socktest_test diff --git a/libgo/go/net/internal/socktest/main_unix_test.go b/libgo/go/net/internal/socktest/main_unix_test.go index 4d9d414..6aa8875 100644 --- a/libgo/go/net/internal/socktest/main_unix_test.go +++ b/libgo/go/net/internal/socktest/main_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js && !plan9 && !windows // +build !js,!plan9,!windows package socktest_test diff --git a/libgo/go/net/internal/socktest/switch_posix.go b/libgo/go/net/internal/socktest/switch_posix.go index 863edef..cda74e8 100644 --- a/libgo/go/net/internal/socktest/switch_posix.go +++ b/libgo/go/net/internal/socktest/switch_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 // +build !plan9 package socktest diff --git a/libgo/go/net/internal/socktest/switch_stub.go b/libgo/go/net/internal/socktest/switch_stub.go index 28ce72c..5aa2ece 100644 --- a/libgo/go/net/internal/socktest/switch_stub.go +++ b/libgo/go/net/internal/socktest/switch_stub.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build plan9 // +build plan9 package socktest diff --git a/libgo/go/net/internal/socktest/switch_unix.go b/libgo/go/net/internal/socktest/switch_unix.go index 4c037ba..be9ef6d 100644 --- a/libgo/go/net/internal/socktest/switch_unix.go +++ b/libgo/go/net/internal/socktest/switch_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package socktest diff --git a/libgo/go/net/internal/socktest/sys_cloexec.go b/libgo/go/net/internal/socktest/sys_cloexec.go index b13ba57..5e95896 100644 --- a/libgo/go/net/internal/socktest/sys_cloexec.go +++ b/libgo/go/net/internal/socktest/sys_cloexec.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build dragonfly || freebsd || hurd || illumos || linux || netbsd || openbsd // +build dragonfly freebsd hurd illumos linux netbsd openbsd package socktest diff --git a/libgo/go/net/internal/socktest/sys_unix.go b/libgo/go/net/internal/socktest/sys_unix.go index fbbffc6..39f3dbc 100644 --- a/libgo/go/net/internal/socktest/sys_unix.go +++ b/libgo/go/net/internal/socktest/sys_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package socktest diff --git a/libgo/go/net/ip.go b/libgo/go/net/ip.go index c00fe8e..38e1aa2 100644 --- a/libgo/go/net/ip.go +++ b/libgo/go/net/ip.go @@ -12,7 +12,10 @@ package net -import "internal/bytealg" +import ( + "internal/bytealg" + "internal/itoa" +) // IP address lengths (bytes). const ( @@ -125,6 +128,25 @@ func (ip IP) IsLoopback() bool { return ip.Equal(IPv6loopback) } +// IsPrivate reports whether ip is a private address, according to +// RFC 1918 (IPv4 addresses) and RFC 4193 (IPv6 addresses). +func (ip IP) IsPrivate() bool { + if ip4 := ip.To4(); ip4 != nil { + // Following RFC 1918, Section 3. Private Address Space which says: + // The Internet Assigned Numbers Authority (IANA) has reserved the + // following three blocks of the IP address space for private internets: + // 10.0.0.0 - 10.255.255.255 (10/8 prefix) + // 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) + // 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) + return ip4[0] == 10 || + (ip4[0] == 172 && ip4[1]&0xf0 == 16) || + (ip4[0] == 192 && ip4[1] == 168) + } + // Following RFC 4193, Section 8. IANA Considerations which says: + // The IANA has assigned the FC00::/7 prefix to "Unique Local Unicast". + return len(ip) == IPv6len && ip[0]&0xfe == 0xfc +} + // IsMulticast reports whether ip is a multicast address. func (ip IP) IsMulticast() bool { if ip4 := ip.To4(); ip4 != nil { @@ -531,7 +553,7 @@ func (n *IPNet) String() string { if l == -1 { return nn.String() + "/" + m.String() } - return nn.String() + "/" + uitoa(uint(l)) + return nn.String() + "/" + itoa.Uitoa(uint(l)) } // Parse IPv4 address (d.d.d.d). @@ -552,6 +574,10 @@ func parseIPv4(s string) IP { if !ok || n > 0xFF { return nil } + if c > 1 && s[0] == '0' { + // Reject non-zero components with leading zeroes. + return nil + } s = s[c:] p[i] = byte(n) } diff --git a/libgo/go/net/ip_test.go b/libgo/go/net/ip_test.go index a5fc5e6..5bbda60 100644 --- a/libgo/go/net/ip_test.go +++ b/libgo/go/net/ip_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net @@ -20,9 +21,7 @@ var parseIPTests = []struct { }{ {"127.0.1.2", IPv4(127, 0, 1, 2)}, {"127.0.0.1", IPv4(127, 0, 0, 1)}, - {"127.001.002.003", IPv4(127, 1, 2, 3)}, {"::ffff:127.1.2.3", IPv4(127, 1, 2, 3)}, - {"::ffff:127.001.002.003", IPv4(127, 1, 2, 3)}, {"::ffff:7f01:0203", IPv4(127, 1, 2, 3)}, {"0:0:0:0:0000:ffff:127.1.2.3", IPv4(127, 1, 2, 3)}, {"0:0:0:0:000000:ffff:127.1.2.3", IPv4(127, 1, 2, 3)}, @@ -42,6 +41,11 @@ var parseIPTests = []struct { {"fe80::1%911", nil}, {"", nil}, {"a1:a2:a3:a4::b1:b2:b3:b4", nil}, // Issue 6628 + {"127.001.002.003", nil}, + {"::ffff:127.001.002.003", nil}, + {"123.000.000.000", nil}, + {"1.2..4", nil}, + {"0123.0.0.1", nil}, } func TestParseIP(t *testing.T) { @@ -357,6 +361,7 @@ var parseCIDRTests = []struct { {"0.0.-2.0/32", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.-2.0/32"}}, {"0.0.0.-3/32", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.0.-3/32"}}, {"0.0.0.0/-0", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.0.0/-0"}}, + {"127.000.000.001/32", nil, nil, &ParseError{Type: "CIDR address", Text: "127.000.000.001/32"}}, {"", nil, nil, &ParseError{Type: "CIDR address", Text: ""}}, } @@ -690,6 +695,28 @@ var ipAddrScopeTests = []struct { {IP.IsGlobalUnicast, IP{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false}, {IP.IsGlobalUnicast, IP{0xff, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false}, {IP.IsGlobalUnicast, nil, false}, + {IP.IsPrivate, nil, false}, + {IP.IsPrivate, IPv4(1, 1, 1, 1), false}, + {IP.IsPrivate, IPv4(9, 255, 255, 255), false}, + {IP.IsPrivate, IPv4(10, 0, 0, 0), true}, + {IP.IsPrivate, IPv4(10, 255, 255, 255), true}, + {IP.IsPrivate, IPv4(11, 0, 0, 0), false}, + {IP.IsPrivate, IPv4(172, 15, 255, 255), false}, + {IP.IsPrivate, IPv4(172, 16, 0, 0), true}, + {IP.IsPrivate, IPv4(172, 16, 255, 255), true}, + {IP.IsPrivate, IPv4(172, 23, 18, 255), true}, + {IP.IsPrivate, IPv4(172, 31, 255, 255), true}, + {IP.IsPrivate, IPv4(172, 31, 0, 0), true}, + {IP.IsPrivate, IPv4(172, 32, 0, 0), false}, + {IP.IsPrivate, IPv4(192, 167, 255, 255), false}, + {IP.IsPrivate, IPv4(192, 168, 0, 0), true}, + {IP.IsPrivate, IPv4(192, 168, 255, 255), true}, + {IP.IsPrivate, IPv4(192, 169, 0, 0), false}, + {IP.IsPrivate, IP{0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, false}, + {IP.IsPrivate, IP{0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, true}, + {IP.IsPrivate, IP{0xfc, 0xff, 0x12, 0, 0, 0, 0, 0x44, 0, 0, 0, 0, 0, 0, 0, 0}, true}, + {IP.IsPrivate, IP{0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, true}, + {IP.IsPrivate, IP{0xfe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false}, } func name(f interface{}) string { diff --git a/libgo/go/net/iprawsock_posix.go b/libgo/go/net/iprawsock_posix.go index fdb3913..ffc437c 100644 --- a/libgo/go/net/iprawsock_posix.go +++ b/libgo/go/net/iprawsock_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows package net @@ -74,7 +75,7 @@ func stripIPv4Header(n int, b []byte) int { func (c *IPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) { var sa syscall.Sockaddr - n, oobn, flags, sa, err = c.fd.readMsg(b, oob) + n, oobn, flags, sa, err = c.fd.readMsg(b, oob, 0) switch sa := sa.(type) { case *syscall.SockaddrInet4: addr = &IPAddr{IP: sa.Addr[0:]} diff --git a/libgo/go/net/iprawsock_test.go b/libgo/go/net/iprawsock_test.go index 8e3543d..a96448e 100644 --- a/libgo/go/net/iprawsock_test.go +++ b/libgo/go/net/iprawsock_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net diff --git a/libgo/go/net/ipsock.go b/libgo/go/net/ipsock.go index 7d0684d..0f5da25 100644 --- a/libgo/go/net/ipsock.go +++ b/libgo/go/net/ipsock.go @@ -7,6 +7,7 @@ package net import ( "context" "internal/bytealg" + "runtime" "sync" ) @@ -44,6 +45,13 @@ func supportsIPv6() bool { // IPv4 address inside an IPv6 address at transport layer // protocols. See RFC 4291, RFC 4038 and RFC 3493. func supportsIPv4map() bool { + // Some operating systems provide no support for mapping IPv4 + // addresses to IPv6, and a runtime check is unnecessary. + switch runtime.GOOS { + case "dragonfly", "openbsd": + return false + } + ipStackCaps.Once.Do(ipStackCaps.probe) return ipStackCaps.ipv4MappedIPv6Enabled } diff --git a/libgo/go/net/ipsock_plan9.go b/libgo/go/net/ipsock_plan9.go index 7a4b7a6..4328743 100644 --- a/libgo/go/net/ipsock_plan9.go +++ b/libgo/go/net/ipsock_plan9.go @@ -7,12 +7,13 @@ package net import ( "context" "internal/bytealg" + "internal/itoa" "io/fs" "os" "syscall" ) -// Probe probes IPv4, IPv6 and IPv4-mapped IPv6 communication +// probe probes IPv4, IPv6 and IPv4-mapped IPv6 communication // capabilities. // // Plan 9 uses IPv6 natively, see ip(3). @@ -336,9 +337,9 @@ func plan9LocalAddr(addr Addr) string { if port == 0 { return "" } - return itoa(port) + return itoa.Itoa(port) } - return ip.String() + "!" + itoa(port) + return ip.String() + "!" + itoa.Itoa(port) } func hangupCtlWrite(ctx context.Context, proto string, ctl *os.File, msg string) error { diff --git a/libgo/go/net/ipsock_posix.go b/libgo/go/net/ipsock_posix.go index 84e72d5..cdd191a 100644 --- a/libgo/go/net/ipsock_posix.go +++ b/libgo/go/net/ipsock_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows package net @@ -13,13 +14,13 @@ import ( "syscall" ) -// Probe probes IPv4, IPv6 and IPv4-mapped IPv6 communication +// probe probes IPv4, IPv6 and IPv4-mapped IPv6 communication // capabilities which are controlled by the IPV6_V6ONLY socket option // and kernel configuration. // // Should we try to use the IPv4 socket interface if we're only // dealing with IPv4 sockets? As long as the host system understands -// IPv4-mapped IPv6, it's okay to pass IPv4-mapeed IPv6 addresses to +// IPv4-mapped IPv6, it's okay to pass IPv4-mapped IPv6 addresses to // the IPv6 interface. That simplifies our code and is most // general. Unfortunately, we need to run on kernels built without // IPv6 support too. So probe the kernel to figure it out. diff --git a/libgo/go/net/listen_test.go b/libgo/go/net/listen_test.go index d8c7209..b1dce29 100644 --- a/libgo/go/net/listen_test.go +++ b/libgo/go/net/listen_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js && !plan9 // +build !js,!plan9 package net diff --git a/libgo/go/net/lookup.go b/libgo/go/net/lookup.go index 0660268..d350ef7 100644 --- a/libgo/go/net/lookup.go +++ b/libgo/go/net/lookup.go @@ -166,6 +166,9 @@ func (r *Resolver) getLookupGroup() *singleflight.Group { // LookupHost looks up the given host using the local resolver. // It returns a slice of that host's addresses. +// +// LookupHost uses context.Background internally; to specify the context, use +// Resolver.LookupHost. func LookupHost(host string) (addrs []string, err error) { return DefaultResolver.LookupHost(context.Background(), host) } @@ -353,6 +356,9 @@ func ipAddrsEface(addrs []IPAddr) []interface{} { } // LookupPort looks up the port for the given network and service. +// +// LookupPort uses context.Background internally; to specify the context, use +// Resolver.LookupPort. func LookupPort(network, service string) (port int, err error) { return DefaultResolver.LookupPort(context.Background(), network, service) } @@ -392,6 +398,9 @@ func (r *Resolver) LookupPort(ctx context.Context, network, service string) (por // // The returned canonical name is validated to be a properly // formatted presentation-format domain name. +// +// LookupCNAME uses context.Background internally; to specify the context, use +// Resolver.LookupCNAME. func LookupCNAME(host string) (cname string, err error) { return DefaultResolver.LookupCNAME(context.Background(), host) } @@ -415,7 +424,7 @@ func (r *Resolver) LookupCNAME(ctx context.Context, host string) (string, error) return "", err } if !isDomainName(cname) { - return "", &DNSError{Err: "CNAME target is invalid", Name: host} + return "", &DNSError{Err: errMalformedDNSRecordsDetail, Name: host} } return cname, nil } @@ -431,7 +440,9 @@ func (r *Resolver) LookupCNAME(ctx context.Context, host string) (string, error) // and proto are empty strings, LookupSRV looks up name directly. // // The returned service names are validated to be properly -// formatted presentation-format domain names. +// formatted presentation-format domain names. If the response contains +// invalid names, those records are filtered out and an error +// will be returned alongside the the remaining results, if any. func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) { return DefaultResolver.LookupSRV(context.Background(), service, proto, name) } @@ -447,7 +458,9 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err // and proto are empty strings, LookupSRV looks up name directly. // // The returned service names are validated to be properly -// formatted presentation-format domain names. +// formatted presentation-format domain names. If the response contains +// invalid names, those records are filtered out and an error +// will be returned alongside the the remaining results, if any. func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) { cname, addrs, err := r.lookupSRV(ctx, service, proto, name) if err != nil { @@ -456,21 +469,31 @@ func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) ( if cname != "" && !isDomainName(cname) { return "", nil, &DNSError{Err: "SRV header name is invalid", Name: name} } + filteredAddrs := make([]*SRV, 0, len(addrs)) for _, addr := range addrs { if addr == nil { continue } if !isDomainName(addr.Target) { - return "", nil, &DNSError{Err: "SRV target is invalid", Name: name} + continue } + filteredAddrs = append(filteredAddrs, addr) } - return cname, addrs, nil + if len(addrs) != len(filteredAddrs) { + return cname, filteredAddrs, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name} + } + return cname, filteredAddrs, nil } // LookupMX returns the DNS MX records for the given domain name sorted by preference. // // The returned mail server names are validated to be properly -// formatted presentation-format domain names. +// formatted presentation-format domain names. If the response contains +// invalid names, those records are filtered out and an error +// will be returned alongside the the remaining results, if any. +// +// LookupMX uses context.Background internally; to specify the context, use +// Resolver.LookupMX. func LookupMX(name string) ([]*MX, error) { return DefaultResolver.LookupMX(context.Background(), name) } @@ -478,27 +501,41 @@ func LookupMX(name string) ([]*MX, error) { // LookupMX returns the DNS MX records for the given domain name sorted by preference. // // The returned mail server names are validated to be properly -// formatted presentation-format domain names. +// formatted presentation-format domain names. If the response contains +// invalid names, those records are filtered out and an error +// will be returned alongside the the remaining results, if any. func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) { records, err := r.lookupMX(ctx, name) if err != nil { return nil, err } + filteredMX := make([]*MX, 0, len(records)) for _, mx := range records { if mx == nil { continue } - if !isDomainName(mx.Host) { - return nil, &DNSError{Err: "MX target is invalid", Name: name} + // Bypass the hostname validity check for targets which contain only a dot, + // as this is used to represent a 'Null' MX record. + if mx.Host != "." && !isDomainName(mx.Host) { + continue } + filteredMX = append(filteredMX, mx) + } + if len(records) != len(filteredMX) { + return filteredMX, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name} } - return records, nil + return filteredMX, nil } // LookupNS returns the DNS NS records for the given domain name. // // The returned name server names are validated to be properly -// formatted presentation-format domain names. +// formatted presentation-format domain names. If the response contains +// invalid names, those records are filtered out and an error +// will be returned alongside the the remaining results, if any. +// +// LookupNS uses context.Background internally; to specify the context, use +// Resolver.LookupNS. func LookupNS(name string) ([]*NS, error) { return DefaultResolver.LookupNS(context.Background(), name) } @@ -506,24 +543,34 @@ func LookupNS(name string) ([]*NS, error) { // LookupNS returns the DNS NS records for the given domain name. // // The returned name server names are validated to be properly -// formatted presentation-format domain names. +// formatted presentation-format domain names. If the response contains +// invalid names, those records are filtered out and an error +// will be returned alongside the the remaining results, if any. func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) { records, err := r.lookupNS(ctx, name) if err != nil { return nil, err } + filteredNS := make([]*NS, 0, len(records)) for _, ns := range records { if ns == nil { continue } if !isDomainName(ns.Host) { - return nil, &DNSError{Err: "NS target is invalid", Name: name} + continue } + filteredNS = append(filteredNS, ns) } - return records, nil + if len(records) != len(filteredNS) { + return filteredNS, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name} + } + return filteredNS, nil } // LookupTXT returns the DNS TXT records for the given domain name. +// +// LookupTXT uses context.Background internally; to specify the context, use +// Resolver.LookupTXT. func LookupTXT(name string) ([]string, error) { return DefaultResolver.lookupTXT(context.Background(), name) } @@ -537,10 +584,14 @@ func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error) // of names mapping to that address. // // The returned names are validated to be properly formatted presentation-format -// domain names. +// domain names. If the response contains invalid names, those records are filtered +// out and an error will be returned alongside the the remaining results, if any. // // When using the host C library resolver, at most one result will be // returned. To bypass the host resolver, use a custom Resolver. +// +// LookupAddr uses context.Background internally; to specify the context, use +// Resolver.LookupAddr. func LookupAddr(addr string) (names []string, err error) { return DefaultResolver.LookupAddr(context.Background(), addr) } @@ -549,16 +600,26 @@ func LookupAddr(addr string) (names []string, err error) { // of names mapping to that address. // // The returned names are validated to be properly formatted presentation-format -// domain names. +// domain names. If the response contains invalid names, those records are filtered +// out and an error will be returned alongside the the remaining results, if any. func (r *Resolver) LookupAddr(ctx context.Context, addr string) ([]string, error) { names, err := r.lookupAddr(ctx, addr) if err != nil { return nil, err } + filteredNames := make([]string, 0, len(names)) for _, name := range names { - if !isDomainName(name) { - return nil, &DNSError{Err: "PTR target is invalid", Name: addr} + if isDomainName(name) { + filteredNames = append(filteredNames, name) } } - return names, nil + if len(names) != len(filteredNames) { + return filteredNames, &DNSError{Err: errMalformedDNSRecordsDetail, Name: addr} + } + return filteredNames, nil } + +// errMalformedDNSRecordsDetail is the DNSError detail which is returned when a Resolver.Lookup... +// method recieves DNS records which contain invalid DNS names. This may be returned alongside +// results which have had the malformed records filtered out. +var errMalformedDNSRecordsDetail = "DNS response contained records which contain invalid names" diff --git a/libgo/go/net/lookup_fake.go b/libgo/go/net/lookup_fake.go index 3b3c39b..f4fcaed 100644 --- a/libgo/go/net/lookup_fake.go +++ b/libgo/go/net/lookup_fake.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package net diff --git a/libgo/go/net/lookup_plan9.go b/libgo/go/net/lookup_plan9.go index 6a2d48e..75c18b3 100644 --- a/libgo/go/net/lookup_plan9.go +++ b/libgo/go/net/lookup_plan9.go @@ -8,6 +8,7 @@ import ( "context" "errors" "internal/bytealg" + "internal/itoa" "io" "os" ) @@ -84,7 +85,7 @@ func queryCS1(ctx context.Context, net string, ip IP, port int) (clone, dest str if len(ip) != 0 && !ip.IsUnspecified() { ips = ip.String() } - lines, err := queryCS(ctx, net, ips, itoa(port)) + lines, err := queryCS(ctx, net, ips, itoa.Itoa(port)) if err != nil { return } @@ -308,7 +309,7 @@ func (*Resolver) lookupTXT(ctx context.Context, name string) (txt []string, err } for _, line := range lines { if i := bytealg.IndexByteString(line, '\t'); i >= 0 { - txt = append(txt, absDomainName([]byte(line[i+1:]))) + txt = append(txt, line[i+1:]) } } return diff --git a/libgo/go/net/lookup_test.go b/libgo/go/net/lookup_test.go index 32a0d37..3faaf00 100644 --- a/libgo/go/net/lookup_test.go +++ b/libgo/go/net/lookup_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net diff --git a/libgo/go/net/lookup_unix.go b/libgo/go/net/lookup_unix.go index c27b1a0..05f49b0 100644 --- a/libgo/go/net/lookup_unix.go +++ b/libgo/go/net/lookup_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package net @@ -89,7 +90,7 @@ func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs []IPAddr, err error) { if r.preferGo() { - return r.goLookupIP(ctx, host) + return r.goLookupIP(ctx, network, host) } order := systemConf().hostLookupOrder(r, host) if order == hostLookupCgo { @@ -99,7 +100,7 @@ func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs [] // cgo not available (or netgo); fall back to Go's DNS resolver order = hostLookupFilesDNS } - ips, _, err := r.goLookupIPCNAMEOrder(ctx, host, order) + ips, _, err := r.goLookupIPCNAMEOrder(ctx, network, host, order) return ips, err } diff --git a/libgo/go/net/lookup_windows_test.go b/libgo/go/net/lookup_windows_test.go index 62b61ed..aa95501 100644 --- a/libgo/go/net/lookup_windows_test.go +++ b/libgo/go/net/lookup_windows_test.go @@ -299,7 +299,7 @@ func lookupPTR(name string) (ptr []string, err error) { ptr = make([]string, 0, 10) rx := regexp.MustCompile(`(?m)^Pinging\s+([a-zA-Z0-9.\-]+)\s+\[.*$`) for _, ans := range rx.FindAllStringSubmatch(r, -1) { - ptr = append(ptr, ans[1]+".") + ptr = append(ptr, absDomainName([]byte(ans[1]))) } return } diff --git a/libgo/go/net/main_cloexec_test.go b/libgo/go/net/main_cloexec_test.go index d436df1..03f7d63 100644 --- a/libgo/go/net/main_cloexec_test.go +++ b/libgo/go/net/main_cloexec_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build dragonfly || freebsd || hurd || illumos || linux || netbsd || openbsd // +build dragonfly freebsd hurd illumos linux netbsd openbsd package net diff --git a/libgo/go/net/main_conf_test.go b/libgo/go/net/main_conf_test.go index a92dff5..645b267 100644 --- a/libgo/go/net/main_conf_test.go +++ b/libgo/go/net/main_conf_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js && !plan9 && !windows // +build !js,!plan9,!windows package net diff --git a/libgo/go/net/main_noconf_test.go b/libgo/go/net/main_noconf_test.go index bac84aa..bcea630 100644 --- a/libgo/go/net/main_noconf_test.go +++ b/libgo/go/net/main_noconf_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (js && wasm) || plan9 || windows // +build js,wasm plan9 windows package net diff --git a/libgo/go/net/main_posix_test.go b/libgo/go/net/main_posix_test.go index f2484f3..c9ab25a 100644 --- a/libgo/go/net/main_posix_test.go +++ b/libgo/go/net/main_posix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js && !plan9 // +build !js,!plan9 package net diff --git a/libgo/go/net/main_test.go b/libgo/go/net/main_test.go index 2d5be2e..dc17d3f 100644 --- a/libgo/go/net/main_test.go +++ b/libgo/go/net/main_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net diff --git a/libgo/go/net/main_unix_test.go b/libgo/go/net/main_unix_test.go index ef7e915..367cefc 100644 --- a/libgo/go/net/main_unix_test.go +++ b/libgo/go/net/main_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package net diff --git a/libgo/go/net/mockserver_test.go b/libgo/go/net/mockserver_test.go index 867e31e..b50a1e5 100644 --- a/libgo/go/net/mockserver_test.go +++ b/libgo/go/net/mockserver_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net diff --git a/libgo/go/net/net.go b/libgo/go/net/net.go index 4b4ed12..a7c65ff 100644 --- a/libgo/go/net/net.go +++ b/libgo/go/net/net.go @@ -539,6 +539,9 @@ type ParseError struct { func (e *ParseError) Error() string { return "invalid " + e.Type + ": " + e.Text } +func (e *ParseError) Timeout() bool { return false } +func (e *ParseError) Temporary() bool { return false } + type AddrError struct { Err string Addr string @@ -642,7 +645,7 @@ var errClosed = poll.ErrNetClosing // another goroutine before the I/O is completed. This may be wrapped // in another error, and should normally be tested using // errors.Is(err, net.ErrClosed). -var ErrClosed = errClosed +var ErrClosed error = errClosed type writerOnly struct { io.Writer @@ -733,6 +736,7 @@ func (v *Buffers) consume(n int64) { return } n -= ln0 + (*v)[0] = nil *v = (*v)[1:] } } diff --git a/libgo/go/net/net_fake.go b/libgo/go/net/net_fake.go index 0c48dd5..74fc1da 100644 --- a/libgo/go/net/net_fake.go +++ b/libgo/go/net/net_fake.go @@ -4,6 +4,7 @@ // Fake networking for js/wasm. It is intended to allow tests of other package to pass. +//go:build js && wasm // +build js,wasm package net @@ -267,7 +268,7 @@ func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) { return 0, nil, syscall.ENOSYS } -func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { +func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int, sa syscall.Sockaddr, err error) { return 0, 0, 0, nil, syscall.ENOSYS } diff --git a/libgo/go/net/net_test.go b/libgo/go/net/net_test.go index 409e140..6e7be4d 100644 --- a/libgo/go/net/net_test.go +++ b/libgo/go/net/net_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net @@ -587,3 +588,23 @@ func TestNotTemporaryRead(t *testing.T) { } withTCPConnPair(t, client, server) } + +// The various errors should implement the Error interface. +func TestErrors(t *testing.T) { + var ( + _ Error = &OpError{} + _ Error = &ParseError{} + _ Error = &AddrError{} + _ Error = UnknownNetworkError("") + _ Error = InvalidAddrError("") + _ Error = &timeoutError{} + _ Error = &DNSConfigError{} + _ Error = &DNSError{} + ) + + // ErrClosed was introduced as type error, so we can't check + // it using a declaration. + if _, ok := ErrClosed.(Error); !ok { + t.Fatal("ErrClosed does not implement Error") + } +} diff --git a/libgo/go/net/nss.go b/libgo/go/net/nss.go index 98d740f..c12ee75 100644 --- a/libgo/go/net/nss.go +++ b/libgo/go/net/nss.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package net diff --git a/libgo/go/net/nss_test.go b/libgo/go/net/nss_test.go index 53cbc4d..948b8d3 100644 --- a/libgo/go/net/nss_test.go +++ b/libgo/go/net/nss_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build darwin dragonfly freebsd hurd linux netbsd openbsd solaris package net diff --git a/libgo/go/net/packetconn_test.go b/libgo/go/net/packetconn_test.go index a377d33..aeb9845 100644 --- a/libgo/go/net/packetconn_test.go +++ b/libgo/go/net/packetconn_test.go @@ -5,6 +5,7 @@ // This file implements API tests across platforms and will never have a build // tag. +//go:build !js // +build !js package net diff --git a/libgo/go/net/parse.go b/libgo/go/net/parse.go index cdb35bb..6c230ab 100644 --- a/libgo/go/net/parse.go +++ b/libgo/go/net/parse.go @@ -172,32 +172,6 @@ func xtoi2(s string, e byte) (byte, bool) { return byte(n), ok && ei == 2 } -// Convert integer to decimal string. -func itoa(val int) string { - if val < 0 { - return "-" + uitoa(uint(-val)) - } - return uitoa(uint(val)) -} - -// Convert unsigned integer to decimal string. -func uitoa(val uint) string { - if val == 0 { // avoid string allocation - return "0" - } - var buf [20]byte // big enough for 64bit value base 10 - i := len(buf) - 1 - for val >= 10 { - q := val / 10 - buf[i] = byte('0' + val - q*10) - i-- - val = q - } - // val < 10 - buf[i] = byte('0' + val) - return string(buf[i:]) -} - // Convert i to a hexadecimal string. Leading zeros are not printed. func appendHex(dst []byte, i uint32) []byte { if i == 0 { diff --git a/libgo/go/net/port_unix.go b/libgo/go/net/port_unix.go index a3b402f..07b4cbb 100644 --- a/libgo/go/net/port_unix.go +++ b/libgo/go/net/port_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris // Read system port mappings from /etc/services diff --git a/libgo/go/net/protoconn_test.go b/libgo/go/net/protoconn_test.go index 6f83f52..fc9b386 100644 --- a/libgo/go/net/protoconn_test.go +++ b/libgo/go/net/protoconn_test.go @@ -5,6 +5,7 @@ // This file implements API tests across platforms and will never have a build // tag. +//go:build !js // +build !js package net diff --git a/libgo/go/net/rawconn_stub_test.go b/libgo/go/net/rawconn_stub_test.go index cec977f..975aa8d 100644 --- a/libgo/go/net/rawconn_stub_test.go +++ b/libgo/go/net/rawconn_stub_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (js && wasm) || plan9 // +build js,wasm plan9 package net diff --git a/libgo/go/net/rawconn_test.go b/libgo/go/net/rawconn_test.go index a08ff89..3ef7af3 100644 --- a/libgo/go/net/rawconn_test.go +++ b/libgo/go/net/rawconn_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net diff --git a/libgo/go/net/rawconn_unix_test.go b/libgo/go/net/rawconn_unix_test.go index 21527c4..77df4f8 100644 --- a/libgo/go/net/rawconn_unix_test.go +++ b/libgo/go/net/rawconn_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package net diff --git a/libgo/go/net/rpc/server.go b/libgo/go/net/rpc/server.go index 9cb9282..074c5b9 100644 --- a/libgo/go/net/rpc/server.go +++ b/libgo/go/net/rpc/server.go @@ -283,7 +283,7 @@ func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType { mtype := method.Type mname := method.Name // Method must be exported. - if method.PkgPath != "" { + if !method.IsExported() { continue } // Method needs three ins: receiver, *args, *reply. diff --git a/libgo/go/net/sendfile_stub.go b/libgo/go/net/sendfile_stub.go index 53bc53a..5753bc0 100644 --- a/libgo/go/net/sendfile_stub.go +++ b/libgo/go/net/sendfile_stub.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || (js && wasm) || netbsd || openbsd // +build aix darwin js,wasm netbsd openbsd package net diff --git a/libgo/go/net/sendfile_test.go b/libgo/go/net/sendfile_test.go index d6057fd..54e51fa 100644 --- a/libgo/go/net/sendfile_test.go +++ b/libgo/go/net/sendfile_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net @@ -13,7 +14,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "os" "runtime" "sync" @@ -366,7 +366,7 @@ func TestSendfileOnWriteTimeoutExceeded(t *testing.T) { } defer conn.Close() - n, err := io.Copy(ioutil.Discard, conn) + n, err := io.Copy(io.Discard, conn) if err != nil { t.Fatalf("expected nil error, but got %v", err) } diff --git a/libgo/go/net/sendfile_unix_alt.go b/libgo/go/net/sendfile_unix_alt.go index 8cededc..54667d6 100644 --- a/libgo/go/net/sendfile_unix_alt.go +++ b/libgo/go/net/sendfile_unix_alt.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build dragonfly || freebsd || solaris // +build dragonfly freebsd solaris package net diff --git a/libgo/go/net/server_test.go b/libgo/go/net/server_test.go index 4ac5443..7cbf152 100644 --- a/libgo/go/net/server_test.go +++ b/libgo/go/net/server_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net @@ -104,13 +105,6 @@ func TestTCPServer(t *testing.T) { if perr := parseDialError(err); perr != nil { t.Error(perr) } - if tt.taddr == "::1" && os.Getenv("GO_BUILDER_NAME") == "darwin-amd64-10_12" && os.IsTimeout(err) { - // A suspected kernel bug in macOS 10.12 occasionally results in - // "i/o timeout" errors when dialing address ::1. The errors have not - // been observed on newer versions of the OS, so we don't plan to work - // around them. See https://golang.org/issue/32919. - t.Skipf("skipping due to error on known-flaky macOS 10.12 builder: %v", err) - } t.Fatal(err) } defer c.Close() diff --git a/libgo/go/net/sock_bsd.go b/libgo/go/net/sock_bsd.go index 73fb6be..4c883ad 100644 --- a/libgo/go/net/sock_bsd.go +++ b/libgo/go/net/sock_bsd.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || netbsd || openbsd // +build darwin dragonfly freebsd netbsd openbsd package net diff --git a/libgo/go/net/sock_cloexec.go b/libgo/go/net/sock_cloexec.go index 43be6ff..cb57bb4 100644 --- a/libgo/go/net/sock_cloexec.go +++ b/libgo/go/net/sock_cloexec.go @@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// This file implements sysSocket and accept for platforms that -// provide a fast path for setting SetNonblock and CloseOnExec. +// This file implements sysSocket for platforms that provide a fast path for +// setting SetNonblock and CloseOnExec. +//go:build dragonfly || freebsd || hurd || illumos || linux || netbsd || openbsd // +build dragonfly freebsd hurd illumos linux netbsd openbsd package net diff --git a/libgo/go/net/sock_posix.go b/libgo/go/net/sock_posix.go index 8fe9bc7..8c09b0b 100644 --- a/libgo/go/net/sock_posix.go +++ b/libgo/go/net/sock_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows package net diff --git a/libgo/go/net/sock_stub.go b/libgo/go/net/sock_stub.go index 6d44f43..1e5032e 100644 --- a/libgo/go/net/sock_stub.go +++ b/libgo/go/net/sock_stub.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || hurd || (js && wasm) || solaris // +build aix hurd js,wasm solaris package net diff --git a/libgo/go/net/sockaddr_posix.go b/libgo/go/net/sockaddr_posix.go index 470d044..618d85f 100644 --- a/libgo/go/net/sockaddr_posix.go +++ b/libgo/go/net/sockaddr_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows package net diff --git a/libgo/go/net/sockopt_bsd.go b/libgo/go/net/sockopt_bsd.go index 7b8b8d9..e52fa88 100644 --- a/libgo/go/net/sockopt_bsd.go +++ b/libgo/go/net/sockopt_bsd.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || netbsd || openbsd // +build darwin dragonfly freebsd netbsd openbsd package net @@ -25,7 +26,7 @@ func setDefaultSockopts(s, family, sotype int, ipv6only bool) error { syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_PORTRANGE, syscall.IPV6_PORTRANGE_HIGH) } } - if supportsIPv4map() && family == syscall.AF_INET6 && sotype != syscall.SOCK_RAW { + if family == syscall.AF_INET6 && sotype != syscall.SOCK_RAW && supportsIPv4map() { // Allow both IP versions even if the OS default // is otherwise. Note that some operating systems // never admit this option. diff --git a/libgo/go/net/sockopt_posix.go b/libgo/go/net/sockopt_posix.go index d2cb30b..3478872 100644 --- a/libgo/go/net/sockopt_posix.go +++ b/libgo/go/net/sockopt_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows package net diff --git a/libgo/go/net/sockopt_stub.go b/libgo/go/net/sockopt_stub.go index 52624a3..99b5277 100644 --- a/libgo/go/net/sockopt_stub.go +++ b/libgo/go/net/sockopt_stub.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package net diff --git a/libgo/go/net/sockoptip_bsdvar.go b/libgo/go/net/sockoptip_bsdvar.go index c93f592..8b0b5d2 100644 --- a/libgo/go/net/sockoptip_bsdvar.go +++ b/libgo/go/net/sockoptip_bsdvar.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd netbsd openbsd solaris package net diff --git a/libgo/go/net/sockoptip_posix.go b/libgo/go/net/sockoptip_posix.go index 0ac50e3..a063e79 100644 --- a/libgo/go/net/sockoptip_posix.go +++ b/libgo/go/net/sockoptip_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows package net diff --git a/libgo/go/net/sockoptip_stub.go b/libgo/go/net/sockoptip_stub.go index 57cd289..4175922 100644 --- a/libgo/go/net/sockoptip_stub.go +++ b/libgo/go/net/sockoptip_stub.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package net diff --git a/libgo/go/net/splice_stub.go b/libgo/go/net/splice_stub.go index 9106cb2..ce2e904 100644 --- a/libgo/go/net/splice_stub.go +++ b/libgo/go/net/splice_stub.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !linux // +build !linux package net diff --git a/libgo/go/net/splice_test.go b/libgo/go/net/splice_test.go index cd4e01f..d5f6367 100644 --- a/libgo/go/net/splice_test.go +++ b/libgo/go/net/splice_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux // +build linux package net diff --git a/libgo/go/net/sys_cloexec.go b/libgo/go/net/sys_cloexec.go index 967b8be..a32483e 100644 --- a/libgo/go/net/sys_cloexec.go +++ b/libgo/go/net/sys_cloexec.go @@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// This file implements sysSocket and accept for platforms that do not -// provide a fast path for setting SetNonblock and CloseOnExec. +// This file implements sysSocket for platforms that do not provide a fast path +// for setting SetNonblock and CloseOnExec. +//go:build aix || darwin || (solaris && !illumos) // +build aix darwin solaris,!illumos package net diff --git a/libgo/go/net/tcpsock.go b/libgo/go/net/tcpsock.go index 9a9b03a..19a90143 100644 --- a/libgo/go/net/tcpsock.go +++ b/libgo/go/net/tcpsock.go @@ -6,6 +6,7 @@ package net import ( "context" + "internal/itoa" "io" "os" "syscall" @@ -31,9 +32,9 @@ func (a *TCPAddr) String() string { } ip := ipEmptyString(a.IP) if a.Zone != "" { - return JoinHostPort(ip+"%"+a.Zone, itoa(a.Port)) + return JoinHostPort(ip+"%"+a.Zone, itoa.Itoa(a.Port)) } - return JoinHostPort(ip, itoa(a.Port)) + return JoinHostPort(ip, itoa.Itoa(a.Port)) } func (a *TCPAddr) isWildcard() bool { diff --git a/libgo/go/net/tcpsock_posix.go b/libgo/go/net/tcpsock_posix.go index 2c359da..9fd7822 100644 --- a/libgo/go/net/tcpsock_posix.go +++ b/libgo/go/net/tcpsock_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows package net diff --git a/libgo/go/net/tcpsock_test.go b/libgo/go/net/tcpsock_test.go index c220c0b..884c5cb 100644 --- a/libgo/go/net/tcpsock_test.go +++ b/libgo/go/net/tcpsock_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net diff --git a/libgo/go/net/tcpsock_unix_test.go b/libgo/go/net/tcpsock_unix_test.go index 2bd591b..41bd229 100644 --- a/libgo/go/net/tcpsock_unix_test.go +++ b/libgo/go/net/tcpsock_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js && !plan9 && !windows // +build !js,!plan9,!windows package net diff --git a/libgo/go/net/tcpsockopt_plan9.go b/libgo/go/net/tcpsockopt_plan9.go index fb56871..264359d 100644 --- a/libgo/go/net/tcpsockopt_plan9.go +++ b/libgo/go/net/tcpsockopt_plan9.go @@ -7,6 +7,7 @@ package net import ( + "internal/itoa" "syscall" "time" ) @@ -17,7 +18,7 @@ func setNoDelay(fd *netFD, noDelay bool) error { // Set keep alive period. func setKeepAlivePeriod(fd *netFD, d time.Duration) error { - cmd := "keepalive " + itoa(int(d/time.Millisecond)) + cmd := "keepalive " + itoa.Itoa(int(d/time.Millisecond)) _, e := fd.ctl.WriteAt([]byte(cmd), 0) return e } diff --git a/libgo/go/net/tcpsockopt_posix.go b/libgo/go/net/tcpsockopt_posix.go index 01bc421..4c99ab8 100644 --- a/libgo/go/net/tcpsockopt_posix.go +++ b/libgo/go/net/tcpsockopt_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows package net diff --git a/libgo/go/net/tcpsockopt_stub.go b/libgo/go/net/tcpsockopt_stub.go index d043da1..028d5fd 100644 --- a/libgo/go/net/tcpsockopt_stub.go +++ b/libgo/go/net/tcpsockopt_stub.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package net diff --git a/libgo/go/net/tcpsockopt_unix.go b/libgo/go/net/tcpsockopt_unix.go index e05cb73..cc0662a 100644 --- a/libgo/go/net/tcpsockopt_unix.go +++ b/libgo/go/net/tcpsockopt_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || freebsd || hurd || linux || netbsd // +build aix freebsd hurd linux netbsd package net diff --git a/libgo/go/net/testdata/ipv4-hosts b/libgo/go/net/testdata/ipv4-hosts index 5208bb4..6b99675 100644 --- a/libgo/go/net/testdata/ipv4-hosts +++ b/libgo/go/net/testdata/ipv4-hosts @@ -1,12 +1,8 @@ # See https://tools.ietf.org/html/rfc1123. -# -# The literal IPv4 address parser in the net package is a relaxed -# one. It may accept a literal IPv4 address in dotted-decimal notation -# with leading zeros such as "001.2.003.4". # internet address and host name 127.0.0.1 localhost # inline comment separated by tab -127.000.000.002 localhost # inline comment separated by space +127.0.0.2 localhost # inline comment separated by space # internet address, host name and aliases -127.000.000.003 localhost localhost.localdomain +127.0.0.3 localhost localhost.localdomain diff --git a/libgo/go/net/timeout_test.go b/libgo/go/net/timeout_test.go index 205aaa4..e1cf146 100644 --- a/libgo/go/net/timeout_test.go +++ b/libgo/go/net/timeout_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net diff --git a/libgo/go/net/udpsock.go b/libgo/go/net/udpsock.go index 571e099..70f2ce2 100644 --- a/libgo/go/net/udpsock.go +++ b/libgo/go/net/udpsock.go @@ -6,6 +6,7 @@ package net import ( "context" + "internal/itoa" "syscall" ) @@ -34,9 +35,9 @@ func (a *UDPAddr) String() string { } ip := ipEmptyString(a.IP) if a.Zone != "" { - return JoinHostPort(ip+"%"+a.Zone, itoa(a.Port)) + return JoinHostPort(ip+"%"+a.Zone, itoa.Itoa(a.Port)) } - return JoinHostPort(ip, itoa(a.Port)) + return JoinHostPort(ip, itoa.Itoa(a.Port)) } func (a *UDPAddr) isWildcard() bool { @@ -99,11 +100,20 @@ func (c *UDPConn) SyscallConn() (syscall.RawConn, error) { } // ReadFromUDP acts like ReadFrom but returns a UDPAddr. -func (c *UDPConn) ReadFromUDP(b []byte) (int, *UDPAddr, error) { +func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) { + // This function is designed to allow the caller to control the lifetime + // of the returned *UDPAddr and thereby prevent an allocation. + // See https://blog.filippo.io/efficient-go-apis-with-the-inliner/. + // The real work is done by readFromUDP, below. + return c.readFromUDP(b, &UDPAddr{}) +} + +// readFromUDP implements ReadFromUDP. +func (c *UDPConn) readFromUDP(b []byte, addr *UDPAddr) (int, *UDPAddr, error) { if !c.ok() { return 0, nil, syscall.EINVAL } - n, addr, err := c.readFrom(b) + n, addr, err := c.readFrom(b, addr) if err != nil { err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} } @@ -112,14 +122,9 @@ func (c *UDPConn) ReadFromUDP(b []byte) (int, *UDPAddr, error) { // ReadFrom implements the PacketConn ReadFrom method. func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) { - if !c.ok() { - return 0, nil, syscall.EINVAL - } - n, addr, err := c.readFrom(b) - if err != nil { - err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err} - } + n, addr, err := c.readFromUDP(b, &UDPAddr{}) if addr == nil { + // Return Addr(nil), not Addr(*UDPConn(nil)). return n, nil, err } return n, addr, err diff --git a/libgo/go/net/udpsock_plan9.go b/libgo/go/net/udpsock_plan9.go index 79986ce..1df293d 100644 --- a/libgo/go/net/udpsock_plan9.go +++ b/libgo/go/net/udpsock_plan9.go @@ -11,7 +11,7 @@ import ( "syscall" ) -func (c *UDPConn) readFrom(b []byte) (n int, addr *UDPAddr, err error) { +func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) { buf := make([]byte, udpHeaderSize+len(b)) m, err := c.fd.Read(buf) if err != nil { @@ -23,8 +23,9 @@ func (c *UDPConn) readFrom(b []byte) (n int, addr *UDPAddr, err error) { buf = buf[:m] h, buf := unmarshalUDPHeader(buf) - n = copy(b, buf) - return n, &UDPAddr{IP: h.raddr, Port: int(h.rport)}, nil + n := copy(b, buf) + *addr = UDPAddr{IP: h.raddr, Port: int(h.rport)} + return n, addr, nil } func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) { diff --git a/libgo/go/net/udpsock_posix.go b/libgo/go/net/udpsock_posix.go index 858a3ef..a4c6da2 100644 --- a/libgo/go/net/udpsock_posix.go +++ b/libgo/go/net/udpsock_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows package net @@ -42,21 +43,23 @@ func (a *UDPAddr) toLocal(net string) sockaddr { return &UDPAddr{loopbackIP(net), a.Port, a.Zone} } -func (c *UDPConn) readFrom(b []byte) (int, *UDPAddr, error) { - var addr *UDPAddr +func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) { n, sa, err := c.fd.readFrom(b) switch sa := sa.(type) { case *syscall.SockaddrInet4: - addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port} + *addr = UDPAddr{IP: sa.Addr[0:], Port: sa.Port} case *syscall.SockaddrInet6: - addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))} + *addr = UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))} + default: + // No sockaddr, so don't return UDPAddr. + addr = nil } return n, addr, err } func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) { var sa syscall.Sockaddr - n, oobn, flags, sa, err = c.fd.readMsg(b, oob) + n, oobn, flags, sa, err = c.fd.readMsg(b, oob, 0) switch sa := sa.(type) { case *syscall.SockaddrInet4: addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port} diff --git a/libgo/go/net/udpsock_test.go b/libgo/go/net/udpsock_test.go index 327eba6..0e8c351 100644 --- a/libgo/go/net/udpsock_test.go +++ b/libgo/go/net/udpsock_test.go @@ -2,12 +2,15 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net import ( + "errors" "internal/testenv" + "os" "reflect" "runtime" "testing" @@ -444,3 +447,51 @@ func TestUDPReadSizeError(t *testing.T) { } } } + +// TestUDPReadTimeout verifies that ReadFromUDP with timeout returns an error +// without data or an address. +func TestUDPReadTimeout(t *testing.T) { + la, err := ResolveUDPAddr("udp4", "127.0.0.1:0") + if err != nil { + t.Fatal(err) + } + c, err := ListenUDP("udp4", la) + if err != nil { + t.Fatal(err) + } + defer c.Close() + + c.SetDeadline(time.Now()) + b := make([]byte, 1) + n, addr, err := c.ReadFromUDP(b) + if !errors.Is(err, os.ErrDeadlineExceeded) { + t.Errorf("ReadFromUDP got err %v want os.ErrDeadlineExceeded", err) + } + if n != 0 { + t.Errorf("ReadFromUDP got n %d want 0", n) + } + if addr != nil { + t.Errorf("ReadFromUDP got addr %+#v want nil", addr) + } +} + +func BenchmarkWriteToReadFromUDP(b *testing.B) { + conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}) + if err != nil { + b.Fatal(err) + } + addr := conn.LocalAddr() + buf := make([]byte, 8) + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _, err := conn.WriteTo(buf, addr) + if err != nil { + b.Fatal(err) + } + _, _, err = conn.ReadFromUDP(buf) + if err != nil { + b.Fatal(err) + } + } +} diff --git a/libgo/go/net/unixsock_posix.go b/libgo/go/net/unixsock_posix.go index 3721485..af075af 100644 --- a/libgo/go/net/unixsock_posix.go +++ b/libgo/go/net/unixsock_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows package net @@ -112,7 +113,11 @@ func (c *UnixConn) readFrom(b []byte) (int, *UnixAddr, error) { func (c *UnixConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) { var sa syscall.Sockaddr - n, oobn, flags, sa, err = c.fd.readMsg(b, oob) + n, oobn, flags, sa, err = c.fd.readMsg(b, oob, readMsgFlags) + if readMsgFlags == 0 && err == nil && oobn > 0 { + setReadMsgCloseOnExec(oob[:oobn]) + } + switch sa := sa.(type) { case *syscall.SockaddrUnix: if sa.Name != "" { diff --git a/libgo/go/net/unixsock_readmsg_cloexec.go b/libgo/go/net/unixsock_readmsg_cloexec.go new file mode 100644 index 0000000..716484c --- /dev/null +++ b/libgo/go/net/unixsock_readmsg_cloexec.go @@ -0,0 +1,31 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || freebsd || solaris +// +build aix darwin freebsd solaris + +package net + +import "syscall" + +const readMsgFlags = 0 + +func setReadMsgCloseOnExec(oob []byte) { + scms, err := syscall.ParseSocketControlMessage(oob) + if err != nil { + return + } + + for _, scm := range scms { + if scm.Header.Level == syscall.SOL_SOCKET && scm.Header.Type == syscall.SCM_RIGHTS { + fds, err := syscall.ParseUnixRights(&scm) + if err != nil { + continue + } + for _, fd := range fds { + syscall.CloseOnExec(fd) + } + } + } +} diff --git a/libgo/go/net/unixsock_readmsg_cmsg_cloexec.go b/libgo/go/net/unixsock_readmsg_cmsg_cloexec.go new file mode 100644 index 0000000..bb851b8 --- /dev/null +++ b/libgo/go/net/unixsock_readmsg_cmsg_cloexec.go @@ -0,0 +1,14 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build dragonfly || linux || netbsd || openbsd +// +build dragonfly linux netbsd openbsd + +package net + +import "syscall" + +const readMsgFlags = syscall.MSG_CMSG_CLOEXEC + +func setReadMsgCloseOnExec(oob []byte) {} diff --git a/libgo/go/net/unixsock_readmsg_other.go b/libgo/go/net/unixsock_readmsg_other.go new file mode 100644 index 0000000..3290761 --- /dev/null +++ b/libgo/go/net/unixsock_readmsg_other.go @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (js && wasm) || windows +// +build js,wasm windows + +package net + +const readMsgFlags = 0 + +func setReadMsgCloseOnExec(oob []byte) {} diff --git a/libgo/go/net/unixsock_readmsg_test.go b/libgo/go/net/unixsock_readmsg_test.go new file mode 100644 index 0000000..a4d2fca --- /dev/null +++ b/libgo/go/net/unixsock_readmsg_test.go @@ -0,0 +1,105 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris + +package net + +import ( + "os" + "syscall" + "testing" + "time" +) + +func TestUnixConnReadMsgUnixSCMRightsCloseOnExec(t *testing.T) { + if !testableNetwork("unix") { + t.Skip("not unix system") + } + + scmFile, err := os.Open(os.DevNull) + if err != nil { + t.Fatalf("file open: %v", err) + } + defer scmFile.Close() + + rights := syscall.UnixRights(int(scmFile.Fd())) + fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0) + if err != nil { + t.Fatalf("Socketpair: %v", err) + } + + writeFile := os.NewFile(uintptr(fds[0]), "write-socket") + defer writeFile.Close() + readFile := os.NewFile(uintptr(fds[1]), "read-socket") + defer readFile.Close() + + cw, err := FileConn(writeFile) + if err != nil { + t.Fatalf("FileConn: %v", err) + } + defer cw.Close() + cr, err := FileConn(readFile) + if err != nil { + t.Fatalf("FileConn: %v", err) + } + defer cr.Close() + + ucw, ok := cw.(*UnixConn) + if !ok { + t.Fatalf("got %T; want UnixConn", cw) + } + ucr, ok := cr.(*UnixConn) + if !ok { + t.Fatalf("got %T; want UnixConn", cr) + } + + oob := make([]byte, syscall.CmsgSpace(4)) + err = ucw.SetWriteDeadline(time.Now().Add(5 * time.Second)) + if err != nil { + t.Fatalf("Can't set unix connection timeout: %v", err) + } + _, _, err = ucw.WriteMsgUnix(nil, rights, nil) + if err != nil { + t.Fatalf("UnixConn readMsg: %v", err) + } + err = ucr.SetReadDeadline(time.Now().Add(5 * time.Second)) + if err != nil { + t.Fatalf("Can't set unix connection timeout: %v", err) + } + _, oobn, _, _, err := ucr.ReadMsgUnix(nil, oob) + if err != nil { + t.Fatalf("UnixConn readMsg: %v", err) + } + + scms, err := syscall.ParseSocketControlMessage(oob[:oobn]) + if err != nil { + t.Fatalf("ParseSocketControlMessage: %v", err) + } + if len(scms) != 1 { + t.Fatalf("got scms = %#v; expected 1 SocketControlMessage", scms) + } + scm := scms[0] + gotFDs, err := syscall.ParseUnixRights(&scm) + if err != nil { + t.Fatalf("syscall.ParseUnixRights: %v", err) + } + if len(gotFDs) != 1 { + t.Fatalf("got FDs %#v: wanted only 1 fd", gotFDs) + } + defer func() { + if err := syscall.Close(gotFDs[0]); err != nil { + t.Fatalf("fail to close gotFDs: %v", err) + } + }() + + flags, err := fcntl(gotFDs[0], syscall.F_GETFD, 0) + if err != nil { + t.Fatalf("Can't get flags of fd:%#v, with err:%v", gotFDs[0], err) + } + if flags&syscall.FD_CLOEXEC == 0 { + t.Fatalf("got flags %#x, want %#x (FD_CLOEXEC) set", flags, syscall.FD_CLOEXEC) + } +} diff --git a/libgo/go/net/unixsock_test.go b/libgo/go/net/unixsock_test.go index 0b13bf6..71092e8 100644 --- a/libgo/go/net/unixsock_test.go +++ b/libgo/go/net/unixsock_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js && !plan9 && !windows // +build !js,!plan9,!windows package net diff --git a/libgo/go/net/unixsock_windows_test.go b/libgo/go/net/unixsock_windows_test.go index 5dccc14..29244f6 100644 --- a/libgo/go/net/unixsock_windows_test.go +++ b/libgo/go/net/unixsock_windows_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package net diff --git a/libgo/go/net/url/url.go b/libgo/go/net/url/url.go index d90f5f0..20de0f6 100644 --- a/libgo/go/net/url/url.go +++ b/libgo/go/net/url/url.go @@ -425,31 +425,31 @@ func (u *Userinfo) String() string { return s } -// Maybe rawurl is of the form scheme:path. +// Maybe rawURL is of the form scheme:path. // (Scheme must be [a-zA-Z][a-zA-Z0-9+-.]*) -// If so, return scheme, path; else return "", rawurl. -func getscheme(rawurl string) (scheme, path string, err error) { - for i := 0; i < len(rawurl); i++ { - c := rawurl[i] +// If so, return scheme, path; else return "", rawURL. +func getScheme(rawURL string) (scheme, path string, err error) { + for i := 0; i < len(rawURL); i++ { + c := rawURL[i] switch { case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z': // do nothing case '0' <= c && c <= '9' || c == '+' || c == '-' || c == '.': if i == 0 { - return "", rawurl, nil + return "", rawURL, nil } case c == ':': if i == 0 { return "", "", errors.New("missing protocol scheme") } - return rawurl[:i], rawurl[i+1:], nil + return rawURL[:i], rawURL[i+1:], nil default: // we have encountered an invalid character, // so there is no valid scheme - return "", rawurl, nil + return "", rawURL, nil } } - return "", rawurl, nil + return "", rawURL, nil } // split slices s into two substrings separated by the first occurrence of @@ -466,15 +466,15 @@ func split(s string, sep byte, cutc bool) (string, string) { return s[:i], s[i:] } -// Parse parses rawurl into a URL structure. +// Parse parses a raw url into a URL structure. // -// The rawurl may be relative (a path, without a host) or absolute +// The url may be relative (a path, without a host) or absolute // (starting with a scheme). Trying to parse a hostname and path // without a scheme is invalid but may not necessarily return an // error, due to parsing ambiguities. -func Parse(rawurl string) (*URL, error) { +func Parse(rawURL string) (*URL, error) { // Cut off #frag - u, frag := split(rawurl, '#', true) + u, frag := split(rawURL, '#', true) url, err := parse(u, false) if err != nil { return nil, &Error{"parse", u, err} @@ -483,20 +483,20 @@ func Parse(rawurl string) (*URL, error) { return url, nil } if err = url.setFragment(frag); err != nil { - return nil, &Error{"parse", rawurl, err} + return nil, &Error{"parse", rawURL, err} } return url, nil } -// ParseRequestURI parses rawurl into a URL structure. It assumes that -// rawurl was received in an HTTP request, so the rawurl is interpreted +// ParseRequestURI parses a raw url into a URL structure. It assumes that +// url was received in an HTTP request, so the url is interpreted // only as an absolute URI or an absolute path. -// The string rawurl is assumed not to have a #fragment suffix. +// The string url is assumed not to have a #fragment suffix. // (Web browsers strip #fragment before sending the URL to a web server.) -func ParseRequestURI(rawurl string) (*URL, error) { - url, err := parse(rawurl, true) +func ParseRequestURI(rawURL string) (*URL, error) { + url, err := parse(rawURL, true) if err != nil { - return nil, &Error{"parse", rawurl, err} + return nil, &Error{"parse", rawURL, err} } return url, nil } @@ -505,27 +505,27 @@ func ParseRequestURI(rawurl string) (*URL, error) { // viaRequest is true, the URL is assumed to have arrived via an HTTP request, // in which case only absolute URLs or path-absolute relative URLs are allowed. // If viaRequest is false, all forms of relative URLs are allowed. -func parse(rawurl string, viaRequest bool) (*URL, error) { +func parse(rawURL string, viaRequest bool) (*URL, error) { var rest string var err error - if stringContainsCTLByte(rawurl) { + if stringContainsCTLByte(rawURL) { return nil, errors.New("net/url: invalid control character in URL") } - if rawurl == "" && viaRequest { + if rawURL == "" && viaRequest { return nil, errors.New("empty url") } url := new(URL) - if rawurl == "*" { + if rawURL == "*" { url.Path = "*" return url, nil } // Split off possible leading "http:", "mailto:", etc. // Cannot contain escaped characters. - if url.Scheme, rest, err = getscheme(rawurl); err != nil { + if url.Scheme, rest, err = getScheme(rawURL); err != nil { return nil, err } url.Scheme = strings.ToLower(url.Scheme) @@ -909,15 +909,22 @@ func (v Values) Del(key string) { delete(v, key) } +// Has checks whether a given key is set. +func (v Values) Has(key string) bool { + _, ok := v[key] + return ok +} + // ParseQuery parses the URL-encoded query string and returns // a map listing the values specified for each key. // ParseQuery always returns a non-nil map containing all the // valid query parameters found; err describes the first decoding error // encountered, if any. // -// Query is expected to be a list of key=value settings separated by -// ampersands or semicolons. A setting without an equals sign is -// interpreted as a key set to an empty value. +// Query is expected to be a list of key=value settings separated by ampersands. +// A setting without an equals sign is interpreted as a key set to an empty +// value. +// Settings containing a non-URL-encoded semicolon are considered invalid. func ParseQuery(query string) (Values, error) { m := make(Values) err := parseQuery(m, query) @@ -927,11 +934,15 @@ func ParseQuery(query string) (Values, error) { func parseQuery(m Values, query string) (err error) { for query != "" { key := query - if i := strings.IndexAny(key, "&;"); i >= 0 { + if i := strings.IndexAny(key, "&"); i >= 0 { key, query = key[:i], key[i+1:] } else { query = "" } + if strings.Contains(key, ";") { + err = fmt.Errorf("invalid semicolon separator in query") + continue + } if key == "" { continue } @@ -1009,6 +1020,8 @@ func resolvePath(base, ref string) string { ) first := true remaining := full + // We want to return a leading '/', so write it now. + dst.WriteByte('/') for i >= 0 { i = strings.IndexByte(remaining, '/') if i < 0 { @@ -1023,10 +1036,12 @@ func resolvePath(base, ref string) string { } if elem == ".." { - str := dst.String() + // Ignore the leading '/' we already wrote. + str := dst.String()[1:] index := strings.LastIndexByte(str, '/') dst.Reset() + dst.WriteByte('/') if index == -1 { first = true } else { @@ -1045,7 +1060,12 @@ func resolvePath(base, ref string) string { dst.WriteByte('/') } - return "/" + strings.TrimPrefix(dst.String(), "/") + // We wrote an initial '/', but we don't want two. + r := dst.String() + if len(r) > 1 && r[1] == '/' { + r = r[1:] + } + return r } // IsAbs reports whether the URL is absolute. @@ -1058,11 +1078,11 @@ func (u *URL) IsAbs() bool { // may be relative or absolute. Parse returns nil, err on parse // failure, otherwise its return value is the same as ResolveReference. func (u *URL) Parse(ref string) (*URL, error) { - refurl, err := Parse(ref) + refURL, err := Parse(ref) if err != nil { return nil, err } - return u.ResolveReference(refurl), nil + return u.ResolveReference(refURL), nil } // ResolveReference resolves a URI reference to an absolute URI from @@ -1151,8 +1171,8 @@ func (u *URL) Port() string { // splitHostPort separates host and port. If the port is not valid, it returns // the entire input as host, and it doesn't check the validity of the host. // Unlike net.SplitHostPort, but per RFC 3986, it requires ports to be numeric. -func splitHostPort(hostport string) (host, port string) { - host = hostport +func splitHostPort(hostPort string) (host, port string) { + host = hostPort colon := strings.LastIndexByte(host, ':') if colon != -1 && validOptionalPort(host[colon:]) { diff --git a/libgo/go/net/url/url_test.go b/libgo/go/net/url/url_test.go index f02e4650..63c8e69 100644 --- a/libgo/go/net/url/url_test.go +++ b/libgo/go/net/url/url_test.go @@ -1295,10 +1295,10 @@ func TestResolveReference(t *testing.T) { } func TestQueryValues(t *testing.T) { - u, _ := Parse("http://x.com?foo=bar&bar=1&bar=2") + u, _ := Parse("http://x.com?foo=bar&bar=1&bar=2&baz") v := u.Query() - if len(v) != 2 { - t.Errorf("got %d keys in Query values, want 2", len(v)) + if len(v) != 3 { + t.Errorf("got %d keys in Query values, want 3", len(v)) } if g, e := v.Get("foo"), "bar"; g != e { t.Errorf("Get(foo) = %q, want %q", g, e) @@ -1313,6 +1313,18 @@ func TestQueryValues(t *testing.T) { if g, e := v.Get("baz"), ""; g != e { t.Errorf("Get(baz) = %q, want %q", g, e) } + if h, e := v.Has("foo"), true; h != e { + t.Errorf("Has(foo) = %t, want %t", h, e) + } + if h, e := v.Has("bar"), true; h != e { + t.Errorf("Has(bar) = %t, want %t", h, e) + } + if h, e := v.Has("baz"), true; h != e { + t.Errorf("Has(baz) = %t, want %t", h, e) + } + if h, e := v.Has("noexist"), false; h != e { + t.Errorf("Has(noexist) = %t, want %t", h, e) + } v.Del("bar") if g, e := v.Get("bar"), ""; g != e { t.Errorf("second Get(bar) = %q, want %q", g, e) @@ -1322,57 +1334,125 @@ func TestQueryValues(t *testing.T) { type parseTest struct { query string out Values + ok bool } var parseTests = []parseTest{ { + query: "a=1", + out: Values{"a": []string{"1"}}, + ok: true, + }, + { query: "a=1&b=2", out: Values{"a": []string{"1"}, "b": []string{"2"}}, + ok: true, }, { query: "a=1&a=2&a=banana", out: Values{"a": []string{"1", "2", "banana"}}, + ok: true, }, { query: "ascii=%3Ckey%3A+0x90%3E", out: Values{"ascii": []string{"<key: 0x90>"}}, + ok: true, + }, { + query: "a=1;b=2", + out: Values{}, + ok: false, + }, { + query: "a;b=1", + out: Values{}, + ok: false, + }, { + query: "a=%3B", // hex encoding for semicolon + out: Values{"a": []string{";"}}, + ok: true, }, { - query: "a=1;b=2", - out: Values{"a": []string{"1"}, "b": []string{"2"}}, + query: "a%3Bb=1", + out: Values{"a;b": []string{"1"}}, + ok: true, }, { query: "a=1&a=2;a=banana", - out: Values{"a": []string{"1", "2", "banana"}}, + out: Values{"a": []string{"1"}}, + ok: false, + }, + { + query: "a;b&c=1", + out: Values{"c": []string{"1"}}, + ok: false, + }, + { + query: "a=1&b=2;a=3&c=4", + out: Values{"a": []string{"1"}, "c": []string{"4"}}, + ok: false, + }, + { + query: "a=1&b=2;c=3", + out: Values{"a": []string{"1"}}, + ok: false, + }, + { + query: ";", + out: Values{}, + ok: false, + }, + { + query: "a=1;", + out: Values{}, + ok: false, + }, + { + query: "a=1&;", + out: Values{"a": []string{"1"}}, + ok: false, + }, + { + query: ";a=1&b=2", + out: Values{"b": []string{"2"}}, + ok: false, + }, + { + query: "a=1&b=2;", + out: Values{"a": []string{"1"}}, + ok: false, }, } func TestParseQuery(t *testing.T) { - for i, test := range parseTests { - form, err := ParseQuery(test.query) - if err != nil { - t.Errorf("test %d: Unexpected error: %v", i, err) - continue - } - if len(form) != len(test.out) { - t.Errorf("test %d: len(form) = %d, want %d", i, len(form), len(test.out)) - } - for k, evs := range test.out { - vs, ok := form[k] - if !ok { - t.Errorf("test %d: Missing key %q", i, k) - continue + for _, test := range parseTests { + t.Run(test.query, func(t *testing.T) { + form, err := ParseQuery(test.query) + if test.ok != (err == nil) { + want := "<error>" + if test.ok { + want = "<nil>" + } + t.Errorf("Unexpected error: %v, want %v", err, want) } - if len(vs) != len(evs) { - t.Errorf("test %d: len(form[%q]) = %d, want %d", i, k, len(vs), len(evs)) - continue + if len(form) != len(test.out) { + t.Errorf("len(form) = %d, want %d", len(form), len(test.out)) } - for j, ev := range evs { - if v := vs[j]; v != ev { - t.Errorf("test %d: form[%q][%d] = %q, want %q", i, k, j, v, ev) + for k, evs := range test.out { + vs, ok := form[k] + if !ok { + t.Errorf("Missing key %q", k) + continue + } + if len(vs) != len(evs) { + t.Errorf("len(form[%q]) = %d, want %d", k, len(vs), len(evs)) + continue + } + for j, ev := range evs { + if v := vs[j]; v != ev { + t.Errorf("form[%q][%d] = %q, want %q", k, j, v, ev) + } } } - } + }) } } diff --git a/libgo/go/net/write_unix_test.go b/libgo/go/net/write_unix_test.go index 6d8cb6a..f79f2d0 100644 --- a/libgo/go/net/write_unix_test.go +++ b/libgo/go/net/write_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris // +build darwin dragonfly freebsd linux netbsd openbsd solaris package net diff --git a/libgo/go/net/writev_test.go b/libgo/go/net/writev_test.go index d603b7f..bf40ca2 100644 --- a/libgo/go/net/writev_test.go +++ b/libgo/go/net/writev_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package net diff --git a/libgo/go/net/writev_unix.go b/libgo/go/net/writev_unix.go index 8b20f42..a0fedc2 100644 --- a/libgo/go/net/writev_unix.go +++ b/libgo/go/net/writev_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || illumos || linux || netbsd || openbsd // +build darwin dragonfly freebsd illumos linux netbsd openbsd package net diff --git a/libgo/go/os/env_unix_test.go b/libgo/go/os/env_unix_test.go index fd21ddd..0336323 100644 --- a/libgo/go/os/env_unix_test.go +++ b/libgo/go/os/env_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package os_test diff --git a/libgo/go/os/error.go b/libgo/go/os/error.go index 704a6fb..fe8f2a8 100644 --- a/libgo/go/os/error.go +++ b/libgo/go/os/error.go @@ -78,7 +78,7 @@ func NewSyscallError(syscall string, err error) error { // well as some syscall errors. // // This function predates errors.Is. It only supports errors returned by -// the os package. New code should use errors.Is(err, os.ErrExist). +// the os package. New code should use errors.Is(err, fs.ErrExist). func IsExist(err error) bool { return underlyingErrorIs(err, ErrExist) } @@ -88,7 +88,7 @@ func IsExist(err error) bool { // ErrNotExist as well as some syscall errors. // // This function predates errors.Is. It only supports errors returned by -// the os package. New code should use errors.Is(err, os.ErrNotExist). +// the os package. New code should use errors.Is(err, fs.ErrNotExist). func IsNotExist(err error) bool { return underlyingErrorIs(err, ErrNotExist) } @@ -98,7 +98,7 @@ func IsNotExist(err error) bool { // as some syscall errors. // // This function predates errors.Is. It only supports errors returned by -// the os package. New code should use errors.Is(err, os.ErrPermission). +// the os package. New code should use errors.Is(err, fs.ErrPermission). func IsPermission(err error) bool { return underlyingErrorIs(err, ErrPermission) } diff --git a/libgo/go/os/error_errno.go b/libgo/go/os/error_errno.go index 31ae05a..580e915 100644 --- a/libgo/go/os/error_errno.go +++ b/libgo/go/os/error_errno.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 // +build !plan9 package os diff --git a/libgo/go/os/error_posix.go b/libgo/go/os/error_posix.go index 7d5a19c..7a7c860 100644 --- a/libgo/go/os/error_posix.go +++ b/libgo/go/os/error_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows package os diff --git a/libgo/go/os/error_test.go b/libgo/go/os/error_test.go index 6264ccc..4ab6246 100644 --- a/libgo/go/os/error_test.go +++ b/libgo/go/os/error_test.go @@ -33,7 +33,12 @@ func TestErrIsExist(t *testing.T) { } } -func testErrNotExist(name string) string { +func testErrNotExist(t *testing.T, name string) string { + originalWD, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + f, err := os.Open(name) if err == nil { f.Close() @@ -45,7 +50,10 @@ func testErrNotExist(name string) string { err = os.Chdir(name) if err == nil { - return "Chdir should have failed" + if err := os.Chdir(originalWD); err != nil { + t.Fatalf("Chdir should have failed, failed to restore original working directory: %v", err) + } + return "Chdir should have failed, restored original working directory" } if s := checkErrorPredicate("os.IsNotExist", os.IsNotExist, err, fs.ErrNotExist); s != "" { return s @@ -54,21 +62,15 @@ func testErrNotExist(name string) string { } func TestErrIsNotExist(t *testing.T) { - tmpDir, err := os.MkdirTemp("", "_Go_ErrIsNotExist") - if err != nil { - t.Fatalf("create ErrIsNotExist tempdir: %s", err) - return - } - defer os.RemoveAll(tmpDir) - + tmpDir := t.TempDir() name := filepath.Join(tmpDir, "NotExists") - if s := testErrNotExist(name); s != "" { + if s := testErrNotExist(t, name); s != "" { t.Fatal(s) return } name = filepath.Join(name, "NotExists2") - if s := testErrNotExist(name); s != "" { + if s := testErrNotExist(t, name); s != "" { t.Fatal(s) return } diff --git a/libgo/go/os/error_unix_test.go b/libgo/go/os/error_unix_test.go index dd9f317..3f419d5 100644 --- a/libgo/go/os/error_unix_test.go +++ b/libgo/go/os/error_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package os_test diff --git a/libgo/go/os/error_windows_test.go b/libgo/go/os/error_windows_test.go index b8191c5..aa0c14b 100644 --- a/libgo/go/os/error_windows_test.go +++ b/libgo/go/os/error_windows_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package os_test diff --git a/libgo/go/os/example_test.go b/libgo/go/os/example_test.go index 3adce51..e8554b0 100644 --- a/libgo/go/os/example_test.go +++ b/libgo/go/os/example_test.go @@ -5,6 +5,7 @@ package os_test import ( + "errors" "fmt" "io/fs" "log" @@ -71,9 +72,9 @@ func ExampleFileMode() { } } -func ExampleIsNotExist() { +func ExampleErrNotExist() { filename := "a-nonexistent-file" - if _, err := os.Stat(filename); os.IsNotExist(err) { + if _, err := os.Stat(filename); errors.Is(err, fs.ErrNotExist) { fmt.Println("file does not exist") } // Output: diff --git a/libgo/go/os/exec.go b/libgo/go/os/exec.go index edb773a..bc75d4d 100644 --- a/libgo/go/os/exec.go +++ b/libgo/go/os/exec.go @@ -54,6 +54,9 @@ type ProcAttr struct { // standard error. An implementation may support additional entries, // depending on the underlying operating system. A nil entry corresponds // to that file being closed when the process starts. + // On Unix systems, StartProcess will change these File values + // to blocking mode, which means that SetDeadline will stop working + // and calling Close will not interrupt a Read or Write. Files []*File // Operating system-specific process creation attributes. diff --git a/libgo/go/os/exec/exec_linux_test.go b/libgo/go/os/exec/exec_linux_test.go index 6f85020..3cfa30e 100644 --- a/libgo/go/os/exec/exec_linux_test.go +++ b/libgo/go/os/exec/exec_linux_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux && cgo // +build linux,cgo // On systems that use glibc, calling malloc can create a new arena, diff --git a/libgo/go/os/exec/exec_posix_test.go b/libgo/go/os/exec/exec_posix_test.go index d4d67ac..7b2c0c0 100644 --- a/libgo/go/os/exec/exec_posix_test.go +++ b/libgo/go/os/exec/exec_posix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package exec_test diff --git a/libgo/go/os/exec/exec_test.go b/libgo/go/os/exec/exec_test.go index 8b0c93f..d854e0d 100644 --- a/libgo/go/os/exec/exec_test.go +++ b/libgo/go/os/exec/exec_test.go @@ -488,7 +488,7 @@ func numOpenFDsAndroid(t *testing.T) (n int, lsof []byte) { } func TestExtraFilesFDShuffle(t *testing.T) { - t.Skip("flaky test; see https://golang.org/issue/5780") + testenv.SkipFlaky(t, 5780) switch runtime.GOOS { case "windows": t.Skip("no operating system support; skipping") @@ -915,6 +915,16 @@ func TestHelperProcess(*testing.T) { case "sleep": time.Sleep(3 * time.Second) os.Exit(0) + case "pipehandle": + handle, _ := strconv.ParseUint(args[0], 16, 64) + pipe := os.NewFile(uintptr(handle), "") + _, err := fmt.Fprint(pipe, args[1]) + if err != nil { + fmt.Fprintf(os.Stderr, "writing to pipe failed: %v\n", err) + os.Exit(1) + } + pipe.Close() + os.Exit(0) default: fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd) os.Exit(2) @@ -1042,41 +1052,18 @@ func TestContextCancel(t *testing.T) { defer cancel() c := helperCommandContext(t, ctx, "cat") - r, w, err := os.Pipe() - if err != nil { - t.Fatal(err) - } - c.Stdin = r - - stdout, err := c.StdoutPipe() + stdin, err := c.StdinPipe() if err != nil { t.Fatal(err) } - readDone := make(chan struct{}) - go func() { - defer close(readDone) - var a [1024]byte - for { - n, err := stdout.Read(a[:]) - if err != nil { - if err != io.EOF { - t.Errorf("unexpected read error: %v", err) - } - return - } - t.Logf("%s", a[:n]) - } - }() + defer stdin.Close() if err := c.Start(); err != nil { t.Fatal(err) } - if err := r.Close(); err != nil { - t.Fatal(err) - } - - if _, err := io.WriteString(w, "echo"); err != nil { + // At this point the process is alive. Ensure it by sending data to stdin. + if _, err := io.WriteString(stdin, "echo"); err != nil { t.Fatal(err) } @@ -1086,20 +1073,15 @@ func TestContextCancel(t *testing.T) { // should now fail. Give the process a little while to die. start := time.Now() for { - if _, err := io.WriteString(w, "echo"); err != nil { + if _, err := io.WriteString(stdin, "echo"); err != nil { break } - if time.Since(start) > time.Second { + if time.Since(start) > time.Minute { t.Fatal("canceling context did not stop program") } time.Sleep(time.Millisecond) } - if err := w.Close(); err != nil { - t.Errorf("error closing write end of pipe: %v", err) - } - <-readDone - if err := c.Wait(); err == nil { t.Error("program unexpectedly exited successfully") } else { diff --git a/libgo/go/os/exec/exec_unix.go b/libgo/go/os/exec/exec_unix.go index 51c5242..467c069 100644 --- a/libgo/go/os/exec/exec_unix.go +++ b/libgo/go/os/exec/exec_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 && !windows // +build !plan9,!windows package exec diff --git a/libgo/go/os/exec/exec_windows_test.go b/libgo/go/os/exec/exec_windows_test.go new file mode 100644 index 0000000..fbccffe --- /dev/null +++ b/libgo/go/os/exec/exec_windows_test.go @@ -0,0 +1,43 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows +// +build windows + +package exec_test + +import ( + "io" + "os" + "strconv" + "syscall" + "testing" +) + +func TestPipePassing(t *testing.T) { + r, w, err := os.Pipe() + if err != nil { + t.Error(err) + } + const marker = "arrakis, dune, desert planet" + childProc := helperCommand(t, "pipehandle", strconv.FormatUint(uint64(w.Fd()), 16), marker) + childProc.SysProcAttr = &syscall.SysProcAttr{AdditionalInheritedHandles: []syscall.Handle{syscall.Handle(w.Fd())}} + err = childProc.Start() + if err != nil { + t.Error(err) + } + w.Close() + response, err := io.ReadAll(r) + if err != nil { + t.Error(err) + } + r.Close() + if string(response) != marker { + t.Errorf("got %q; want %q", string(response), marker) + } + err = childProc.Wait() + if err != nil { + t.Error(err) + } +} diff --git a/libgo/go/os/exec/lp_js.go b/libgo/go/os/exec/lp_js.go index 6750fb9..4eac25f 100644 --- a/libgo/go/os/exec/lp_js.go +++ b/libgo/go/os/exec/lp_js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package exec diff --git a/libgo/go/os/exec/lp_unix.go b/libgo/go/os/exec/lp_unix.go index bb5a3ec..ebecc74 100644 --- a/libgo/go/os/exec/lp_unix.go +++ b/libgo/go/os/exec/lp_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package exec diff --git a/libgo/go/os/exec/lp_unix_test.go b/libgo/go/os/exec/lp_unix_test.go index 23d1506..fe4df1a 100644 --- a/libgo/go/os/exec/lp_unix_test.go +++ b/libgo/go/os/exec/lp_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package exec @@ -36,13 +37,7 @@ func TestLookPathUnixEmptyPath(t *testing.T) { t.Fatal("Close failed: ", err) } - pathenv := os.Getenv("PATH") - defer os.Setenv("PATH", pathenv) - - err = os.Setenv("PATH", "") - if err != nil { - t.Fatal("Setenv failed: ", err) - } + t.Setenv("PATH", "") path, err := LookPath("exec_me") if err == nil { diff --git a/libgo/go/os/exec/read3.go b/libgo/go/os/exec/read3.go index 8cc24da..a8c7183 100644 --- a/libgo/go/os/exec/read3.go +++ b/libgo/go/os/exec/read3.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // This is a test program that verifies that it can read from diff --git a/libgo/go/os/exec_plan9.go b/libgo/go/os/exec_plan9.go index 8580153..cc84f97 100644 --- a/libgo/go/os/exec_plan9.go +++ b/libgo/go/os/exec_plan9.go @@ -5,6 +5,7 @@ package os import ( + "internal/itoa" "runtime" "syscall" "time" @@ -40,7 +41,7 @@ func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err e } func (p *Process) writeProcFile(file string, data string) error { - f, e := OpenFile("/proc/"+itoa(p.Pid)+"/"+file, O_WRONLY, 0) + f, e := OpenFile("/proc/"+itoa.Itoa(p.Pid)+"/"+file, O_WRONLY, 0) if e != nil { return e } diff --git a/libgo/go/os/exec_posix.go b/libgo/go/os/exec_posix.go index aa8dfe0..eb5cbc8 100644 --- a/libgo/go/os/exec_posix.go +++ b/libgo/go/os/exec_posix.go @@ -2,11 +2,13 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows package os import ( + "internal/itoa" "internal/syscall/execenv" "runtime" "syscall" @@ -102,13 +104,18 @@ func (p *ProcessState) String() string { res := "" switch { case status.Exited(): - res = "exit status " + itoa(status.ExitStatus()) + code := status.ExitStatus() + if runtime.GOOS == "windows" && uint(code) >= 1<<16 { // windows uses large hex numbers + res = "exit status " + uitox(uint(code)) + } else { // unix systems use small decimal integers + res = "exit status " + itoa.Itoa(code) // unix + } case status.Signaled(): res = "signal: " + status.Signal().String() case status.Stopped(): res = "stop signal: " + status.StopSignal().String() if status.StopSignal() == syscall.SIGTRAP && status.TrapCause() != 0 { - res += " (trap " + itoa(status.TrapCause()) + ")" + res += " (trap " + itoa.Itoa(status.TrapCause()) + ")" } case status.Continued(): res = "continued" diff --git a/libgo/go/os/exec_unix.go b/libgo/go/os/exec_unix.go index 69eb615..4ada050 100644 --- a/libgo/go/os/exec_unix.go +++ b/libgo/go/os/exec_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package os diff --git a/libgo/go/os/exec_unix_test.go b/libgo/go/os/exec_unix_test.go index d942cdb..f14b351 100644 --- a/libgo/go/os/exec_unix_test.go +++ b/libgo/go/os/exec_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package os_test diff --git a/libgo/go/os/exec_windows.go b/libgo/go/os/exec_windows.go index 5710401..239bed1 100644 --- a/libgo/go/os/exec_windows.go +++ b/libgo/go/os/exec_windows.go @@ -45,16 +45,6 @@ func (p *Process) wait() (ps *ProcessState, err error) { return &ProcessState{p.Pid, syscall.WaitStatus{ExitCode: ec}, &u}, nil } -func terminateProcess(pid, exitcode int) error { - h, e := syscall.OpenProcess(syscall.PROCESS_TERMINATE, false, uint32(pid)) - if e != nil { - return NewSyscallError("OpenProcess", e) - } - defer syscall.CloseHandle(h) - e = syscall.TerminateProcess(h, uint32(exitcode)) - return NewSyscallError("TerminateProcess", e) -} - func (p *Process) signal(sig Signal) error { handle := atomic.LoadUintptr(&p.handle) if handle == uintptr(syscall.InvalidHandle) { @@ -64,16 +54,22 @@ func (p *Process) signal(sig Signal) error { return ErrProcessDone } if sig == Kill { - err := terminateProcess(p.Pid, 1) + var terminationHandle syscall.Handle + e := syscall.DuplicateHandle(^syscall.Handle(0), syscall.Handle(handle), ^syscall.Handle(0), &terminationHandle, syscall.PROCESS_TERMINATE, false, 0) + if e != nil { + return NewSyscallError("DuplicateHandle", e) + } runtime.KeepAlive(p) - return err + defer syscall.CloseHandle(terminationHandle) + e = syscall.TerminateProcess(syscall.Handle(terminationHandle), 1) + return NewSyscallError("TerminateProcess", e) } // TODO(rsc): Handle Interrupt too? return syscall.Errno(syscall.EWINDOWS) } func (p *Process) release() error { - handle := atomic.LoadUintptr(&p.handle) + handle := atomic.SwapUintptr(&p.handle, uintptr(syscall.InvalidHandle)) if handle == uintptr(syscall.InvalidHandle) { return syscall.EINVAL } @@ -81,7 +77,6 @@ func (p *Process) release() error { if e != nil { return NewSyscallError("CloseHandle", e) } - atomic.StoreUintptr(&p.handle, uintptr(syscall.InvalidHandle)) // no need for a finalizer anymore runtime.SetFinalizer(p, nil) return nil diff --git a/libgo/go/os/executable_path.go b/libgo/go/os/executable_path.go index 7b8b836..625430e 100644 --- a/libgo/go/os/executable_path.go +++ b/libgo/go/os/executable_path.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || openbsd // +build aix openbsd package os diff --git a/libgo/go/os/executable_plan9.go b/libgo/go/os/executable_plan9.go index a5947ea..ad7a441 100644 --- a/libgo/go/os/executable_plan9.go +++ b/libgo/go/os/executable_plan9.go @@ -2,14 +2,18 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build plan9 // +build plan9 package os -import "syscall" +import ( + "internal/itoa" + "syscall" +) func executable() (string, error) { - fn := "/proc/" + itoa(Getpid()) + "/text" + fn := "/proc/" + itoa.Itoa(Getpid()) + "/text" f, err := Open(fn) if err != nil { return "", err diff --git a/libgo/go/os/executable_procfs.go b/libgo/go/os/executable_procfs.go index 989a220..fdb2394 100644 --- a/libgo/go/os/executable_procfs.go +++ b/libgo/go/os/executable_procfs.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build hurd || linux || netbsd || (js && wasm) // +build hurd linux netbsd js,wasm package os @@ -11,10 +12,7 @@ import ( "runtime" ) -// We query the executable path at init time to avoid the problem of -// readlink returns a path appended with " (deleted)" when the original -// binary gets deleted. -var executablePath, executablePathErr = func() (string, error) { +func executable() (string, error) { var procfn string switch runtime.GOOS { default: @@ -24,9 +22,17 @@ var executablePath, executablePathErr = func() (string, error) { case "netbsd": procfn = "/proc/curproc/exe" } - return Readlink(procfn) -}() + path, err := Readlink(procfn) -func executable() (string, error) { - return executablePath, executablePathErr + // When the executable has been deleted then Readlink returns a + // path appended with " (deleted)". + return stringsTrimSuffix(path, " (deleted)"), err +} + +// stringsTrimSuffix is the same as strings.TrimSuffix. +func stringsTrimSuffix(s, suffix string) string { + if len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix { + return s[:len(s)-len(suffix)] + } + return s } diff --git a/libgo/go/os/executable_sysctl.go b/libgo/go/os/executable_sysctl.go index f9a4b18..039448b 100644 --- a/libgo/go/os/executable_sysctl.go +++ b/libgo/go/os/executable_sysctl.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build freebsd || dragonfly // +build freebsd dragonfly package os diff --git a/libgo/go/os/executable_test.go b/libgo/go/os/executable_test.go index f25ee0c..719d6a6 100644 --- a/libgo/go/os/executable_test.go +++ b/libgo/go/os/executable_test.go @@ -86,3 +86,68 @@ func init() { os.Exit(0) } } + +func TestExecutableDeleted(t *testing.T) { + testenv.MustHaveExec(t) + switch runtime.GOOS { + case "windows", "plan9": + t.Skipf("%v does not support deleting running binary", runtime.GOOS) + case "openbsd", "freebsd", "aix": + t.Skipf("%v does not support reading deleted binary name", runtime.GOOS) + } + + dir := t.TempDir() + + src := filepath.Join(dir, "testdel.go") + exe := filepath.Join(dir, "testdel.exe") + + err := os.WriteFile(src, []byte(testExecutableDeletion), 0666) + if err != nil { + t.Fatal(err) + } + + out, err := osexec.Command(testenv.GoToolPath(t), "build", "-o", exe, src).CombinedOutput() + t.Logf("build output:\n%s", out) + if err != nil { + t.Fatal(err) + } + + out, err = osexec.Command(exe).CombinedOutput() + t.Logf("exec output:\n%s", out) + if err != nil { + t.Fatal(err) + } +} + +const testExecutableDeletion = `package main + +import ( + "fmt" + "os" +) + +func main() { + before, err := os.Executable() + if err != nil { + fmt.Fprintf(os.Stderr, "failed to read executable name before deletion: %v\n", err) + os.Exit(1) + } + + err = os.Remove(before) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to remove executable: %v\n", err) + os.Exit(1) + } + + after, err := os.Executable() + if err != nil { + fmt.Fprintf(os.Stderr, "failed to read executable name after deletion: %v\n", err) + os.Exit(1) + } + + if before != after { + fmt.Fprintf(os.Stderr, "before and after do not match: %v != %v\n", before, after) + os.Exit(1) + } +} +` diff --git a/libgo/go/os/export_unix_test.go b/libgo/go/os/export_unix_test.go index f4d399d..dd2f8ec 100644 --- a/libgo/go/os/export_unix_test.go +++ b/libgo/go/os/export_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package os diff --git a/libgo/go/os/export_windows_test.go b/libgo/go/os/export_windows_test.go index f36fadb..ff4f899 100644 --- a/libgo/go/os/export_windows_test.go +++ b/libgo/go/os/export_windows_test.go @@ -8,6 +8,7 @@ package os var ( FixLongPath = fixLongPath + CanUseLongPaths = canUseLongPaths NewConsoleFile = newConsoleFile CommandLineToArgv = commandLineToArgv ) diff --git a/libgo/go/os/fifo_test.go b/libgo/go/os/fifo_test.go index 2439192..007ed29 100644 --- a/libgo/go/os/fifo_test.go +++ b/libgo/go/os/fifo_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd // +build darwin dragonfly freebsd linux netbsd openbsd package os_test @@ -25,17 +26,9 @@ func TestFifoEOF(t *testing.T) { switch runtime.GOOS { case "android": t.Skip("skipping on Android; mkfifo syscall not available") - case "openbsd": - // On OpenBSD 6.2 this test just hangs for some reason. - t.Skip("skipping on OpenBSD; issue 25877") } - dir, err := os.MkdirTemp("", "TestFifoEOF") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dir) - + dir := t.TempDir() fifoName := filepath.Join(dir, "fifo") if err := syscall.Mkfifo(fifoName, 0600); err != nil { t.Fatal(err) diff --git a/libgo/go/os/file.go b/libgo/go/os/file.go index 52dd943..e717f17 100644 --- a/libgo/go/os/file.go +++ b/libgo/go/os/file.go @@ -44,11 +44,13 @@ import ( "errors" "internal/poll" "internal/testlog" + "internal/unsafeheader" "io" "io/fs" "runtime" "syscall" "time" + "unsafe" ) // Name returns the name of the file as presented to Open. @@ -246,7 +248,12 @@ func (f *File) Seek(offset int64, whence int) (ret int64, err error) { // WriteString is like Write, but writes the contents of string s rather than // a slice of bytes. func (f *File) WriteString(s string) (n int, err error) { - return f.Write([]byte(s)) + var b []byte + hdr := (*unsafeheader.Slice)(unsafe.Pointer(&b)) + hdr.Data = (*unsafeheader.String)(unsafe.Pointer(&s)).Data + hdr.Cap = len(s) + hdr.Len = len(s) + return f.Write(b) } // Mkdir creates a new directory with the specified name and permission @@ -644,6 +651,17 @@ func (dir dirFS) Open(name string) (fs.File, error) { return f, nil } +func (dir dirFS) Stat(name string) (fs.FileInfo, error) { + if !fs.ValidPath(name) || runtime.GOOS == "windows" && containsAny(name, `\:`) { + return nil, &PathError{Op: "stat", Path: name, Err: ErrInvalid} + } + f, err := Stat(string(dir) + "/" + name) + if err != nil { + return nil, err + } + return f, nil +} + // ReadFile reads the named file and returns the contents. // A successful call returns err == nil, not err == EOF. // Because ReadFile reads the whole file, it does not treat an EOF from Read diff --git a/libgo/go/os/file_plan9.go b/libgo/go/os/file_plan9.go index 4f384e9..604aea6 100644 --- a/libgo/go/os/file_plan9.go +++ b/libgo/go/os/file_plan9.go @@ -440,6 +440,8 @@ func Link(oldname, newname string) error { } // Symlink creates newname as a symbolic link to oldname. +// On Windows, a symlink to a non-existent oldname creates a file symlink; +// if oldname is later created as a directory the symlink will not work. // If there is an error, it will be of type *LinkError. func Symlink(oldname, newname string) error { return &LinkError{"symlink", oldname, newname, syscall.EPLAN9} diff --git a/libgo/go/os/file_posix.go b/libgo/go/os/file_posix.go index 95bf9e7..21831a7 100644 --- a/libgo/go/os/file_posix.go +++ b/libgo/go/os/file_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows package os diff --git a/libgo/go/os/file_unix.go b/libgo/go/os/file_unix.go index 5888d48..a31800bd 100644 --- a/libgo/go/os/file_unix.go +++ b/libgo/go/os/file_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package os @@ -173,7 +174,7 @@ func newFile(fd uintptr, name string, kind newFileKind) *File { // with the netpoll system. That can happen for // a file descriptor that is not supported by // epoll/kqueue; for example, disk files on - // GNU/Linux systems. We assume that any real error + // Linux systems. We assume that any real error // will show up in later I/O. } else if pollable { // We successfully registered with netpoll, so put @@ -261,6 +262,7 @@ func (file *file) close() error { var err error if file.dirinfo != nil { file.dirinfo.close() + file.dirinfo = nil } if e := file.pfd.Close(); e != nil { if e == poll.ErrFileClosing { @@ -363,6 +365,8 @@ func Link(oldname, newname string) error { } // Symlink creates newname as a symbolic link to oldname. +// On Windows, a symlink to a non-existent oldname creates a file symlink; +// if oldname is later created as a directory the symlink will not work. // If there is an error, it will be of type *LinkError. func Symlink(oldname, newname string) error { e := ignoringEINTR(func() error { diff --git a/libgo/go/os/os_test.go b/libgo/go/os/os_test.go index 734c655..0cde454 100644 --- a/libgo/go/os/os_test.go +++ b/libgo/go/os/os_test.go @@ -615,11 +615,7 @@ func TestReaddirNValues(t *testing.T) { if testing.Short() { t.Skip("test.short; skipping") } - dir, err := os.MkdirTemp("", "") - if err != nil { - t.Fatalf("TempDir: %v", err) - } - defer RemoveAll(dir) + dir := t.TempDir() for i := 1; i <= 105; i++ { f, err := Create(filepath.Join(dir, fmt.Sprintf("%d", i))) if err != nil { @@ -714,11 +710,7 @@ func TestReaddirStatFailures(t *testing.T) { // testing it wouldn't work. t.Skipf("skipping test on %v", runtime.GOOS) } - dir, err := os.MkdirTemp("", "") - if err != nil { - t.Fatalf("TempDir: %v", err) - } - defer RemoveAll(dir) + dir := t.TempDir() touch(t, filepath.Join(dir, "good1")) touch(t, filepath.Join(dir, "x")) // will disappear or have an error touch(t, filepath.Join(dir, "good2")) @@ -1951,22 +1943,16 @@ func TestAppend(t *testing.T) { func TestStatDirWithTrailingSlash(t *testing.T) { // Create new temporary directory and arrange to clean it up. - path, err := os.MkdirTemp("", "_TestStatDirWithSlash_") - if err != nil { - t.Fatalf("TempDir: %s", err) - } - defer RemoveAll(path) + path := t.TempDir() // Stat of path should succeed. - _, err = Stat(path) - if err != nil { + if _, err := Stat(path); err != nil { t.Fatalf("stat %s failed: %s", path, err) } // Stat of path+"/" should succeed too. path += "/" - _, err = Stat(path) - if err != nil { + if _, err := Stat(path); err != nil { t.Fatalf("stat %s failed: %s", path, err) } } @@ -2093,12 +2079,7 @@ func TestLargeWriteToConsole(t *testing.T) { func TestStatDirModeExec(t *testing.T) { const mode = 0111 - path, err := os.MkdirTemp("", "go-build") - if err != nil { - t.Fatalf("Failed to create temp directory: %v", err) - } - defer RemoveAll(path) - + path := t.TempDir() if err := Chmod(path, 0777); err != nil { t.Fatalf("Chmod %q 0777: %v", path, err) } @@ -2162,12 +2143,7 @@ func TestStatStdin(t *testing.T) { func TestStatRelativeSymlink(t *testing.T) { testenv.MustHaveSymlink(t) - tmpdir, err := os.MkdirTemp("", "TestStatRelativeSymlink") - if err != nil { - t.Fatal(err) - } - defer RemoveAll(tmpdir) - + tmpdir := t.TempDir() target := filepath.Join(tmpdir, "target") f, err := Create(target) if err != nil { @@ -2775,3 +2751,21 @@ func TestReadFileProc(t *testing.T) { t.Fatalf("read %s: not newline-terminated: %q", name, data) } } + +func TestWriteStringAlloc(t *testing.T) { + if runtime.GOOS == "js" { + t.Skip("js allocates a lot during File.WriteString") + } + d := t.TempDir() + f, err := Create(filepath.Join(d, "whiteboard.txt")) + if err != nil { + t.Fatal(err) + } + defer f.Close() + allocs := testing.AllocsPerRun(100, func() { + f.WriteString("I will not allocate when passed a string longer than 32 bytes.\n") + }) + if allocs != 0 { + t.Errorf("expected 0 allocs for File.WriteString, got %v", allocs) + } +} diff --git a/libgo/go/os/os_unix_test.go b/libgo/go/os/os_unix_test.go index 9a5d7bf..95ceb0d 100644 --- a/libgo/go/os/os_unix_test.go +++ b/libgo/go/os/os_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package os_test diff --git a/libgo/go/os/os_windows_test.go b/libgo/go/os/os_windows_test.go index b0929b4..195c30f 100644 --- a/libgo/go/os/os_windows_test.go +++ b/libgo/go/os/os_windows_test.go @@ -29,22 +29,32 @@ import ( // For TestRawConnReadWrite. type syscallDescriptor = syscall.Handle -func TestSameWindowsFile(t *testing.T) { - temp, err := os.MkdirTemp("", "TestSameWindowsFile") +// chdir changes the current working directory to the named directory, +// and then restore the original working directory at the end of the test. +func chdir(t *testing.T, dir string) { + olddir, err := os.Getwd() if err != nil { - t.Fatal(err) + t.Fatalf("chdir: %v", err) } - defer os.RemoveAll(temp) - - wd, err := os.Getwd() - if err != nil { - t.Fatal(err) + if err := os.Chdir(dir); err != nil { + t.Fatalf("chdir %s: %v", dir, err) } - err = os.Chdir(temp) + + t.Cleanup(func() { + if err := os.Chdir(olddir); err != nil { + t.Errorf("chdir to original working directory %s: %v", olddir, err) + os.Exit(1) + } + }) +} + +func TestSameWindowsFile(t *testing.T) { + temp, err := os.MkdirTemp("", "TestSameWindowsFile") if err != nil { t.Fatal(err) } - defer os.Chdir(wd) + defer os.RemoveAll(temp) + chdir(t, temp) f, err := os.Create("a") if err != nil { @@ -94,16 +104,7 @@ func testDirLinks(t *testing.T, tests []dirLinkTest) { t.Fatal(err) } defer os.RemoveAll(tmpdir) - - oldwd, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - err = os.Chdir(tmpdir) - if err != nil { - t.Fatal(err) - } - defer os.Chdir(oldwd) + chdir(t, tmpdir) dir := filepath.Join(tmpdir, "dir") err = os.Mkdir(dir, 0777) @@ -444,15 +445,7 @@ func TestNetworkSymbolicLink(t *testing.T) { } defer os.RemoveAll(dir) - oldwd, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - err = os.Chdir(dir) - if err != nil { - t.Fatal(err) - } - defer os.Chdir(oldwd) + chdir(t, dir) shareName := "GoSymbolicLinkTestShare" // hope no conflictions sharePath := filepath.Join(dir, shareName) @@ -604,16 +597,7 @@ func TestOpenVolumeName(t *testing.T) { t.Fatal(err) } defer os.RemoveAll(tmpdir) - - wd, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - err = os.Chdir(tmpdir) - if err != nil { - t.Fatal(err) - } - defer os.Chdir(wd) + chdir(t, tmpdir) want := []string{"file1", "file2", "file3", "gopher.txt"} sort.Strings(want) @@ -642,11 +626,7 @@ func TestOpenVolumeName(t *testing.T) { } func TestDeleteReadOnly(t *testing.T) { - tmpdir, err := os.MkdirTemp("", "TestDeleteReadOnly") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) + tmpdir := t.TempDir() p := filepath.Join(tmpdir, "a") // This sets FILE_ATTRIBUTE_READONLY. f, err := os.OpenFile(p, os.O_CREATE, 0400) @@ -812,11 +792,7 @@ func compareCommandLineToArgvWithSyscall(t *testing.T, cmd string) { } func TestCmdArgs(t *testing.T) { - tmpdir, err := os.MkdirTemp("", "TestCmdArgs") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) + tmpdir := t.TempDir() const prog = ` package main @@ -831,8 +807,7 @@ func main() { } ` src := filepath.Join(tmpdir, "main.go") - err = os.WriteFile(src, []byte(prog), 0666) - if err != nil { + if err := os.WriteFile(src, []byte(prog), 0666); err != nil { t.Fatal(err) } @@ -979,21 +954,14 @@ func TestSymlinkCreation(t *testing.T) { } t.Parallel() - temp, err := os.MkdirTemp("", "TestSymlinkCreation") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(temp) - + temp := t.TempDir() dummyFile := filepath.Join(temp, "file") - err = os.WriteFile(dummyFile, []byte(""), 0644) - if err != nil { + if err := os.WriteFile(dummyFile, []byte(""), 0644); err != nil { t.Fatal(err) } linkFile := filepath.Join(temp, "link") - err = os.Symlink(dummyFile, linkFile) - if err != nil { + if err := os.Symlink(dummyFile, linkFile); err != nil { t.Fatal(err) } } @@ -1226,16 +1194,7 @@ func TestWindowsReadlink(t *testing.T) { if err != nil { t.Fatal(err) } - - wd, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - err = os.Chdir(tmpdir) - if err != nil { - t.Fatal(err) - } - defer os.Chdir(wd) + chdir(t, tmpdir) vol := filepath.VolumeName(tmpdir) output, err := osexec.Command("cmd", "/c", "mountvol", vol, "/L").CombinedOutput() diff --git a/libgo/go/os/path_test.go b/libgo/go/os/path_test.go index b79d958..4535abb 100644 --- a/libgo/go/os/path_test.go +++ b/libgo/go/os/path_test.go @@ -6,7 +6,6 @@ package os_test import ( "internal/testenv" - "os" . "os" "path/filepath" "runtime" @@ -78,27 +77,19 @@ func TestMkdirAll(t *testing.T) { func TestMkdirAllWithSymlink(t *testing.T) { testenv.MustHaveSymlink(t) - tmpDir, err := os.MkdirTemp("", "TestMkdirAllWithSymlink-") - if err != nil { - t.Fatal(err) - } - defer RemoveAll(tmpDir) - + tmpDir := t.TempDir() dir := tmpDir + "/dir" - err = Mkdir(dir, 0755) - if err != nil { + if err := Mkdir(dir, 0755); err != nil { t.Fatalf("Mkdir %s: %s", dir, err) } link := tmpDir + "/link" - err = Symlink("dir", link) - if err != nil { + if err := Symlink("dir", link); err != nil { t.Fatalf("Symlink %s: %s", link, err) } path := link + "/foo" - err = MkdirAll(path, 0755) - if err != nil { + if err := MkdirAll(path, 0755); err != nil { t.Errorf("MkdirAll %q: %s", path, err) } } diff --git a/libgo/go/os/path_unix.go b/libgo/go/os/path_unix.go index 6ef6560..bb0b0a0 100644 --- a/libgo/go/os/path_unix.go +++ b/libgo/go/os/path_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package os diff --git a/libgo/go/os/path_windows.go b/libgo/go/os/path_windows.go index 87b1cac..a96245f 100644 --- a/libgo/go/os/path_windows.go +++ b/libgo/go/os/path_windows.go @@ -128,6 +128,10 @@ func dirname(path string) string { return vol + dir } +// This is set via go:linkname on runtime.canUseLongPaths, and is true when the OS +// supports opting into proper long path handling without the need for fixups. +var canUseLongPaths bool + // fixLongPath returns the extended-length (\\?\-prefixed) form of // path when needed, in order to avoid the default 260 character file // path limit imposed by Windows. If path is not easily converted to @@ -137,6 +141,9 @@ func dirname(path string) string { // // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath func fixLongPath(path string) string { + if canUseLongPaths { + return path + } // Do nothing (and don't allocate) if the path is "short". // Empirically (at least on the Windows Server 2013 builder), // the kernel is arbitrarily okay with < 248 bytes. That diff --git a/libgo/go/os/path_windows_test.go b/libgo/go/os/path_windows_test.go index 869db8f..e960bcb 100644 --- a/libgo/go/os/path_windows_test.go +++ b/libgo/go/os/path_windows_test.go @@ -12,6 +12,9 @@ import ( ) func TestFixLongPath(t *testing.T) { + if os.CanUseLongPaths { + return + } // 248 is long enough to trigger the longer-than-248 checks in // fixLongPath, but short enough not to make a path component // longer than 255, which is illegal on Windows. (which @@ -46,12 +49,22 @@ func TestFixLongPath(t *testing.T) { } } -func TestMkdirAllExtendedLength(t *testing.T) { - tmpDir, err := os.MkdirTemp("", "TestMkdirAllExtendedLength") - if err != nil { - t.Fatal(err) +func TestMkdirAllLongPath(t *testing.T) { + tmpDir := t.TempDir() + path := tmpDir + for i := 0; i < 100; i++ { + path += `\another-path-component` + } + if err := os.MkdirAll(path, 0777); err != nil { + t.Fatalf("MkdirAll(%q) failed; %v", path, err) + } + if err := os.RemoveAll(tmpDir); err != nil { + t.Fatalf("RemoveAll(%q) failed; %v", tmpDir, err) } - defer os.RemoveAll(tmpDir) +} + +func TestMkdirAllExtendedLength(t *testing.T) { + tmpDir := t.TempDir() const prefix = `\\?\` if len(tmpDir) < 4 || tmpDir[:4] != prefix { @@ -62,14 +75,12 @@ func TestMkdirAllExtendedLength(t *testing.T) { tmpDir = prefix + fullPath } path := tmpDir + `\dir\` - err = os.MkdirAll(path, 0777) - if err != nil { + if err := os.MkdirAll(path, 0777); err != nil { t.Fatalf("MkdirAll(%q) failed: %v", path, err) } path = path + `.\dir2` - err = os.MkdirAll(path, 0777) - if err == nil { + if err := os.MkdirAll(path, 0777); err == nil { t.Fatalf("MkdirAll(%q) should have failed, but did not", path) } } diff --git a/libgo/go/os/pipe2_bsd.go b/libgo/go/os/pipe2_bsd.go index 0ef894b..bf6d081 100644 --- a/libgo/go/os/pipe2_bsd.go +++ b/libgo/go/os/pipe2_bsd.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build freebsd netbsd openbsd +//go:build dragonfly || freebsd || netbsd || openbsd +// +build dragonfly freebsd netbsd openbsd package os diff --git a/libgo/go/os/pipe2_illumos.go b/libgo/go/os/pipe2_illumos.go index 026ce62..71b8cb8 100644 --- a/libgo/go/os/pipe2_illumos.go +++ b/libgo/go/os/pipe2_illumos.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build illumos // +build illumos package os diff --git a/libgo/go/os/pipe_bsd.go b/libgo/go/os/pipe_bsd.go index 115d6ba..097b32e 100644 --- a/libgo/go/os/pipe_bsd.go +++ b/libgo/go/os/pipe_bsd.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly js,wasm solaris,!illumos +//go:build aix || darwin || (js && wasm) || (solaris && !illumos) +// +build aix darwin js,wasm solaris,!illumos package os diff --git a/libgo/go/os/pipe_test.go b/libgo/go/os/pipe_test.go index b98e538..41a1e9c 100644 --- a/libgo/go/os/pipe_test.go +++ b/libgo/go/os/pipe_test.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. // Test broken pipes on Unix systems. +//go:build !plan9 && !js // +build !plan9,!js package os_test @@ -441,12 +442,14 @@ func TestFdReadRace(t *testing.T) { defer r.Close() defer w.Close() - c := make(chan bool) + const count = 10 + + c := make(chan bool, 1) var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() - var buf [10]byte + var buf [count]byte r.SetReadDeadline(time.Now().Add(time.Minute)) c <- true if _, err := r.Read(buf[:]); os.IsTimeout(err) { @@ -465,8 +468,9 @@ func TestFdReadRace(t *testing.T) { r.Fd() // The bug was that Fd would hang until Read timed out. - // If the bug is fixed, then closing r here will cause - // the Read to exit before the timeout expires. + // If the bug is fixed, then writing to w and closing r here + // will cause the Read to exit before the timeout expires. + w.Write(make([]byte, count)) r.Close() }() diff --git a/libgo/go/os/rawconn.go b/libgo/go/os/rawconn.go index 9e11cda..ffc598b 100644 --- a/libgo/go/os/rawconn.go +++ b/libgo/go/os/rawconn.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 // +build !plan9 package os diff --git a/libgo/go/os/rawconn_test.go b/libgo/go/os/rawconn_test.go index 2554f5b..8aebaf8 100644 --- a/libgo/go/os/rawconn_test.go +++ b/libgo/go/os/rawconn_test.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. // Test use of raw connections. +//go:build !plan9 && !js // +build !plan9,!js package os_test diff --git a/libgo/go/os/readfrom_linux_test.go b/libgo/go/os/readfrom_linux_test.go index 1d145da..cb6a59a 100644 --- a/libgo/go/os/readfrom_linux_test.go +++ b/libgo/go/os/readfrom_linux_test.go @@ -106,7 +106,7 @@ func TestCopyFileRange(t *testing.T) { t.Fatal(err) } if n != int64(len(data)) { - t.Fatalf("transfered %d, want %d", n, len(data)) + t.Fatalf("transferred %d, want %d", n, len(data)) } if !hook.called { t.Fatalf("should have called poll.CopyFileRange") @@ -130,7 +130,7 @@ func TestCopyFileRange(t *testing.T) { t.Fatal(err) } if n != int64(len(data)) { - t.Fatalf("transfered %d, want %d", n, len(data)) + t.Fatalf("transferred %d, want %d", n, len(data)) } if !hook.called { t.Fatalf("should have called poll.CopyFileRange") @@ -162,7 +162,7 @@ func TestCopyFileRange(t *testing.T) { t.Fatal(err) } if n != int64(len(data)) { - t.Fatalf("transfered %d, want %d", n, len(data)) + t.Fatalf("transferred %d, want %d", n, len(data)) } if !hook.called { t.Fatalf("should have called poll.CopyFileRange") diff --git a/libgo/go/os/readfrom_stub.go b/libgo/go/os/readfrom_stub.go index 65429d0..826760f 100644 --- a/libgo/go/os/readfrom_stub.go +++ b/libgo/go/os/readfrom_stub.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !linux // +build !linux package os diff --git a/libgo/go/os/removeall_at.go b/libgo/go/os/removeall_at.go index f9eafa1..4e55577 100644 --- a/libgo/go/os/removeall_at.go +++ b/libgo/go/os/removeall_at.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package os diff --git a/libgo/go/os/removeall_noat.go b/libgo/go/os/removeall_noat.go index a4cde5a..966f3f5 100644 --- a/libgo/go/os/removeall_noat.go +++ b/libgo/go/os/removeall_noat.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !aix && !darwin && !dragonfly && !freebsd && !hurd && !linux && !netbsd && !openbsd && !solaris // +build !aix,!darwin,!dragonfly,!freebsd,!hurd,!linux,!netbsd,!openbsd,!solaris package os diff --git a/libgo/go/os/removeall_test.go b/libgo/go/os/removeall_test.go index 3a2f6e3..08dfdd8 100644 --- a/libgo/go/os/removeall_test.go +++ b/libgo/go/os/removeall_test.go @@ -15,12 +15,7 @@ import ( ) func TestRemoveAll(t *testing.T) { - tmpDir, err := os.MkdirTemp("", "TestRemoveAll-") - if err != nil { - t.Fatal(err) - } - defer RemoveAll(tmpDir) - + tmpDir := t.TempDir() if err := RemoveAll(""); err != nil { t.Errorf("RemoveAll(\"\"): %v; want nil", err) } @@ -128,12 +123,7 @@ func TestRemoveAllLarge(t *testing.T) { t.Skip("skipping in short mode") } - tmpDir, err := os.MkdirTemp("", "TestRemoveAll-") - if err != nil { - t.Fatal(err) - } - defer RemoveAll(tmpDir) - + tmpDir := t.TempDir() path := filepath.Join(tmpDir, "_TestRemoveAllLarge_") // Make directory with 1000 files and remove. @@ -236,12 +226,7 @@ func TestRemoveAllDot(t *testing.T) { func TestRemoveAllDotDot(t *testing.T) { t.Parallel() - tempDir, err := os.MkdirTemp("", "TestRemoveAllDotDot-") - if err != nil { - t.Fatal(err) - } - defer RemoveAll(tempDir) - + tempDir := t.TempDir() subdir := filepath.Join(tempDir, "x") subsubdir := filepath.Join(subdir, "y") if err := MkdirAll(subsubdir, 0777); err != nil { @@ -261,12 +246,7 @@ func TestRemoveAllDotDot(t *testing.T) { func TestRemoveReadOnlyDir(t *testing.T) { t.Parallel() - tempDir, err := os.MkdirTemp("", "TestRemoveReadOnlyDir-") - if err != nil { - t.Fatal(err) - } - defer RemoveAll(tempDir) - + tempDir := t.TempDir() subdir := filepath.Join(tempDir, "x") if err := Mkdir(subdir, 0); err != nil { t.Fatal(err) @@ -298,12 +278,7 @@ func TestRemoveAllButReadOnlyAndPathError(t *testing.T) { t.Parallel() - tempDir, err := os.MkdirTemp("", "TestRemoveAllButReadOnly-") - if err != nil { - t.Fatal(err) - } - defer RemoveAll(tempDir) - + tempDir := t.TempDir() dirs := []string{ "a", "a/x", @@ -347,7 +322,7 @@ func TestRemoveAllButReadOnlyAndPathError(t *testing.T) { defer Chmod(d, 0777) } - err = RemoveAll(tempDir) + err := RemoveAll(tempDir) if err == nil { t.Fatal("RemoveAll succeeded unexpectedly") } @@ -389,12 +364,7 @@ func TestRemoveUnreadableDir(t *testing.T) { t.Parallel() - tempDir, err := os.MkdirTemp("", "TestRemoveAllButReadOnly-") - if err != nil { - t.Fatal(err) - } - defer RemoveAll(tempDir) - + tempDir := t.TempDir() target := filepath.Join(tempDir, "d0", "d1", "d2") if err := MkdirAll(target, 0755); err != nil { t.Fatal(err) @@ -413,12 +383,7 @@ func TestRemoveAllWithMoreErrorThanReqSize(t *testing.T) { t.Skip("skipping in short mode") } - tmpDir, err := os.MkdirTemp("", "TestRemoveAll-") - if err != nil { - t.Fatal(err) - } - defer RemoveAll(tmpDir) - + tmpDir := t.TempDir() path := filepath.Join(tmpDir, "_TestRemoveAllWithMoreErrorThanReqSize_") // Make directory with 1025 read-only files. @@ -443,7 +408,7 @@ func TestRemoveAllWithMoreErrorThanReqSize(t *testing.T) { // This call should not hang, even on a platform that disallows file deletion // from read-only directories. - err = RemoveAll(path) + err := RemoveAll(path) if Getuid() == 0 { // On many platforms, root can remove files from read-only directories. diff --git a/libgo/go/os/signal/doc.go b/libgo/go/os/signal/doc.go index 2229d36..7af61d2 100644 --- a/libgo/go/os/signal/doc.go +++ b/libgo/go/os/signal/doc.go @@ -50,7 +50,7 @@ If the Go program is started with either SIGHUP or SIGINT ignored If the Go program is started with a non-empty signal mask, that will generally be honored. However, some signals are explicitly unblocked: the synchronous signals, SIGILL, SIGTRAP, SIGSTKFLT, SIGCHLD, SIGPROF, -and, on GNU/Linux, signals 32 (SIGCANCEL) and 33 (SIGSETXID) +and, on Linux, signals 32 (SIGCANCEL) and 33 (SIGSETXID) (SIGCANCEL and SIGSETXID are used internally by glibc). Subprocesses started by os.Exec, or by the os/exec package, will inherit the modified signal mask. @@ -129,9 +129,7 @@ If the non-Go code installs any signal handlers, it must use the SA_ONSTACK flag with sigaction. Failing to do so is likely to cause the program to crash if the signal is received. Go programs routinely run with a limited stack, and therefore set up an alternate signal -stack. Also, the Go standard library expects that any signal handlers -will use the SA_RESTART flag. Failing to do so may cause some library -calls to return "interrupted system call" errors. +stack. If the non-Go code installs a signal handler for any of the synchronous signals (SIGBUS, SIGFPE, SIGSEGV), then it should record @@ -178,7 +176,7 @@ will initialize signals at global constructor time. For shared library is loaded. If the Go runtime sees an existing signal handler for the SIGCANCEL or -SIGSETXID signals (which are used only on GNU/Linux), it will turn on +SIGSETXID signals (which are used only on Linux), it will turn on the SA_ONSTACK flag and otherwise keep the signal handler. For the synchronous signals and SIGPIPE, the Go runtime will install a diff --git a/libgo/go/os/signal/example_unix_test.go b/libgo/go/os/signal/example_unix_test.go index a0af37a..3f7795b 100644 --- a/libgo/go/os/signal/example_unix_test.go +++ b/libgo/go/os/signal/example_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package signal_test diff --git a/libgo/go/os/signal/internal/pty/pty.go b/libgo/go/os/signal/internal/pty/pty.go index dd0aee1..4ed3eb4 100644 --- a/libgo/go/os/signal/internal/pty/pty.go +++ b/libgo/go/os/signal/internal/pty/pty.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (aix || darwin || dragonfly || freebsd || hurd || (linux && !android) || netbsd || openbsd || solaris) && cgo // +build aix darwin dragonfly freebsd hurd linux,!android netbsd openbsd solaris // +build cgo diff --git a/libgo/go/os/signal/signal_cgo_test.go b/libgo/go/os/signal/signal_cgo_test.go index a8a4856..e1e4509 100644 --- a/libgo/go/os/signal/signal_cgo_test.go +++ b/libgo/go/os/signal/signal_cgo_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (darwin || dragonfly || freebsd || (linux && !android) || netbsd || openbsd) && cgo // +build darwin dragonfly freebsd linux,!android netbsd openbsd // +build cgo diff --git a/libgo/go/os/signal/signal_linux_test.go b/libgo/go/os/signal/signal_linux_test.go index 2e553d0..7abe1ec 100644 --- a/libgo/go/os/signal/signal_linux_test.go +++ b/libgo/go/os/signal/signal_linux_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux // +build linux package signal diff --git a/libgo/go/os/signal/signal_plan9_test.go b/libgo/go/os/signal/signal_plan9_test.go index 10bfdc3..8357199 100644 --- a/libgo/go/os/signal/signal_plan9_test.go +++ b/libgo/go/os/signal/signal_plan9_test.go @@ -5,6 +5,7 @@ package signal import ( + "internal/itoa" "os" "runtime" "syscall" @@ -155,23 +156,8 @@ func TestStop(t *testing.T) { } } -func itoa(val int) string { - if val < 0 { - return "-" + itoa(-val) - } - var buf [32]byte // big enough for int64 - i := len(buf) - 1 - for val >= 10 { - buf[i] = byte(val%10 + '0') - i-- - val /= 10 - } - buf[i] = byte(val + '0') - return string(buf[i:]) -} - func postNote(pid int, note string) error { - f, err := os.OpenFile("/proc/"+itoa(pid)+"/note", os.O_WRONLY, 0) + f, err := os.OpenFile("/proc/"+itoa.Itoa(pid)+"/note", os.O_WRONLY, 0) if err != nil { return err } diff --git a/libgo/go/os/signal/signal_test.go b/libgo/go/os/signal/signal_test.go index 1f89780..c653c34 100644 --- a/libgo/go/os/signal/signal_test.go +++ b/libgo/go/os/signal/signal_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package signal @@ -17,6 +18,7 @@ import ( "runtime" "runtime/trace" "strconv" + "strings" "sync" "syscall" "testing" @@ -30,6 +32,11 @@ import ( // The current value is set based on flakes observed in the Go builders. var settleTime = 100 * time.Millisecond +// fatalWaitingTime is an absurdly long time to wait for signals to be +// delivered but, using it, we (hopefully) eliminate test flakes on the +// build servers. See #46736 for discussion. +var fatalWaitingTime = 30 * time.Second + func init() { if testenv.Builder() == "solaris-amd64-oraclerel" { // The solaris-amd64-oraclerel builder has been observed to time out in @@ -46,6 +53,13 @@ func init() { // // See https://golang.org/issue/33174. settleTime = 11 * time.Second + } else if runtime.GOOS == "linux" && strings.HasPrefix(runtime.GOARCH, "ppc64") { + // Older linux kernels seem to have some hiccups delivering the signal + // in a timely manner on ppc64 and ppc64le. When running on a + // ppc64le/ubuntu 16.04/linux 4.4 host the time can vary quite + // substantially even on a idle system. 5 seconds is twice any value + // observed when running 10000 tests on such a system. + settleTime = 5 * time.Second } else if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" { if scale, err := strconv.Atoi(s); err == nil { settleTime *= time.Duration(scale) @@ -75,7 +89,7 @@ func waitSig1(t *testing.T, c <-chan os.Signal, sig os.Signal, all bool) { // General user code should filter out all unexpected signals instead of just // SIGURG, but since os/signal is tightly coupled to the runtime it seems // appropriate to be stricter here. - for time.Since(start) < settleTime { + for time.Since(start) < fatalWaitingTime { select { case s := <-c: if s == sig { @@ -88,7 +102,7 @@ func waitSig1(t *testing.T, c <-chan os.Signal, sig os.Signal, all bool) { timer.Reset(settleTime / 10) } } - t.Fatalf("timeout after %v waiting for %v", settleTime, sig) + t.Fatalf("timeout after %v waiting for %v", fatalWaitingTime, sig) } // quiesce waits until we can be reasonably confident that all pending signals diff --git a/libgo/go/os/signal/signal_unix.go b/libgo/go/os/signal/signal_unix.go index c18db0c..a0c7ffb 100644 --- a/libgo/go/os/signal/signal_unix.go +++ b/libgo/go/os/signal/signal_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows package signal diff --git a/libgo/go/os/stat_js.go b/libgo/go/os/stat_js.go index 8d20ccd..3badf5b 100644 --- a/libgo/go/os/stat_js.go +++ b/libgo/go/os/stat_js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package os diff --git a/libgo/go/os/stat_test.go b/libgo/go/os/stat_test.go index c409f0f..8d99f64 100644 --- a/libgo/go/os/stat_test.go +++ b/libgo/go/os/stat_test.go @@ -185,30 +185,22 @@ func testSymlinkSameFile(t *testing.T, path, link string) { func TestDirAndSymlinkStats(t *testing.T) { testenv.MustHaveSymlink(t) - tmpdir, err := os.MkdirTemp("", "TestDirAndSymlinkStats") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) - + tmpdir := t.TempDir() dir := filepath.Join(tmpdir, "dir") - err = os.Mkdir(dir, 0777) - if err != nil { + if err := os.Mkdir(dir, 0777); err != nil { t.Fatal(err) } testDirStats(t, dir) dirlink := filepath.Join(tmpdir, "link") - err = os.Symlink(dir, dirlink) - if err != nil { + if err := os.Symlink(dir, dirlink); err != nil { t.Fatal(err) } testSymlinkStats(t, dirlink, true) testSymlinkSameFile(t, dir, dirlink) linklink := filepath.Join(tmpdir, "linklink") - err = os.Symlink(dirlink, linklink) - if err != nil { + if err := os.Symlink(dirlink, linklink); err != nil { t.Fatal(err) } testSymlinkStats(t, linklink, true) @@ -218,30 +210,22 @@ func TestDirAndSymlinkStats(t *testing.T) { func TestFileAndSymlinkStats(t *testing.T) { testenv.MustHaveSymlink(t) - tmpdir, err := os.MkdirTemp("", "TestFileAndSymlinkStats") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) - + tmpdir := t.TempDir() file := filepath.Join(tmpdir, "file") - err = os.WriteFile(file, []byte(""), 0644) - if err != nil { + if err := os.WriteFile(file, []byte(""), 0644); err != nil { t.Fatal(err) } testFileStats(t, file) filelink := filepath.Join(tmpdir, "link") - err = os.Symlink(file, filelink) - if err != nil { + if err := os.Symlink(file, filelink); err != nil { t.Fatal(err) } testSymlinkStats(t, filelink, false) testSymlinkSameFile(t, file, filelink) linklink := filepath.Join(tmpdir, "linklink") - err = os.Symlink(filelink, linklink) - if err != nil { + if err := os.Symlink(filelink, linklink); err != nil { t.Fatal(err) } testSymlinkStats(t, linklink, false) @@ -252,20 +236,13 @@ func TestFileAndSymlinkStats(t *testing.T) { func TestSymlinkWithTrailingSlash(t *testing.T) { testenv.MustHaveSymlink(t) - tmpdir, err := os.MkdirTemp("", "TestSymlinkWithTrailingSlash") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) - + tmpdir := t.TempDir() dir := filepath.Join(tmpdir, "dir") - err = os.Mkdir(dir, 0777) - if err != nil { + if err := os.Mkdir(dir, 0777); err != nil { t.Fatal(err) } dirlink := filepath.Join(tmpdir, "link") - err = os.Symlink(dir, dirlink) - if err != nil { + if err := os.Symlink(dir, dirlink); err != nil { t.Fatal(err) } dirlinkWithSlash := dirlink + string(os.PathSeparator) diff --git a/libgo/go/os/stat_unix.go b/libgo/go/os/stat_unix.go index 7873bf9..6ae26ad 100644 --- a/libgo/go/os/stat_unix.go +++ b/libgo/go/os/stat_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package os diff --git a/libgo/go/os/sticky_bsd.go b/libgo/go/os/sticky_bsd.go index c09b1ac..ab23d81 100644 --- a/libgo/go/os/sticky_bsd.go +++ b/libgo/go/os/sticky_bsd.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd js,wasm netbsd openbsd solaris package os diff --git a/libgo/go/os/sticky_notbsd.go b/libgo/go/os/sticky_notbsd.go index c158506..9979b43 100644 --- a/libgo/go/os/sticky_notbsd.go +++ b/libgo/go/os/sticky_notbsd.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !aix && !darwin && !dragonfly && !freebsd && (!js || !wasm) && !netbsd && !openbsd && !solaris // +build !aix // +build !darwin // +build !dragonfly diff --git a/libgo/go/os/str.go b/libgo/go/os/str.go index cba9fa3..35643e0 100644 --- a/libgo/go/os/str.go +++ b/libgo/go/os/str.go @@ -6,28 +6,34 @@ package os -// Convert integer to decimal string -func itoa(val int) string { +// itox converts val (an int) to a hexdecimal string. +func itox(val int) string { if val < 0 { - return "-" + uitoa(uint(-val)) + return "-" + uitox(uint(-val)) } - return uitoa(uint(val)) + return uitox(uint(val)) } -// Convert unsigned integer to decimal string -func uitoa(val uint) string { +const hex = "0123456789abcdef" + +// uitox converts val (a uint) to a hexdecimal string. +func uitox(val uint) string { if val == 0 { // avoid string allocation - return "0" + return "0x0" } - var buf [20]byte // big enough for 64bit value base 10 + var buf [20]byte // big enough for 64bit value base 16 + 0x i := len(buf) - 1 - for val >= 10 { - q := val / 10 - buf[i] = byte('0' + val - q*10) + for val >= 16 { + q := val / 16 + buf[i] = hex[val%16] i-- val = q } - // val < 10 - buf[i] = byte('0' + val) + // val < 16 + buf[i] = hex[val%16] + i-- + buf[i] = 'x' + i-- + buf[i] = '0' return string(buf[i:]) } diff --git a/libgo/go/os/sys_bsd.go b/libgo/go/os/sys_bsd.go index b1698f5..1e245eb 100644 --- a/libgo/go/os/sys_bsd.go +++ b/libgo/go/os/sys_bsd.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || (js && wasm) || netbsd || openbsd // +build darwin dragonfly freebsd js,wasm netbsd openbsd package os diff --git a/libgo/go/os/sys_js.go b/libgo/go/os/sys_js.go index e860654..4d6a64e 100644 --- a/libgo/go/os/sys_js.go +++ b/libgo/go/os/sys_js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package os diff --git a/libgo/go/os/sys_unix.go b/libgo/go/os/sys_unix.go index 37b5a47..aab683e 100644 --- a/libgo/go/os/sys_unix.go +++ b/libgo/go/os/sys_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package os diff --git a/libgo/go/os/tempfile.go b/libgo/go/os/tempfile.go index 1ad44f1..5b681fc 100644 --- a/libgo/go/os/tempfile.go +++ b/libgo/go/os/tempfile.go @@ -4,7 +4,10 @@ package os -import "errors" +import ( + "errors" + "internal/itoa" +) // fastrand provided by runtime. // We generate random temporary file names so that there's a good @@ -13,7 +16,7 @@ import "errors" func fastrand() uint32 func nextRandom() string { - return uitoa(uint(fastrand())) + return itoa.Uitoa(uint(fastrand())) } // CreateTemp creates a new temporary file in the directory dir, diff --git a/libgo/go/os/timeout_test.go b/libgo/go/os/timeout_test.go index 0a39f46..6d65e42 100644 --- a/libgo/go/os/timeout_test.go +++ b/libgo/go/os/timeout_test.go @@ -2,9 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !js -// +build !plan9 -// +build !windows +//go:build !js && !plan9 && !windows +// +build !js,!plan9,!windows package os_test diff --git a/libgo/go/os/types_unix.go b/libgo/go/os/types_unix.go index c0259ae..e9b8b8b 100644 --- a/libgo/go/os/types_unix.go +++ b/libgo/go/os/types_unix.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !windows -// +build !plan9 +//go:build !windows && !plan9 +// +build !windows,!plan9 package os diff --git a/libgo/go/os/user/cgo_lookup_unix.go b/libgo/go/os/user/cgo_lookup_unix.go index eb6ab50..3f4014c 100644 --- a/libgo/go/os/user/cgo_lookup_unix.go +++ b/libgo/go/os/user/cgo_lookup_unix.go @@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (aix || darwin || dragonfly || freebsd || hurd || (!android && linux) || netbsd || openbsd || solaris) && cgo && !osusergo // +build aix darwin dragonfly freebsd hurd !android,linux netbsd openbsd solaris -// +build cgo,!osusergo +// +build cgo +// +build !osusergo package user diff --git a/libgo/go/os/user/cgo_unix_test.go b/libgo/go/os/user/cgo_unix_test.go index 1d341aa..9ec32b3 100644 --- a/libgo/go/os/user/cgo_unix_test.go +++ b/libgo/go/os/user/cgo_unix_test.go @@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (darwin || dragonfly || freebsd || (!android && linux) || netbsd || openbsd || solaris) && cgo && !osusergo // +build darwin dragonfly freebsd !android,linux netbsd openbsd solaris -// +build cgo,!osusergo +// +build cgo +// +build !osusergo package user diff --git a/libgo/go/os/user/listgroups_aix.go b/libgo/go/os/user/listgroups_aix.go index 5b9f3f9..93feb80 100644 --- a/libgo/go/os/user/listgroups_aix.go +++ b/libgo/go/os/user/listgroups_aix.go @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cgo && !osusergo +// +build cgo,!osusergo + package user import "fmt" diff --git a/libgo/go/os/user/listgroups_solaris.go b/libgo/go/os/user/listgroups_illumos.go index f3cbf6c..d25e033 100644 --- a/libgo/go/os/user/listgroups_solaris.go +++ b/libgo/go/os/user/listgroups_illumos.go @@ -1,11 +1,12 @@ -// Copyright 2016 The Go Authors. All rights reserved. +// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cgo && !osusergo // +build cgo,!osusergo // Even though this file requires no C, it is used to provide a -// listGroup stub because all the other Solaris calls work. Otherwise, +// listGroup stub because all the other illumos calls work. Otherwise, // this stub will conflict with the lookup_stubs.go fallback. package user @@ -13,5 +14,5 @@ package user import "fmt" func listGroups(u *User) ([]string, error) { - return nil, fmt.Errorf("user: list groups for %s: not supported on Solaris", u.Username) + return nil, fmt.Errorf("user: list groups for %s: not supported on illumos", u.Username) } diff --git a/libgo/go/os/user/listgroups_unix.go b/libgo/go/os/user/listgroups_unix.go index af04c05..38bf807 100644 --- a/libgo/go/os/user/listgroups_unix.go +++ b/libgo/go/os/user/listgroups_unix.go @@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build dragonfly darwin freebsd hurd !android,linux netbsd openbsd -// +build cgo,!osusergo +//go:build (dragonfly || darwin || freebsd || hurd || (!android && linux) || netbsd || openbsd || (solaris && !illumos)) && cgo && !osusergo +// +build dragonfly darwin freebsd hurd !android,linux netbsd openbsd solaris,!illumos +// +build cgo +// +build !osusergo package user diff --git a/libgo/go/os/user/lookup_android.go b/libgo/go/os/user/lookup_android.go index 8ca30b8..151aab4 100644 --- a/libgo/go/os/user/lookup_android.go +++ b/libgo/go/os/user/lookup_android.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build android // +build android package user diff --git a/libgo/go/os/user/lookup_stubs.go b/libgo/go/os/user/lookup_stubs.go index 178d814..c975a11 100644 --- a/libgo/go/os/user/lookup_stubs.go +++ b/libgo/go/os/user/lookup_stubs.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (!cgo && !windows && !plan9) || android || (osusergo && !windows && !plan9) // +build !cgo,!windows,!plan9 android osusergo,!windows,!plan9 package user diff --git a/libgo/go/os/user/lookup_unix.go b/libgo/go/os/user/lookup_unix.go index 0f5e82d..28b9634 100644 --- a/libgo/go/os/user/lookup_unix.go +++ b/libgo/go/os/user/lookup_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || (!android && linux) || netbsd || openbsd || solaris) && (!cgo || osusergo) // +build aix darwin dragonfly freebsd hurd js,wasm !android,linux netbsd openbsd solaris // +build !cgo osusergo @@ -32,23 +33,72 @@ type lineFunc func(line []byte) (v interface{}, err error) // readColonFile parses r as an /etc/group or /etc/passwd style file, running // fn for each row. readColonFile returns a value, an error, or (nil, nil) if // the end of the file is reached without a match. -func readColonFile(r io.Reader, fn lineFunc) (v interface{}, err error) { - bs := bufio.NewScanner(r) - for bs.Scan() { - line := bs.Bytes() +// +// readCols is the minimum number of colon-separated fields that will be passed +// to fn; in a long line additional fields may be silently discarded. +func readColonFile(r io.Reader, fn lineFunc, readCols int) (v interface{}, err error) { + rd := bufio.NewReader(r) + + // Read the file line-by-line. + for { + var isPrefix bool + var wholeLine []byte + + // Read the next line. We do so in chunks (as much as reader's + // buffer is able to keep), check if we read enough columns + // already on each step and store final result in wholeLine. + for { + var line []byte + line, isPrefix, err = rd.ReadLine() + + if err != nil { + // We should return (nil, nil) if EOF is reached + // without a match. + if err == io.EOF { + err = nil + } + return nil, err + } + + // Simple common case: line is short enough to fit in a + // single reader's buffer. + if !isPrefix && len(wholeLine) == 0 { + wholeLine = line + break + } + + wholeLine = append(wholeLine, line...) + + // Check if we read the whole line (or enough columns) + // already. + if !isPrefix || bytes.Count(wholeLine, []byte{':'}) >= readCols { + break + } + } + // There's no spec for /etc/passwd or /etc/group, but we try to follow // the same rules as the glibc parser, which allows comments and blank // space at the beginning of a line. - line = bytes.TrimSpace(line) - if len(line) == 0 || line[0] == '#' { + wholeLine = bytes.TrimSpace(wholeLine) + if len(wholeLine) == 0 || wholeLine[0] == '#' { continue } - v, err = fn(line) + v, err = fn(wholeLine) if v != nil || err != nil { return } + + // If necessary, skip the rest of the line + for ; isPrefix; _, isPrefix, err = rd.ReadLine() { + if err != nil { + // We should return (nil, nil) if EOF is reached without a match. + if err == io.EOF { + err = nil + } + return nil, err + } + } } - return nil, bs.Err() } func matchGroupIndexValue(value string, idx int) lineFunc { @@ -79,7 +129,7 @@ func matchGroupIndexValue(value string, idx int) lineFunc { } func findGroupId(id string, r io.Reader) (*Group, error) { - if v, err := readColonFile(r, matchGroupIndexValue(id, 2)); err != nil { + if v, err := readColonFile(r, matchGroupIndexValue(id, 2), 3); err != nil { return nil, err } else if v != nil { return v.(*Group), nil @@ -88,7 +138,7 @@ func findGroupId(id string, r io.Reader) (*Group, error) { } func findGroupName(name string, r io.Reader) (*Group, error) { - if v, err := readColonFile(r, matchGroupIndexValue(name, 0)); err != nil { + if v, err := readColonFile(r, matchGroupIndexValue(name, 0), 3); err != nil { return nil, err } else if v != nil { return v.(*Group), nil @@ -143,7 +193,7 @@ func findUserId(uid string, r io.Reader) (*User, error) { if e != nil { return nil, errors.New("user: invalid userid " + uid) } - if v, err := readColonFile(r, matchUserIndexValue(uid, 2)); err != nil { + if v, err := readColonFile(r, matchUserIndexValue(uid, 2), 6); err != nil { return nil, err } else if v != nil { return v.(*User), nil @@ -152,7 +202,7 @@ func findUserId(uid string, r io.Reader) (*User, error) { } func findUsername(name string, r io.Reader) (*User, error) { - if v, err := readColonFile(r, matchUserIndexValue(name, 0)); err != nil { + if v, err := readColonFile(r, matchUserIndexValue(name, 0), 6); err != nil { return nil, err } else if v != nil { return v.(*User), nil diff --git a/libgo/go/os/user/lookup_unix_test.go b/libgo/go/os/user/lookup_unix_test.go index 72d3b47..060cfe1 100644 --- a/libgo/go/os/user/lookup_unix_test.go +++ b/libgo/go/os/user/lookup_unix_test.go @@ -2,18 +2,20 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (aix || darwin || dragonfly || freebsd || (!android && linux) || netbsd || openbsd || solaris) && !cgo // +build aix darwin dragonfly freebsd !android,linux netbsd openbsd solaris // +build !cgo package user import ( + "fmt" "reflect" "strings" "testing" ) -const testGroupFile = `# See the opendirectoryd(8) man page for additional +var testGroupFile = `# See the opendirectoryd(8) man page for additional # information about Open Directory. ## nobody:*:-2: @@ -29,7 +31,7 @@ daemon:*:1:root # comment:*:4:found # comment:*:4:found kmem:*:2:root -` +` + largeGroup() var groupTests = []struct { in string @@ -48,9 +50,20 @@ var groupTests = []struct { {testGroupFile, "invalidgid", ""}, {testGroupFile, "indented", "7"}, {testGroupFile, "# comment", ""}, + {testGroupFile, "largegroup", "1000"}, {"", "emptyfile", ""}, } +// Generate a proper "largegroup" entry for testGroupFile string +func largeGroup() (res string) { + var b strings.Builder + b.WriteString("largegroup:x:1000:user1") + for i := 2; i <= 7500; i++ { + fmt.Fprintf(&b, ",user%d", i) + } + return b.String() +} + func TestFindGroupName(t *testing.T) { for _, tt := range groupTests { got, err := findGroupName(tt.name, strings.NewReader(tt.in)) diff --git a/libgo/go/os/user/user_test.go b/libgo/go/os/user/user_test.go index 8c4c817..4992031 100644 --- a/libgo/go/os/user/user_test.go +++ b/libgo/go/os/user/user_test.go @@ -132,7 +132,7 @@ func TestGroupIds(t *testing.T) { if runtime.GOOS == "aix" { t.Skip("skipping GroupIds, see golang.org/issue/30563") } - if runtime.GOOS == "solaris" || runtime.GOOS == "illumos" { + if runtime.GOOS == "illumos" { t.Skip("skipping GroupIds, see golang.org/issue/14709") } user, err := Current() diff --git a/libgo/go/os/wait_unimp.go b/libgo/go/os/wait_unimp.go index cb875ab..783a66f 100644 --- a/libgo/go/os/wait_unimp.go +++ b/libgo/go/os/wait_unimp.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly hurd js,wasm netbsd openbsd solaris +//go:build aix || darwin || hurd || (js && wasm) || openbsd || solaris +// +build aix darwin hurd js,wasm openbsd solaris package os diff --git a/libgo/go/os/wait_wait6.go b/libgo/go/os/wait_wait6.go index 5420b2d..45b370a 100644 --- a/libgo/go/os/wait_wait6.go +++ b/libgo/go/os/wait_wait6.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build freebsd +//go:build dragonfly || freebsd || netbsd +// +build dragonfly freebsd netbsd package os @@ -22,9 +23,9 @@ func (p *Process) blockUntilWaitable() (bool, error) { // The arguments on 32-bit FreeBSD look like the following: // - freebsd32_wait6_args{ idtype, id1, id2, status, options, wrusage, info } or // - freebsd32_wait6_args{ idtype, pad, id1, id2, status, options, wrusage, info } when PAD64_REQUIRED=1 on ARM, MIPS or PowerPC - if runtime.GOARCH == "386" { + if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" { _, _, errno = syscall.Syscall9(syscall.SYS_WAIT6, _P_PID, uintptr(p.Pid), 0, 0, syscall.WEXITED|syscall.WNOWAIT, 0, 0, 0, 0) - } else if runtime.GOARCH == "arm" { + } else if runtime.GOOS == "freebsd" && runtime.GOARCH == "arm" { _, _, errno = syscall.Syscall9(syscall.SYS_WAIT6, _P_PID, 0, uintptr(p.Pid), 0, 0, syscall.WEXITED|syscall.WNOWAIT, 0, 0, 0) } else { _, _, errno = syscall.Syscall6(syscall.SYS_WAIT6, _P_PID, uintptr(p.Pid), 0, syscall.WEXITED|syscall.WNOWAIT, 0, 0) @@ -34,7 +35,9 @@ func (p *Process) blockUntilWaitable() (bool, error) { } } runtime.KeepAlive(p) - if errno != 0 { + if errno == syscall.ENOSYS { + return false, nil + } else if errno != 0 { return false, NewSyscallError("wait6", errno) } return true, nil diff --git a/libgo/go/os/wait_waitid.go b/libgo/go/os/wait_waitid.go index 2c39f9b..d7c9751 100644 --- a/libgo/go/os/wait_waitid.go +++ b/libgo/go/os/wait_waitid.go @@ -5,6 +5,7 @@ // We used to used this code for Darwin, but according to issue #19314 // waitid returns if the process is stopped, even when using WEXITED. +//go:build linux // +build linux package os @@ -22,7 +23,7 @@ const _P_PID = 1 // It does not actually call p.Wait. func (p *Process) blockUntilWaitable() (bool, error) { // The waitid system call expects a pointer to a siginfo_t, - // which is 128 bytes on all GNU/Linux systems. + // which is 128 bytes on all Linux systems. // On darwin/amd64, it requires 104 bytes. // We don't care about the values it returns. var siginfo [16]uint64 diff --git a/libgo/go/path/filepath/example_unix_test.go b/libgo/go/path/filepath/example_unix_test.go index c9d6944..4ce1009 100644 --- a/libgo/go/path/filepath/example_unix_test.go +++ b/libgo/go/path/filepath/example_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows && !plan9 // +build !windows,!plan9 package filepath_test diff --git a/libgo/go/path/filepath/example_unix_walk_test.go b/libgo/go/path/filepath/example_unix_walk_test.go index c8a818f..d72efce 100644 --- a/libgo/go/path/filepath/example_unix_walk_test.go +++ b/libgo/go/path/filepath/example_unix_walk_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows && !plan9 // +build !windows,!plan9 package filepath_test diff --git a/libgo/go/path/filepath/match_test.go b/libgo/go/path/filepath/match_test.go index 0204225..3d90982 100644 --- a/libgo/go/path/filepath/match_test.go +++ b/libgo/go/path/filepath/match_test.go @@ -182,12 +182,7 @@ var globSymlinkTests = []struct { func TestGlobSymlink(t *testing.T) { testenv.MustHaveSymlink(t) - tmpDir, err := os.MkdirTemp("", "globsymlink") - if err != nil { - t.Fatal("creating temp dir:", err) - } - defer os.RemoveAll(tmpDir) - + tmpDir := t.TempDir() for _, tt := range globSymlinkTests { path := Join(tmpDir, tt.path) dest := Join(tmpDir, tt.dest) @@ -268,18 +263,7 @@ func TestWindowsGlob(t *testing.T) { t.Skipf("skipping windows specific test") } - tmpDir, err := os.MkdirTemp("", "TestWindowsGlob") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpDir) - - // /tmp may itself be a symlink - tmpDir, err = EvalSymlinks(tmpDir) - if err != nil { - t.Fatal("eval symlink for tmp dir:", err) - } - + tmpDir := tempDirCanonical(t) if len(tmpDir) < 3 { t.Fatalf("tmpDir path %q is too short", tmpDir) } @@ -324,15 +308,13 @@ func TestWindowsGlob(t *testing.T) { // test absolute paths for _, test := range tests { var p string - err = test.globAbs(tmpDir, tmpDir) - if err != nil { + if err := test.globAbs(tmpDir, tmpDir); err != nil { t.Error(err) } // test C:\*Documents and Settings\... p = tmpDir p = strings.Replace(p, `:\`, `:\*`, 1) - err = test.globAbs(tmpDir, p) - if err != nil { + if err := test.globAbs(tmpDir, p); err != nil { t.Error(err) } // test C:\Documents and Settings*\... @@ -340,8 +322,7 @@ func TestWindowsGlob(t *testing.T) { p = strings.Replace(p, `:\`, `:`, 1) p = strings.Replace(p, `\`, `*\`, 1) p = strings.Replace(p, `:`, `:\`, 1) - err = test.globAbs(tmpDir, p) - if err != nil { + if err := test.globAbs(tmpDir, p); err != nil { t.Error(err) } } diff --git a/libgo/go/path/filepath/path.go b/libgo/go/path/filepath/path.go index 2e7b439..b56534d 100644 --- a/libgo/go/path/filepath/path.go +++ b/libgo/go/path/filepath/path.go @@ -275,7 +275,11 @@ func Rel(basepath, targpath string) (string, error) { targ = targ[len(targVol):] if base == "." { base = "" + } else if base == "" && volumeNameLen(baseVol) > 2 /* isUNC */ { + // Treat any targetpath matching `\\host\share` basepath as absolute path. + base = string(Separator) } + // Can't use IsAbs - `\a` and `a` are both relative in Windows. baseSlashed := len(base) > 0 && base[0] == Separator targSlashed := len(targ) > 0 && targ[0] == Separator @@ -336,7 +340,7 @@ func Rel(basepath, targpath string) (string, error) { // as an error by any function. var SkipDir error = fs.SkipDir -// WalkFunc is the type of the function called by Walk to visit each each +// WalkFunc is the type of the function called by Walk to visit each // file or directory. // // The path argument contains the argument to Walk as a prefix. diff --git a/libgo/go/path/filepath/path_test.go b/libgo/go/path/filepath/path_test.go index 51ea684..1be17df 100644 --- a/libgo/go/path/filepath/path_test.go +++ b/libgo/go/path/filepath/path_test.go @@ -413,6 +413,25 @@ func mark(d fs.DirEntry, err error, errors *[]error, clear bool) error { return nil } +// chdir changes the current working directory to the named directory, +// and then restore the original working directory at the end of the test. +func chdir(t *testing.T, dir string) { + olddir, err := os.Getwd() + if err != nil { + t.Fatalf("getwd %s: %v", dir, err) + } + if err := os.Chdir(dir); err != nil { + t.Fatalf("chdir %s: %v", dir, err) + } + + t.Cleanup(func() { + if err := os.Chdir(olddir); err != nil { + t.Errorf("restore original working directory %s: %v", olddir, err) + os.Exit(1) + } + }) +} + func chtmpdir(t *testing.T) (restore func()) { oldwd, err := os.Getwd() if err != nil { @@ -433,6 +452,19 @@ func chtmpdir(t *testing.T) (restore func()) { } } +// tempDirCanonical returns a temporary directory for the test to use, ensuring +// that the returned path does not contain symlinks. +func tempDirCanonical(t *testing.T) string { + dir := t.TempDir() + + cdir, err := filepath.EvalSymlinks(dir) + if err != nil { + t.Errorf("tempDirCanonical: %v", err) + } + + return cdir +} + func TestWalk(t *testing.T) { walk := func(root string, fn fs.WalkDirFunc) error { return filepath.Walk(root, func(path string, info fs.FileInfo, err error) error { @@ -461,11 +493,7 @@ func testWalk(t *testing.T, walk func(string, fs.WalkDirFunc) error, errVisit in defer restore() } - tmpDir, err := os.MkdirTemp("", "TestWalk") - if err != nil { - t.Fatal("creating temp dir:", err) - } - defer os.RemoveAll(tmpDir) + tmpDir := t.TempDir() origDir, err := os.Getwd() if err != nil { @@ -565,11 +593,7 @@ func touch(t *testing.T, name string) { } func TestWalkSkipDirOnFile(t *testing.T) { - td, err := os.MkdirTemp("", "walktest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(td) + td := t.TempDir() if err := os.MkdirAll(filepath.Join(td, "dir"), 0755); err != nil { t.Fatal(err) @@ -593,7 +617,7 @@ func TestWalkSkipDirOnFile(t *testing.T) { check := func(t *testing.T, walk func(root string) error, root string) { t.Helper() sawFoo2 = false - err = walk(root) + err := walk(root) if err != nil { t.Fatal(err) } @@ -615,11 +639,7 @@ func TestWalkSkipDirOnFile(t *testing.T) { } func TestWalkFileError(t *testing.T) { - td, err := os.MkdirTemp("", "walktest") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(td) + td := t.TempDir() touch(t, filepath.Join(td, "foo")) touch(t, filepath.Join(td, "bar")) @@ -640,7 +660,7 @@ func TestWalkFileError(t *testing.T) { return os.Lstat(path) } got := map[string]error{} - err = filepath.Walk(td, func(path string, fi fs.FileInfo, err error) error { + err := filepath.Walk(td, func(path string, fi fs.FileInfo, err error) error { rel, _ := filepath.Rel(td, path) got[filepath.ToSlash(rel)] = err return nil @@ -894,14 +914,11 @@ func testEvalSymlinksAfterChdir(t *testing.T, wd, path, want string) { func TestEvalSymlinks(t *testing.T) { testenv.MustHaveSymlink(t) - tmpDir, err := os.MkdirTemp("", "evalsymlink") - if err != nil { - t.Fatal("creating temp dir:", err) - } - defer os.RemoveAll(tmpDir) + tmpDir := t.TempDir() // /tmp may itself be a symlink! Avoid the confusion, although // it means trusting the thing we're testing. + var err error tmpDir, err = filepath.EvalSymlinks(tmpDir) if err != nil { t.Fatal("eval symlink for tmp dir:", err) @@ -980,14 +997,10 @@ func TestEvalSymlinksIsNotExist(t *testing.T) { func TestIssue13582(t *testing.T) { testenv.MustHaveSymlink(t) - tmpDir, err := os.MkdirTemp("", "issue13582") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpDir) + tmpDir := t.TempDir() dir := filepath.Join(tmpDir, "dir") - err = os.Mkdir(dir, 0755) + err := os.Mkdir(dir, 0755) if err != nil { t.Fatal(err) } @@ -1067,12 +1080,7 @@ var absTests = []string{ } func TestAbs(t *testing.T) { - root, err := os.MkdirTemp("", "TestAbs") - if err != nil { - t.Fatal("TempDir failed: ", err) - } - defer os.RemoveAll(root) - + root := t.TempDir() wd, err := os.Getwd() if err != nil { t.Fatal("getwd failed: ", err) @@ -1138,11 +1146,7 @@ func TestAbs(t *testing.T) { // We test it separately from all other absTests because the empty string is not // a valid path, so it can't be used with os.Stat. func TestAbsEmptyString(t *testing.T) { - root, err := os.MkdirTemp("", "TestAbsEmptyString") - if err != nil { - t.Fatal("TempDir failed: ", err) - } - defer os.RemoveAll(root) + root := t.TempDir() wd, err := os.Getwd() if err != nil { @@ -1230,6 +1234,7 @@ var winreltests = []RelTests{ {`C:\Projects`, `c:\projects\src`, `src`}, {`C:\Projects`, `c:\projects`, `.`}, {`C:\Projects\a\..`, `c:\projects`, `.`}, + {`\\host\share`, `\\host\share\file.txt`, `file.txt`}, } func TestRel(t *testing.T) { @@ -1360,11 +1365,7 @@ func TestBug3486(t *testing.T) { // https://golang.org/issue/3486 } func testWalkSymlink(t *testing.T, mklink func(target, link string) error) { - tmpdir, err := os.MkdirTemp("", "testWalkSymlink") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) + tmpdir := t.TempDir() wd, err := os.Getwd() if err != nil { @@ -1410,14 +1411,10 @@ func TestWalkSymlink(t *testing.T) { } func TestIssue29372(t *testing.T) { - tmpDir, err := os.MkdirTemp("", "TestIssue29372") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpDir) + tmpDir := t.TempDir() path := filepath.Join(tmpDir, "file.txt") - err = os.WriteFile(path, nil, 0644) + err := os.WriteFile(path, nil, 0644) if err != nil { t.Fatal(err) } @@ -1446,11 +1443,7 @@ func TestEvalSymlinksAboveRoot(t *testing.T) { t.Parallel() - tmpDir, err := os.MkdirTemp("", "TestEvalSymlinksAboveRoot") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpDir) + tmpDir := t.TempDir() evalTmpDir, err := filepath.EvalSymlinks(tmpDir) if err != nil { @@ -1480,11 +1473,16 @@ func TestEvalSymlinksAboveRoot(t *testing.T) { // Try different numbers of "..". for _, i := range []int{c, c + 1, c + 2} { check := strings.Join([]string{evalTmpDir, strings.Join(dd[:i], string(os.PathSeparator)), evalTmpDir[len(vol)+1:], "b", "file"}, string(os.PathSeparator)) - if resolved, err := filepath.EvalSymlinks(check); err != nil { + resolved, err := filepath.EvalSymlinks(check) + switch { + case runtime.GOOS == "darwin" && errors.Is(err, fs.ErrNotExist): + // On darwin, the temp dir is sometimes cleaned up mid-test (issue 37910). + testenv.SkipFlaky(t, 37910) + case err != nil: t.Errorf("EvalSymlinks(%q) failed: %v", check, err) - } else if !strings.HasSuffix(resolved, wantSuffix) { + case !strings.HasSuffix(resolved, wantSuffix): t.Errorf("EvalSymlinks(%q) = %q does not end with %q", check, resolved, wantSuffix) - } else { + default: t.Logf("EvalSymlinks(%q) = %q", check, resolved) } } @@ -1499,16 +1497,7 @@ func TestEvalSymlinksAboveRootChdir(t *testing.T) { t.Fatal(err) } defer os.RemoveAll(tmpDir) - - wd, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - defer os.Chdir(wd) - - if err := os.Chdir(tmpDir); err != nil { - t.Fatal(err) - } + chdir(t, tmpDir) subdir := filepath.Join("a", "b") if err := os.MkdirAll(subdir, 0777); err != nil { diff --git a/libgo/go/path/filepath/path_unix.go b/libgo/go/path/filepath/path_unix.go index 57341ed..b0a6391 100644 --- a/libgo/go/path/filepath/path_unix.go +++ b/libgo/go/path/filepath/path_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package filepath diff --git a/libgo/go/path/filepath/symlink_unix.go b/libgo/go/path/filepath/symlink_unix.go index d20e63a..657945a 100644 --- a/libgo/go/path/filepath/symlink_unix.go +++ b/libgo/go/path/filepath/symlink_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package filepath diff --git a/libgo/go/plugin/plugin_dlopen.go b/libgo/go/plugin/plugin_dlopen.go index 8342267..23adc4f 100644 --- a/libgo/go/plugin/plugin_dlopen.go +++ b/libgo/go/plugin/plugin_dlopen.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (linux && cgo) || (darwin && cgo) || (freebsd && cgo) || (hurd && cgo) // +build linux,cgo darwin,cgo freebsd,cgo hurd,cgo package plugin diff --git a/libgo/go/plugin/plugin_stubs.go b/libgo/go/plugin/plugin_stubs.go index 0f9adb7..215becc 100644 --- a/libgo/go/plugin/plugin_stubs.go +++ b/libgo/go/plugin/plugin_stubs.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (!hurd && !linux && !freebsd && !darwin) || !cgo // +build !hurd,!linux,!freebsd,!darwin !cgo package plugin diff --git a/libgo/go/plugin/plugin_test.go b/libgo/go/plugin/plugin_test.go index 30b79ed..4ce9121 100644 --- a/libgo/go/plugin/plugin_test.go +++ b/libgo/go/plugin/plugin_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !linux || (linux && !arm64) // +build !linux linux,!arm64 package plugin_test diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go index c73ef47..7fa815f 100644 --- a/libgo/go/reflect/all_test.go +++ b/libgo/go/reflect/all_test.go @@ -15,6 +15,8 @@ import ( "math/rand" "os" . "reflect" + "reflect/internal/example1" + "reflect/internal/example2" "runtime" "sort" "strconv" @@ -1945,6 +1947,22 @@ func BenchmarkCall(b *testing.B) { }) } +type myint int64 + +func (i *myint) inc() { + *i = *i + 1 +} + +func BenchmarkCallMethod(b *testing.B) { + b.ReportAllocs() + z := new(myint) + + v := ValueOf(z.inc) + for i := 0; i < b.N; i++ { + v.Call(nil) + } +} + func BenchmarkCallArgCopy(b *testing.B) { byteArray := func(n int) Value { return Zero(ArrayOf(n, TypeOf(byte(0)))) @@ -2903,6 +2921,7 @@ func TestFieldPkgPath(t *testing.T) { index []int pkgPath string embedded bool + exported bool } checkPkgPath := func(name string, s []pkgpathTest) { @@ -2914,27 +2933,63 @@ func TestFieldPkgPath(t *testing.T) { if got, want := f.Anonymous, test.embedded; got != want { t.Errorf("%s: Field(%d).Anonymous = %v, want %v", name, test.index, got, want) } + if got, want := f.IsExported(), test.exported; got != want { + t.Errorf("%s: Field(%d).IsExported = %v, want %v", name, test.index, got, want) + } } } checkPkgPath("testStruct", []pkgpathTest{ - {[]int{0}, "", false}, // Exported - {[]int{1}, "reflect_test", false}, // unexported - {[]int{2}, "", true}, // OtherPkgFields - {[]int{2, 0}, "", false}, // OtherExported - {[]int{2, 1}, "reflect", false}, // otherUnexported - {[]int{3}, "reflect_test", true}, // int - {[]int{4}, "reflect_test", true}, // *x + {[]int{0}, "", false, true}, // Exported + {[]int{1}, "reflect_test", false, false}, // unexported + {[]int{2}, "", true, true}, // OtherPkgFields + {[]int{2, 0}, "", false, true}, // OtherExported + {[]int{2, 1}, "reflect", false, false}, // otherUnexported + {[]int{3}, "reflect_test", true, false}, // int + {[]int{4}, "reflect_test", true, false}, // *x }) type localOtherPkgFields OtherPkgFields typ = TypeOf(localOtherPkgFields{}) checkPkgPath("localOtherPkgFields", []pkgpathTest{ - {[]int{0}, "", false}, // OtherExported - {[]int{1}, "reflect", false}, // otherUnexported + {[]int{0}, "", false, true}, // OtherExported + {[]int{1}, "reflect", false, false}, // otherUnexported }) } +func TestMethodPkgPath(t *testing.T) { + type I interface { + x() + X() + } + typ := TypeOf((*interface { + I + y() + Y() + })(nil)).Elem() + + tests := []struct { + name string + pkgPath string + exported bool + }{ + {"X", "", true}, + {"Y", "", true}, + {"x", "reflect_test", false}, + {"y", "reflect_test", false}, + } + + for _, test := range tests { + m, _ := typ.MethodByName(test.name) + if got, want := m.PkgPath, test.pkgPath; got != want { + t.Errorf("MethodByName(%q).PkgPath = %q, want %q", test.name, got, want) + } + if got, want := m.IsExported(), test.exported; got != want { + t.Errorf("MethodByName(%q).IsExported = %v, want %v", test.name, got, want) + } + } +} + func TestVariadicType(t *testing.T) { // Test example from Type documentation. var f func(x int, y ...float64) @@ -3765,8 +3820,22 @@ type Empty struct{} type MyStruct struct { x int `some:"tag"` } +type MyStruct1 struct { + x struct { + int `some:"bar"` + } +} +type MyStruct2 struct { + x struct { + int `some:"foo"` + } +} type MyString string type MyBytes []byte +type MyBytesArrayPtr0 *[0]byte +type MyBytesArrayPtr *[4]byte +type MyBytesArray0 [0]byte +type MyBytesArray [4]byte type MyRunes []int32 type MyFunc func() type MyByte byte @@ -4073,6 +4142,30 @@ var convertTests = []struct { {V(MyString("runes♝")), V(MyRunes("runes♝"))}, {V(MyRunes("runes♕")), V(MyString("runes♕"))}, + // slice to array pointer + {V([]byte(nil)), V((*[0]byte)(nil))}, + {V([]byte{}), V(new([0]byte))}, + {V([]byte{7}), V(&[1]byte{7})}, + {V(MyBytes([]byte(nil))), V((*[0]byte)(nil))}, + {V(MyBytes([]byte{})), V(new([0]byte))}, + {V(MyBytes([]byte{9})), V(&[1]byte{9})}, + {V([]byte(nil)), V(MyBytesArrayPtr0(nil))}, + {V([]byte{}), V(MyBytesArrayPtr0(new([0]byte)))}, + {V([]byte{1, 2, 3, 4}), V(MyBytesArrayPtr(&[4]byte{1, 2, 3, 4}))}, + {V(MyBytes([]byte{})), V(MyBytesArrayPtr0(new([0]byte)))}, + {V(MyBytes([]byte{5, 6, 7, 8})), V(MyBytesArrayPtr(&[4]byte{5, 6, 7, 8}))}, + + {V([]byte(nil)), V((*MyBytesArray0)(nil))}, + {V([]byte{}), V((*MyBytesArray0)(new([0]byte)))}, + {V([]byte{1, 2, 3, 4}), V(&MyBytesArray{1, 2, 3, 4})}, + {V(MyBytes([]byte(nil))), V((*MyBytesArray0)(nil))}, + {V(MyBytes([]byte{})), V((*MyBytesArray0)(new([0]byte)))}, + {V(MyBytes([]byte{5, 6, 7, 8})), V(&MyBytesArray{5, 6, 7, 8})}, + {V(new([0]byte)), V(new(MyBytesArray0))}, + {V(new(MyBytesArray0)), V(new([0]byte))}, + {V(MyBytesArrayPtr0(nil)), V((*[0]byte)(nil))}, + {V((*[0]byte)(nil)), V(MyBytesArrayPtr0(nil))}, + // named types and equal underlying types {V(new(int)), V(new(integer))}, {V(new(integer)), V(new(int))}, @@ -4115,6 +4208,9 @@ var convertTests = []struct { x int `some:"bar"` }{}), V(MyStruct{})}, + {V(MyStruct1{}), V(MyStruct2{})}, + {V(MyStruct2{}), V(MyStruct1{})}, + // can convert *byte and *MyByte {V((*byte)(nil)), V((*MyByte)(nil))}, {V((*MyByte)(nil)), V((*byte)(nil))}, @@ -4218,6 +4314,9 @@ func TestConvert(t *testing.T) { // vout1 represents the in value converted to the in type. v1 := tt.in + if !v1.CanConvert(t1) { + t.Errorf("ValueOf(%T(%[1]v)).CanConvert(%s) = false, want true", tt.in.Interface(), t1) + } vout1 := v1.Convert(t1) out1 := vout1.Interface() if vout1.Type() != tt.in.Type() || !DeepEqual(out1, tt.in.Interface()) { @@ -4225,11 +4324,17 @@ func TestConvert(t *testing.T) { } // vout2 represents the in value converted to the out type. + if !v1.CanConvert(t2) { + t.Errorf("ValueOf(%T(%[1]v)).CanConvert(%s) = false, want true", tt.in.Interface(), t2) + } vout2 := v1.Convert(t2) out2 := vout2.Interface() if vout2.Type() != tt.out.Type() || !DeepEqual(out2, tt.out.Interface()) { t.Errorf("ValueOf(%T(%[1]v)).Convert(%s) = %T(%[3]v), want %T(%[4]v)", tt.in.Interface(), t2, out2, tt.out.Interface()) } + if got, want := vout2.Kind(), vout2.Type().Kind(); got != want { + t.Errorf("ValueOf(%T(%[1]v)).Convert(%s) has internal kind %v want %v", tt.in.Interface(), t1, got, want) + } // vout3 represents a new value of the out type, set to vout2. This makes // sure the converted value vout2 is really usable as a regular value. @@ -4274,6 +4379,22 @@ func TestConvert(t *testing.T) { } } +func TestConvertPanic(t *testing.T) { + s := make([]byte, 4) + p := new([8]byte) + v := ValueOf(s) + pt := TypeOf(p) + if !v.Type().ConvertibleTo(pt) { + t.Errorf("[]byte should be convertible to *[8]byte") + } + if v.CanConvert(pt) { + t.Errorf("slice with length 4 should not be convertible to *[8]byte") + } + shouldPanic("reflect: cannot convert slice with length 4 to pointer to array with length 8", func() { + _ = v.Convert(pt) + }) +} + var gFloat32 float32 func TestConvertNaNs(t *testing.T) { @@ -4612,6 +4733,14 @@ func TestArrayOfDirectIface(t *testing.T) { } } +// Ensure passing in negative lengths panics. +// See https://golang.org/issue/43603 +func TestArrayOfPanicOnNegativeLength(t *testing.T) { + shouldPanic("reflect: negative length passed to ArrayOf", func() { + ArrayOf(-1, TypeOf(byte(0))) + }) +} + func TestSliceOf(t *testing.T) { // check construction and use of type not in binary type T int @@ -6357,148 +6486,142 @@ func clobber() { runtime.GC() } -type funcLayoutTest struct { - rcvr, t Type - size, argsize, retOffset uintptr - stack []byte // pointer bitmap: 1 is pointer, 0 is scalar - gc []byte -} - -var funcLayoutTests []funcLayoutTest - -func init() { - var argAlign uintptr = PtrSize - roundup := func(x uintptr, a uintptr) uintptr { - return (x + a - 1) / a * a - } - - funcLayoutTests = append(funcLayoutTests, - funcLayoutTest{ - nil, - ValueOf(func(a, b string) string { return "" }).Type(), - 6 * PtrSize, - 4 * PtrSize, - 4 * PtrSize, - []byte{1, 0, 1, 0, 1}, - []byte{1, 0, 1, 0, 1}, - }) +/* +func TestFuncLayout(t *testing.T) { + align := func(x uintptr) uintptr { + return (x + PtrSize - 1) &^ (PtrSize - 1) + } var r []byte if PtrSize == 4 { r = []byte{0, 0, 0, 1} } else { r = []byte{0, 0, 1} } - funcLayoutTests = append(funcLayoutTests, - funcLayoutTest{ - nil, - ValueOf(func(a, b, c uint32, p *byte, d uint16) {}).Type(), - roundup(roundup(3*4, PtrSize)+PtrSize+2, argAlign), - roundup(3*4, PtrSize) + PtrSize + 2, - roundup(roundup(3*4, PtrSize)+PtrSize+2, argAlign), - r, - r, - }) - - funcLayoutTests = append(funcLayoutTests, - funcLayoutTest{ - nil, - ValueOf(func(a map[int]int, b uintptr, c interface{}) {}).Type(), - 4 * PtrSize, - 4 * PtrSize, - 4 * PtrSize, - []byte{1, 0, 1, 1}, - []byte{1, 0, 1, 1}, - }) type S struct { a, b uintptr c, d *byte } - funcLayoutTests = append(funcLayoutTests, - funcLayoutTest{ - nil, - ValueOf(func(a S) {}).Type(), - 4 * PtrSize, - 4 * PtrSize, - 4 * PtrSize, - []byte{0, 0, 1, 1}, - []byte{0, 0, 1, 1}, - }) - - funcLayoutTests = append(funcLayoutTests, - funcLayoutTest{ - ValueOf((*byte)(nil)).Type(), - ValueOf(func(a uintptr, b *int) {}).Type(), - roundup(3*PtrSize, argAlign), - 3 * PtrSize, - roundup(3*PtrSize, argAlign), - []byte{1, 0, 1}, - []byte{1, 0, 1}, - }) - funcLayoutTests = append(funcLayoutTests, - funcLayoutTest{ - nil, - ValueOf(func(a uintptr) {}).Type(), - roundup(PtrSize, argAlign), - PtrSize, - roundup(PtrSize, argAlign), - []byte{}, - []byte{}, - }) - - funcLayoutTests = append(funcLayoutTests, - funcLayoutTest{ - nil, - ValueOf(func() uintptr { return 0 }).Type(), - PtrSize, - 0, - 0, - []byte{}, - []byte{}, - }) - - funcLayoutTests = append(funcLayoutTests, - funcLayoutTest{ - ValueOf(uintptr(0)).Type(), - ValueOf(func(a uintptr) {}).Type(), - 2 * PtrSize, - 2 * PtrSize, - 2 * PtrSize, - []byte{1}, - []byte{1}, + type test struct { + rcvr, typ Type + size, argsize, retOffset uintptr + stack, gc, inRegs, outRegs []byte // pointer bitmap: 1 is pointer, 0 is scalar + intRegs, floatRegs int + floatRegSize uintptr + } + tests := []test{ + { + typ: ValueOf(func(a, b string) string { return "" }).Type(), + size: 6 * PtrSize, + argsize: 4 * PtrSize, + retOffset: 4 * PtrSize, + stack: []byte{1, 0, 1, 0, 1}, + gc: []byte{1, 0, 1, 0, 1}, + }, + { + typ: ValueOf(func(a, b, c uint32, p *byte, d uint16) {}).Type(), + size: align(align(3*4) + PtrSize + 2), + argsize: align(3*4) + PtrSize + 2, + retOffset: align(align(3*4) + PtrSize + 2), + stack: r, + gc: r, + }, + { + typ: ValueOf(func(a map[int]int, b uintptr, c interface{}) {}).Type(), + size: 4 * PtrSize, + argsize: 4 * PtrSize, + retOffset: 4 * PtrSize, + stack: []byte{1, 0, 1, 1}, + gc: []byte{1, 0, 1, 1}, + }, + { + typ: ValueOf(func(a S) {}).Type(), + size: 4 * PtrSize, + argsize: 4 * PtrSize, + retOffset: 4 * PtrSize, + stack: []byte{0, 0, 1, 1}, + gc: []byte{0, 0, 1, 1}, + }, + { + rcvr: ValueOf((*byte)(nil)).Type(), + typ: ValueOf(func(a uintptr, b *int) {}).Type(), + size: 3 * PtrSize, + argsize: 3 * PtrSize, + retOffset: 3 * PtrSize, + stack: []byte{1, 0, 1}, + gc: []byte{1, 0, 1}, + }, + { + typ: ValueOf(func(a uintptr) {}).Type(), + size: PtrSize, + argsize: PtrSize, + retOffset: PtrSize, + stack: []byte{}, + gc: []byte{}, + }, + { + typ: ValueOf(func() uintptr { return 0 }).Type(), + size: PtrSize, + argsize: 0, + retOffset: 0, + stack: []byte{}, + gc: []byte{}, + }, + { + rcvr: ValueOf(uintptr(0)).Type(), + typ: ValueOf(func(a uintptr) {}).Type(), + size: 2 * PtrSize, + argsize: 2 * PtrSize, + retOffset: 2 * PtrSize, + stack: []byte{1}, + gc: []byte{1}, // Note: this one is tricky, as the receiver is not a pointer. But we // pass the receiver by reference to the autogenerated pointer-receiver // version of the function. - }) -} - -func TestFuncLayout(t *testing.T) { - t.Skip("gccgo does not use funcLayout") - for _, lt := range funcLayoutTests { - typ, argsize, retOffset, stack, gc, ptrs := FuncLayout(lt.t, lt.rcvr) - if typ.Size() != lt.size { - t.Errorf("funcLayout(%v, %v).size=%d, want %d", lt.t, lt.rcvr, typ.Size(), lt.size) - } - if argsize != lt.argsize { - t.Errorf("funcLayout(%v, %v).argsize=%d, want %d", lt.t, lt.rcvr, argsize, lt.argsize) - } - if retOffset != lt.retOffset { - t.Errorf("funcLayout(%v, %v).retOffset=%d, want %d", lt.t, lt.rcvr, retOffset, lt.retOffset) - } - if !bytes.Equal(stack, lt.stack) { - t.Errorf("funcLayout(%v, %v).stack=%v, want %v", lt.t, lt.rcvr, stack, lt.stack) - } - if !bytes.Equal(gc, lt.gc) { - t.Errorf("funcLayout(%v, %v).gc=%v, want %v", lt.t, lt.rcvr, gc, lt.gc) - } - if ptrs && len(stack) == 0 || !ptrs && len(stack) > 0 { - t.Errorf("funcLayout(%v, %v) pointers flag=%v, want %v", lt.t, lt.rcvr, ptrs, !ptrs) + }, + // TODO(mknyszek): Add tests for non-zero register count. + } + for _, lt := range tests { + name := lt.typ.String() + if lt.rcvr != nil { + name = lt.rcvr.String() + "." + name } + t.Run(name, func(t *testing.T) { + defer SetArgRegs(SetArgRegs(lt.intRegs, lt.floatRegs, lt.floatRegSize)) + + typ, argsize, retOffset, stack, gc, inRegs, outRegs, ptrs := FuncLayout(lt.typ, lt.rcvr) + if typ.Size() != lt.size { + t.Errorf("funcLayout(%v, %v).size=%d, want %d", lt.typ, lt.rcvr, typ.Size(), lt.size) + } + if argsize != lt.argsize { + t.Errorf("funcLayout(%v, %v).argsize=%d, want %d", lt.typ, lt.rcvr, argsize, lt.argsize) + } + if retOffset != lt.retOffset { + t.Errorf("funcLayout(%v, %v).retOffset=%d, want %d", lt.typ, lt.rcvr, retOffset, lt.retOffset) + } + if !bytes.Equal(stack, lt.stack) { + t.Errorf("funcLayout(%v, %v).stack=%v, want %v", lt.typ, lt.rcvr, stack, lt.stack) + } + if !bytes.Equal(gc, lt.gc) { + t.Errorf("funcLayout(%v, %v).gc=%v, want %v", lt.typ, lt.rcvr, gc, lt.gc) + } + if !bytes.Equal(inRegs, lt.inRegs) { + t.Errorf("funcLayout(%v, %v).inRegs=%v, want %v", lt.typ, lt.rcvr, inRegs, lt.inRegs) + } + if !bytes.Equal(outRegs, lt.outRegs) { + t.Errorf("funcLayout(%v, %v).outRegs=%v, want %v", lt.typ, lt.rcvr, outRegs, lt.outRegs) + } + if ptrs && len(stack) == 0 || !ptrs && len(stack) > 0 { + t.Errorf("funcLayout(%v, %v) pointers flag=%v, want %v", lt.typ, lt.rcvr, ptrs, !ptrs) + } + }) } } +*/ + func verifyGCBits(t *testing.T, typ Type, bits []byte) { heapBits := GCBits(New(typ).Interface()) if !bytes.Equal(heapBits, bits) { @@ -6861,21 +6984,6 @@ func TestExported(t *testing.T) { } */ -type embed struct { - EmbedWithUnexpMeth -} - -/* -func TestNameBytesAreAligned(t *testing.T) { - typ := TypeOf(embed{}) - b := FirstMethodNameBytes(typ) - v := uintptr(unsafe.Pointer(b)) - if v%unsafe.Alignof((*byte)(nil)) != 0 { - t.Errorf("reflect.name.bytes pointer is not aligned: %x", v) - } -} -*/ - func TestTypeStrings(t *testing.T) { type stringTest struct { typ Type @@ -7215,3 +7323,13 @@ func iterateToString(it *MapIter) string { sort.Strings(got) return "[" + strings.Join(got, ", ") + "]" } + +func TestConvertibleTo(t *testing.T) { + t1 := ValueOf(example1.MyStruct{}).Type() + t2 := ValueOf(example2.MyStruct{}).Type() + + // Shouldn't raise stack overflow + if t1.ConvertibleTo(t2) { + t.Fatalf("(%s).ConvertibleTo(%s) = true, want false", t1, t2) + } +} diff --git a/libgo/go/reflect/internal/example1/example.go b/libgo/go/reflect/internal/example1/example.go new file mode 100644 index 0000000..0f829a8 --- /dev/null +++ b/libgo/go/reflect/internal/example1/example.go @@ -0,0 +1,6 @@ +package example1 + +type MyStruct struct { + MyStructs []MyStruct + MyStruct *MyStruct +} diff --git a/libgo/go/reflect/internal/example2/example.go b/libgo/go/reflect/internal/example2/example.go new file mode 100644 index 0000000..df64ba1 --- /dev/null +++ b/libgo/go/reflect/internal/example2/example.go @@ -0,0 +1,6 @@ +package example2 + +type MyStruct struct { + MyStructs []MyStruct + MyStruct *MyStruct +} diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go index c05ec68..0c394a2 100644 --- a/libgo/go/reflect/type.go +++ b/libgo/go/reflect/type.go @@ -108,9 +108,15 @@ type Type interface { AssignableTo(u Type) bool // ConvertibleTo reports whether a value of the type is convertible to type u. + // Even if ConvertibleTo returns true, the conversion may still panic. + // For example, a slice of type []T is convertible to *[N]T, + // but the conversion will panic if its length is less than N. ConvertibleTo(u Type) bool // Comparable reports whether values of this type are comparable. + // Even if Comparable returns true, the comparison may still panic. + // For example, values of interface type are comparable, + // but the comparison will panic if their dynamic type is not comparable. Comparable() bool // Methods applicable only to some types, depending on Kind. @@ -224,7 +230,7 @@ type Type interface { // See https://golang.org/issue/4876 for more details. /* - * These data structures are known to the compiler (../../cmd/internal/gc/reflect.go). + * These data structures are known to the compiler (../../cmd/internal/reflectdata/reflect.go). * A few are known to ../runtime/type.go to convey to debuggers. * They are also known to ../runtime/type.go. */ @@ -419,12 +425,13 @@ type structType struct { // Method represents a single method. type Method struct { // Name is the method name. + Name string + // PkgPath is the package path that qualifies a lower case (unexported) // method name. It is empty for upper case (exported) method names. // The combination of PkgPath and Name uniquely identifies a method // in a method set. // See https://golang.org/ref/spec#Uniqueness_of_identifiers - Name string PkgPath string Type Type // method type @@ -432,6 +439,11 @@ type Method struct { Index int // index for Type.Method } +// IsExported reports whether the method is exported. +func (m Method) IsExported() bool { + return m.PkgPath == "" +} + const ( kindDirectIface = 1 << 5 kindGCProg = 1 << 6 // Type.gc points to GC program @@ -828,6 +840,7 @@ func (t *interfaceType) MethodByName(name string) (m Method, ok bool) { type StructField struct { // Name is the field name. Name string + // PkgPath is the package path that qualifies a lower case (unexported) // field name. It is empty for upper case (exported) field names. // See https://golang.org/ref/spec#Uniqueness_of_identifiers @@ -840,6 +853,11 @@ type StructField struct { Anonymous bool // is an embedded field } +// IsExported reports whether the field is exported. +func (f StructField) IsExported() bool { + return f.PkgPath == "" +} + // A StructTag is the tag string in a struct field. // // By convention, tag strings are a concatenation of @@ -1300,7 +1318,7 @@ func haveIdenticalType(T, V Type, cmpTags bool) bool { return T == V } - if T.Name() != V.Name() || T.Kind() != V.Kind() { + if T.Name() != V.Name() || T.Kind() != V.Kind() || T.PkgPath() != V.PkgPath() { return false } @@ -1529,7 +1547,7 @@ func MapOf(key, elem Type) Type { // Make a map type. // Note: flag values must match those used in the TMAP case - // in ../cmd/compile/internal/gc/reflect.go:dtypesym. + // in ../cmd/compile/internal/reflectdata/reflect.go:writeType. var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil) mt := **(**mapType)(unsafe.Pointer(&imap)) mt.string = &s @@ -2257,8 +2275,7 @@ func runtimeStructField(field StructField) (structField, string) { panic("reflect.StructOf: field \"" + field.Name + "\" is anonymous but has PkgPath set") } - exported := field.PkgPath == "" - if exported { + if field.IsExported() { // Best-effort check for misuse. // Since this field will be treated as exported, not much harm done if Unicode lowercase slips through. c := field.Name[0] @@ -2298,7 +2315,7 @@ func runtimeStructField(field StructField) (structField, string) { // typeptrdata returns the length in bytes of the prefix of t // containing pointer data. Anything after this offset is scalar data. -// keep in sync with ../cmd/compile/internal/gc/reflect.go +// keep in sync with ../cmd/compile/internal/reflectdata/reflect.go func typeptrdata(t *rtype) uintptr { switch t.Kind() { case Struct: @@ -2322,25 +2339,29 @@ func typeptrdata(t *rtype) uintptr { } } -// See cmd/compile/internal/gc/reflect.go for derivation of constant. +// See cmd/compile/internal/reflectdata/reflect.go for derivation of constant. const maxPtrmaskBytes = 2048 -// ArrayOf returns the array type with the given count and element type. +// ArrayOf returns the array type with the given length and element type. // For example, if t represents int, ArrayOf(5, t) represents [5]int. // // If the resulting type would be larger than the available address space, // ArrayOf panics. -func ArrayOf(count int, elem Type) Type { +func ArrayOf(length int, elem Type) Type { + if length < 0 { + panic("reflect: negative length passed to ArrayOf") + } + typ := elem.(*rtype) // Look in cache. - ckey := cacheKey{Array, typ, nil, uintptr(count)} + ckey := cacheKey{Array, typ, nil, uintptr(length)} if array, ok := lookupCache.Load(ckey); ok { return array.(Type) } // Look in known types. - s := "[" + strconv.Itoa(count) + "]" + *typ.string + s := "[" + strconv.Itoa(length) + "]" + *typ.string if tt := lookupType(s); tt != nil { array := (*arrayType)(unsafe.Pointer(toType(tt).(*rtype))) if array.elem == typ { @@ -2358,28 +2379,27 @@ func ArrayOf(count int, elem Type) Type { // gccgo uses a different hash. // array.hash = fnv1(typ.hash, '[') - // for n := uint32(count); n > 0; n >>= 8 { + // for n := uint32(length); n > 0; n >>= 8 { // array.hash = fnv1(array.hash, byte(n)) // } // array.hash = fnv1(array.hash, ']') array.hash = typ.hash + 1 + 13 - array.elem = typ array.ptrToThis = nil if typ.size > 0 { max := ^uintptr(0) / typ.size - if uintptr(count) > max { + if uintptr(length) > max { panic("reflect.ArrayOf: array size would exceed virtual address space") } } - array.size = typ.size * uintptr(count) - if count > 0 && typ.ptrdata != 0 { - array.ptrdata = typ.size*uintptr(count-1) + typ.ptrdata + array.size = typ.size * uintptr(length) + if length > 0 && typ.ptrdata != 0 { + array.ptrdata = typ.size*uintptr(length-1) + typ.ptrdata } array.align = typ.align array.fieldAlign = typ.fieldAlign array.uncommonType = nil - array.len = uintptr(count) + array.len = uintptr(length) array.slice = SliceOf(elem).(*rtype) switch { @@ -2388,7 +2408,7 @@ func ArrayOf(count int, elem Type) Type { array.gcdata = nil array.ptrdata = 0 - case count == 1: + case length == 1: // In memory, 1-element array looks just like the element. array.kind |= typ.kind & kindGCProg array.gcdata = typ.gcdata @@ -2397,7 +2417,7 @@ func ArrayOf(count int, elem Type) Type { case typ.kind&kindGCProg == 0 && array.size <= maxPtrmaskBytes*8*ptrSize: // Element is small with pointer mask; array is still small. // Create direct pointer mask by turning each 1 bit in elem - // into count 1 bits in larger mask. + // into length 1 bits in larger mask. mask := make([]byte, (array.ptrdata/ptrSize+7)/8) emitGCMask(mask, 0, typ, array.len) array.gcdata = &mask[0] @@ -2418,14 +2438,14 @@ func ArrayOf(count int, elem Type) Type { prog = appendVarint(prog, elemWords-elemPtrs-1) } } - // Repeat count-1 times. + // Repeat length-1 times. if elemWords < 0x80 { prog = append(prog, byte(elemWords|0x80)) } else { prog = append(prog, 0x80) prog = appendVarint(prog, elemWords) } - prog = appendVarint(prog, uintptr(count)-1) + prog = appendVarint(prog, uintptr(length)-1) prog = append(prog, 0) *(*uint32)(unsafe.Pointer(&prog[0])) = uint32(len(prog) - 4) array.kind |= kindGCProg @@ -2439,9 +2459,9 @@ func ArrayOf(count int, elem Type) Type { array.equal = nil if eequal := etyp.equal; eequal != nil { array.equal = func(p, q unsafe.Pointer) bool { - for i := 0; i < count; i++ { - pi := arrayAt(p, i, esize, "i < count") - qi := arrayAt(q, i, esize, "i < count") + for i := 0; i < length; i++ { + pi := arrayAt(p, i, esize, "i < length") + qi := arrayAt(q, i, esize, "i < length") if !eequal(pi, qi) { return false } @@ -2451,7 +2471,7 @@ func ArrayOf(count int, elem Type) Type { } switch { - case count == 1 && !ifaceIndir(typ): + case length == 1 && !ifaceIndir(typ): // array of 1 direct iface type can be direct array.kind |= kindDirectIface default: diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go index 0b4f094..300ef1a 100644 --- a/libgo/go/reflect/value.go +++ b/libgo/go/reflect/value.go @@ -5,6 +5,7 @@ package reflect import ( + "internal/itoa" "internal/unsafeheader" "math" "runtime" @@ -350,6 +351,8 @@ func (v Value) CallSlice(in []Value) []Value { var callGC bool // for testing; see TestCallMethodJump +const debugReflectCall = false + func (v Value) call(op string, in []Value) []Value { // Get function pointer, type. t := (*funcType)(unsafe.Pointer(v.typ)) @@ -372,8 +375,9 @@ func (v Value) call(op string, in []Value) []Value { isSlice := op == "CallSlice" n := t.NumIn() + isVariadic := t.IsVariadic() if isSlice { - if !t.IsVariadic() { + if !isVariadic { panic("reflect: CallSlice of non-variadic function") } if len(in) < n { @@ -383,13 +387,13 @@ func (v Value) call(op string, in []Value) []Value { panic("reflect: CallSlice with too many input arguments") } } else { - if t.IsVariadic() { + if isVariadic { n-- } if len(in) < n { panic("reflect: Call with too few input arguments") } - if !t.IsVariadic() && len(in) > n { + if !isVariadic && len(in) > n { panic("reflect: Call with too many input arguments") } } @@ -403,7 +407,7 @@ func (v Value) call(op string, in []Value) []Value { panic("reflect: " + op + " using " + xt.String() + " as type " + targ.String()) } } - if !isSlice && t.IsVariadic() { + if !isSlice && isVariadic { // prepare slice for remaining values m := len(in) - n slice := MakeSlice(t.In(n), m, m) @@ -857,10 +861,16 @@ func valueInterface(v Value, safe bool) interface{} { return packEface(v) } -// InterfaceData returns the interface v's value as a uintptr pair. +// InterfaceData returns a pair of unspecified uintptr values. // It panics if v's Kind is not Interface. +// +// In earlier versions of Go, this function returned the interface's +// value as a uintptr pair. As of Go 1.4, the implementation of +// interface values precludes any defined use of InterfaceData. +// +// Deprecated: The memory representation of interface values is not +// compatible with InterfaceData. func (v Value) InterfaceData() [2]uintptr { - // TODO: deprecate this v.mustBe(Interface) // We treat this as a read operation, so we allow // it even for unexported data, because the caller @@ -2200,9 +2210,14 @@ func New(typ Type) Value { panic("reflect: New(nil)") } t := typ.(*rtype) + pt := t.ptrTo() + if ifaceIndir(pt) { + // This is a pointer to a go:notinheap type. + panic("reflect: New of type that may not be allocated in heap (possibly undefined cgo C type)") + } ptr := unsafe_New(t) fl := flag(Ptr) - return Value{t.ptrTo(), ptr, fl} + return Value{pt, ptr, fl} } // NewAt returns a Value representing a pointer to a value of the @@ -2255,7 +2270,7 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value // Convert returns the value v converted to type t. // If the usual Go conversion rules do not allow conversion -// of the value v to type t, Convert panics. +// of the value v to type t, or if converting v to type t panics, Convert panics. func (v Value) Convert(t Type) Value { if v.flag&flagMethod != 0 { v = makeMethodValue("Convert", v) @@ -2267,6 +2282,26 @@ func (v Value) Convert(t Type) Value { return op(v, t) } +// CanConvert reports whether the value v can be converted to type t. +// If v.CanConvert(t) returns true then v.Convert(t) will not panic. +func (v Value) CanConvert(t Type) bool { + vt := v.Type() + if !vt.ConvertibleTo(t) { + return false + } + // Currently the only conversion that is OK in terms of type + // but that can panic depending on the value is converting + // from slice to pointer-to-array. + if vt.Kind() == Slice && t.Kind() == Ptr && t.Elem().Kind() == Array { + n := t.Elem().Len() + h := (*unsafeheader.Slice)(v.ptr) + if n > h.Len { + return false + } + } + return true +} + // convertOp returns the function to convert a value of type src // to a value of type dst. If the conversion is illegal, convertOp returns nil. func convertOp(dst, src *rtype) func(Value, Type) Value { @@ -2326,6 +2361,11 @@ func convertOp(dst, src *rtype) func(Value, Type) Value { return cvtRunesString } } + // "x is a slice, T is a pointer-to-array type, + // and the slice and array types have identical element types." + if dst.Kind() == Ptr && dst.Elem().Kind() == Array && src.Elem() == dst.Elem().Elem() { + return cvtSliceArrayPtr + } case Chan: if dst.Kind() == Chan && specialChannelAssignability(dst, src) { @@ -2519,6 +2559,16 @@ func cvtStringRunes(v Value, t Type) Value { return makeRunes(v.flag.ro(), []rune(v.String()), t) } +// convertOp: []T -> *[N]T +func cvtSliceArrayPtr(v Value, t Type) Value { + n := t.Elem().Len() + h := (*unsafeheader.Slice)(v.ptr) + if n > h.Len { + panic("reflect: cannot convert slice with length " + itoa.Itoa(h.Len) + " to pointer to array with length " + itoa.Itoa(n)) + } + return Value{t.common(), h.Data, v.flag&^(flagIndir|flagAddr|flagKindMask) | flag(Ptr)} +} + // convertOp: direct copy func cvtDirect(v Value, typ Type) Value { f := v.flag diff --git a/libgo/go/reflect/visiblefields.go b/libgo/go/reflect/visiblefields.go new file mode 100644 index 0000000..1a2b535 --- /dev/null +++ b/libgo/go/reflect/visiblefields.go @@ -0,0 +1,105 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package reflect + +// VisibleFields returns all the visible fields in t, which must be a +// struct type. A field is defined as visible if it's accessible +// directly with a FieldByName call. The returned fields include fields +// inside anonymous struct members and unexported fields. They follow +// the same order found in the struct, with anonymous fields followed +// immediately by their promoted fields. +// +// For each element e of the returned slice, the corresponding field +// can be retrieved from a value v of type t by calling v.FieldByIndex(e.Index). +func VisibleFields(t Type) []StructField { + if t == nil { + panic("reflect: VisibleFields(nil)") + } + if t.Kind() != Struct { + panic("reflect.VisibleFields of non-struct type") + } + w := &visibleFieldsWalker{ + byName: make(map[string]int), + visiting: make(map[Type]bool), + fields: make([]StructField, 0, t.NumField()), + index: make([]int, 0, 2), + } + w.walk(t) + // Remove all the fields that have been hidden. + // Use an in-place removal that avoids copying in + // the common case that there are no hidden fields. + j := 0 + for i := range w.fields { + f := &w.fields[i] + if f.Name == "" { + continue + } + if i != j { + // A field has been removed. We need to shuffle + // all the subsequent elements up. + w.fields[j] = *f + } + j++ + } + return w.fields[:j] +} + +type visibleFieldsWalker struct { + byName map[string]int + visiting map[Type]bool + fields []StructField + index []int +} + +// walk walks all the fields in the struct type t, visiting +// fields in index preorder and appending them to w.fields +// (this maintains the required ordering). +// Fields that have been overridden have their +// Name field cleared. +func (w *visibleFieldsWalker) walk(t Type) { + if w.visiting[t] { + return + } + w.visiting[t] = true + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + w.index = append(w.index, i) + add := true + if oldIndex, ok := w.byName[f.Name]; ok { + old := &w.fields[oldIndex] + if len(w.index) == len(old.Index) { + // Fields with the same name at the same depth + // cancel one another out. Set the field name + // to empty to signify that has happened, and + // there's no need to add this field. + old.Name = "" + add = false + } else if len(w.index) < len(old.Index) { + // The old field loses because it's deeper than the new one. + old.Name = "" + } else { + // The old field wins because it's shallower than the new one. + add = false + } + } + if add { + // Copy the index so that it's not overwritten + // by the other appends. + f.Index = append([]int(nil), w.index...) + w.byName[f.Name] = len(w.fields) + w.fields = append(w.fields, f) + } + if f.Anonymous { + if f.Type.Kind() == Ptr { + f.Type = f.Type.Elem() + } + if f.Type.Kind() == Struct { + w.walk(f.Type) + } + } + w.index = w.index[:len(w.index)-1] + } + delete(w.visiting, t) +} diff --git a/libgo/go/reflect/visiblefields_test.go b/libgo/go/reflect/visiblefields_test.go new file mode 100644 index 0000000..915bbee --- /dev/null +++ b/libgo/go/reflect/visiblefields_test.go @@ -0,0 +1,330 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package reflect_test + +import ( + . "reflect" + "testing" +) + +type structField struct { + name string + index []int +} + +var fieldsTests = []struct { + testName string + val interface{} + expect []structField +}{{ + testName: "SimpleStruct", + val: struct { + A int + B string + C bool + }{}, + expect: []structField{{ + name: "A", + index: []int{0}, + }, { + name: "B", + index: []int{1}, + }, { + name: "C", + index: []int{2}, + }}, +}, { + testName: "NonEmbeddedStructMember", + val: struct { + A struct { + X int + } + }{}, + expect: []structField{{ + name: "A", + index: []int{0}, + }}, +}, { + testName: "EmbeddedExportedStruct", + val: struct { + SFG + }{}, + expect: []structField{{ + name: "SFG", + index: []int{0}, + }, { + name: "F", + index: []int{0, 0}, + }, { + name: "G", + index: []int{0, 1}, + }}, +}, { + testName: "EmbeddedUnexportedStruct", + val: struct { + sFG + }{}, + expect: []structField{{ + name: "sFG", + index: []int{0}, + }, { + name: "F", + index: []int{0, 0}, + }, { + name: "G", + index: []int{0, 1}, + }}, +}, { + testName: "TwoEmbeddedStructsWithCancellingMembers", + val: struct { + SFG + SF + }{}, + expect: []structField{{ + name: "SFG", + index: []int{0}, + }, { + name: "G", + index: []int{0, 1}, + }, { + name: "SF", + index: []int{1}, + }}, +}, { + testName: "EmbeddedStructsWithSameFieldsAtDifferentDepths", + val: struct { + SFGH3 + SG1 + SFG2 + SF2 + L int + }{}, + expect: []structField{{ + name: "SFGH3", + index: []int{0}, + }, { + name: "SFGH2", + index: []int{0, 0}, + }, { + name: "SFGH1", + index: []int{0, 0, 0}, + }, { + name: "SFGH", + index: []int{0, 0, 0, 0}, + }, { + name: "H", + index: []int{0, 0, 0, 0, 2}, + }, { + name: "SG1", + index: []int{1}, + }, { + name: "SG", + index: []int{1, 0}, + }, { + name: "G", + index: []int{1, 0, 0}, + }, { + name: "SFG2", + index: []int{2}, + }, { + name: "SFG1", + index: []int{2, 0}, + }, { + name: "SFG", + index: []int{2, 0, 0}, + }, { + name: "SF2", + index: []int{3}, + }, { + name: "SF1", + index: []int{3, 0}, + }, { + name: "SF", + index: []int{3, 0, 0}, + }, { + name: "L", + index: []int{4}, + }}, +}, { + testName: "EmbeddedPointerStruct", + val: struct { + *SF + }{}, + expect: []structField{{ + name: "SF", + index: []int{0}, + }, { + name: "F", + index: []int{0, 0}, + }}, +}, { + testName: "EmbeddedNotAPointer", + val: struct { + M + }{}, + expect: []structField{{ + name: "M", + index: []int{0}, + }}, +}, { + testName: "RecursiveEmbedding", + val: Rec1{}, + expect: []structField{{ + name: "Rec2", + index: []int{0}, + }, { + name: "F", + index: []int{0, 0}, + }, { + name: "Rec1", + index: []int{0, 1}, + }}, +}, { + testName: "RecursiveEmbedding2", + val: Rec2{}, + expect: []structField{{ + name: "F", + index: []int{0}, + }, { + name: "Rec1", + index: []int{1}, + }, { + name: "Rec2", + index: []int{1, 0}, + }}, +}, { + testName: "RecursiveEmbedding3", + val: RS3{}, + expect: []structField{{ + name: "RS2", + index: []int{0}, + }, { + name: "RS1", + index: []int{1}, + }, { + name: "i", + index: []int{1, 0}, + }}, +}} + +type SFG struct { + F int + G int +} + +type SFG1 struct { + SFG +} + +type SFG2 struct { + SFG1 +} + +type SFGH struct { + F int + G int + H int +} + +type SFGH1 struct { + SFGH +} + +type SFGH2 struct { + SFGH1 +} + +type SFGH3 struct { + SFGH2 +} + +type SF struct { + F int +} + +type SF1 struct { + SF +} + +type SF2 struct { + SF1 +} + +type SG struct { + G int +} + +type SG1 struct { + SG +} + +type sFG struct { + F int + G int +} + +type RS1 struct { + i int +} + +type RS2 struct { + RS1 +} + +type RS3 struct { + RS2 + RS1 +} + +type M map[string]interface{} + +type Rec1 struct { + *Rec2 +} + +type Rec2 struct { + F string + *Rec1 +} + +func TestFields(t *testing.T) { + for _, test := range fieldsTests { + test := test + t.Run(test.testName, func(t *testing.T) { + typ := TypeOf(test.val) + fields := VisibleFields(typ) + if got, want := len(fields), len(test.expect); got != want { + t.Fatalf("unexpected field count; got %d want %d", got, want) + } + + for j, field := range fields { + expect := test.expect[j] + t.Logf("field %d: %s", j, expect.name) + gotField := typ.FieldByIndex(field.Index) + // Unfortunately, FieldByIndex does not return + // a field with the same index that we passed in, + // so we set it to the expected value so that + // it can be compared later with the result of FieldByName. + gotField.Index = field.Index + expectField := typ.FieldByIndex(expect.index) + // ditto. + expectField.Index = expect.index + if !DeepEqual(gotField, expectField) { + t.Fatalf("unexpected field result\ngot %#v\nwant %#v", gotField, expectField) + } + + // Sanity check that we can actually access the field by the + // expected name. + gotField1, ok := typ.FieldByName(expect.name) + if !ok { + t.Fatalf("field %q not accessible by name", expect.name) + } + if !DeepEqual(gotField1, expectField) { + t.Fatalf("unexpected FieldByName result; got %#v want %#v", gotField1, expectField) + } + } + }) + } +} diff --git a/libgo/go/regexp/exec2_test.go b/libgo/go/regexp/exec2_test.go index 7b86b41..6444bc1 100644 --- a/libgo/go/regexp/exec2_test.go +++ b/libgo/go/regexp/exec2_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !race // +build !race package regexp diff --git a/libgo/go/regexp/find_test.go b/libgo/go/regexp/find_test.go index 87c49b0..64c2239 100644 --- a/libgo/go/regexp/find_test.go +++ b/libgo/go/regexp/find_test.go @@ -97,6 +97,7 @@ var findTests = []FindTest{ {`\B`, "xx", build(1, 1, 1)}, {`\B`, "x y", nil}, {`\B`, "xx yy", build(2, 1, 1, 4, 4)}, + {`(|a)*`, "aa", build(3, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2)}, // RE2 tests {`[^\S\s]`, "abcd", nil}, diff --git a/libgo/go/regexp/onepass_test.go b/libgo/go/regexp/onepass_test.go index 32264d5..6a42eda 100644 --- a/libgo/go/regexp/onepass_test.go +++ b/libgo/go/regexp/onepass_test.go @@ -142,7 +142,7 @@ var onePassTests = []struct { {`^(?:(a)|(?:a*))$`, false}, {`^(?:(?:(?:.(?:$))?))$`, true}, {`^abcd$`, true}, - {`^(?:(?:a{0,})*?)$`, true}, + {`^(?:(?:a{0,})*?)$`, false}, {`^(?:(?:a+)*)$`, true}, {`^(?:(?:a|(?:aa)))$`, true}, {`^(?:[^\s\S])$`, true}, diff --git a/libgo/go/regexp/syntax/compile.go b/libgo/go/regexp/syntax/compile.go index 7524d62..c9f9fa0 100644 --- a/libgo/go/regexp/syntax/compile.go +++ b/libgo/go/regexp/syntax/compile.go @@ -57,8 +57,9 @@ func (l1 patchList) append(p *Prog, l2 patchList) patchList { // A frag represents a compiled program fragment. type frag struct { - i uint32 // index of first instruction - out patchList // where to record end instruction + i uint32 // index of first instruction + out patchList // where to record end instruction + nullable bool // whether fragment can match empty string } type compiler struct { @@ -159,7 +160,7 @@ func (c *compiler) compile(re *Regexp) frag { func (c *compiler) inst(op InstOp) frag { // TODO: impose length limit - f := frag{i: uint32(len(c.p.Inst))} + f := frag{i: uint32(len(c.p.Inst)), nullable: true} c.p.Inst = append(c.p.Inst, Inst{Op: op}) return f } @@ -194,7 +195,7 @@ func (c *compiler) cat(f1, f2 frag) frag { // TODO: elide nop f1.out.patch(c.p, f2.i) - return frag{f1.i, f2.out} + return frag{f1.i, f2.out, f1.nullable && f2.nullable} } func (c *compiler) alt(f1, f2 frag) frag { @@ -211,6 +212,7 @@ func (c *compiler) alt(f1, f2 frag) frag { i.Out = f1.i i.Arg = f2.i f.out = f1.out.append(c.p, f2.out) + f.nullable = f1.nullable || f2.nullable return f } @@ -228,7 +230,12 @@ func (c *compiler) quest(f1 frag, nongreedy bool) frag { return f } -func (c *compiler) star(f1 frag, nongreedy bool) frag { +// loop returns the fragment for the main loop of a plus or star. +// For plus, it can be used after changing the entry to f1.i. +// For star, it can be used directly when f1 can't match an empty string. +// (When f1 can match an empty string, f1* must be implemented as (f1+)? +// to get the priority match order correct.) +func (c *compiler) loop(f1 frag, nongreedy bool) frag { f := c.inst(InstAlt) i := &c.p.Inst[f.i] if nongreedy { @@ -242,8 +249,17 @@ func (c *compiler) star(f1 frag, nongreedy bool) frag { return f } +func (c *compiler) star(f1 frag, nongreedy bool) frag { + if f1.nullable { + // Use (f1+)? to get priority match order correct. + // See golang.org/issue/46123. + return c.quest(c.plus(f1, nongreedy), nongreedy) + } + return c.loop(f1, nongreedy) +} + func (c *compiler) plus(f1 frag, nongreedy bool) frag { - return frag{f1.i, c.star(f1, nongreedy).out} + return frag{f1.i, c.loop(f1, nongreedy).out, f1.nullable} } func (c *compiler) empty(op EmptyOp) frag { @@ -255,6 +271,7 @@ func (c *compiler) empty(op EmptyOp) frag { func (c *compiler) rune(r []rune, flags Flags) frag { f := c.inst(InstRune) + f.nullable = false i := &c.p.Inst[f.i] i.Rune = r flags &= FoldCase // only relevant flag is FoldCase diff --git a/libgo/go/regexp/syntax/prog_test.go b/libgo/go/regexp/syntax/prog_test.go index 50bfa3d..5603aea 100644 --- a/libgo/go/regexp/syntax/prog_test.go +++ b/libgo/go/regexp/syntax/prog_test.go @@ -89,6 +89,21 @@ var compileTests = []struct { 2 anynotnl -> 3 3 match `}, + {"(?:|a)+", ` 0 fail + 1 nop -> 4 + 2 rune1 "a" -> 4 + 3* alt -> 1, 2 + 4 alt -> 3, 5 + 5 match +`}, + {"(?:|a)*", ` 0 fail + 1 nop -> 4 + 2 rune1 "a" -> 4 + 3 alt -> 1, 2 + 4 alt -> 3, 6 + 5* alt -> 3, 6 + 6 match +`}, } func TestCompile(t *testing.T) { diff --git a/libgo/go/regexp/testdata/basic.dat b/libgo/go/regexp/testdata/basic.dat index 7859290b..1776b1f 100644 --- a/libgo/go/regexp/testdata/basic.dat +++ b/libgo/go/regexp/testdata/basic.dat @@ -124,24 +124,20 @@ E ((a)) abc (0,1)(0,1)(0,1) E (a)b(c) abc (0,3)(0,1)(2,3) E a+b+c aabbabc (4,7) E a* aaa (0,3) -#E (a*)* - (0,0)(0,0) -E (a*)* - (0,0)(?,?) RE2/Go +E (a*)* - (0,0)(0,0) E (a*)+ - (0,0)(0,0) -#E (a*|b)* - (0,0)(0,0) -E (a*|b)* - (0,0)(?,?) RE2/Go +E (a*|b)* - (0,0)(0,0) E (a+|b)* ab (0,2)(1,2) E (a+|b)+ ab (0,2)(1,2) E (a+|b)? ab (0,1)(0,1) BE [^ab]* cde (0,3) -#E (^)* - (0,0)(0,0) -E (^)* - (0,0)(?,?) RE2/Go +E (^)* - (0,0)(0,0) BE a* NULL (0,0) E ([abc])*d abbbcd (0,6)(4,5) E ([abc])*bcd abcd (0,4)(0,1) E a|b|c|d|e e (0,1) E (a|b|c|d|e)f ef (0,2)(0,1) -#E ((a*|b))* - (0,0)(0,0)(0,0) -E ((a*|b))* - (0,0)(?,?)(?,?) RE2/Go +E ((a*|b))* - (0,0)(0,0)(0,0) BE abcd*efg abcdefg (0,7) BE ab* xabyabbbz (1,3) BE ab* xayabbbz (1,2) diff --git a/libgo/go/regexp/testdata/nullsubexpr.dat b/libgo/go/regexp/testdata/nullsubexpr.dat index 2e18fbb..68d9c99 100644 --- a/libgo/go/regexp/testdata/nullsubexpr.dat +++ b/libgo/go/regexp/testdata/nullsubexpr.dat @@ -1,8 +1,7 @@ NOTE null subexpression matches : 2002-06-06 E (a*)* a (0,1)(0,1) -#E SAME x (0,0)(0,0) -E SAME x (0,0)(?,?) RE2/Go +E SAME x (0,0)(0,0) E SAME aaaaaa (0,6)(0,6) E SAME aaaaaax (0,6)(0,6) E (a*)+ a (0,1)(0,1) @@ -19,8 +18,7 @@ E SAME aaaaaa (0,6)(0,6) E SAME aaaaaax (0,6)(0,6) E ([a]*)* a (0,1)(0,1) -#E SAME x (0,0)(0,0) -E SAME x (0,0)(?,?) RE2/Go +E SAME x (0,0)(0,0) E SAME aaaaaa (0,6)(0,6) E SAME aaaaaax (0,6)(0,6) E ([a]*)+ a (0,1)(0,1) @@ -28,8 +26,7 @@ E SAME x (0,0)(0,0) E SAME aaaaaa (0,6)(0,6) E SAME aaaaaax (0,6)(0,6) E ([^b]*)* a (0,1)(0,1) -#E SAME b (0,0)(0,0) -E SAME b (0,0)(?,?) RE2/Go +E SAME b (0,0)(0,0) E SAME aaaaaa (0,6)(0,6) E SAME aaaaaab (0,6)(0,6) E ([ab]*)* a (0,1)(0,1) @@ -41,11 +38,9 @@ E SAME bbbbbb (0,6)(0,6) E SAME aaaabcde (0,5)(0,5) E ([^a]*)* b (0,1)(0,1) E SAME bbbbbb (0,6)(0,6) -#E SAME aaaaaa (0,0)(0,0) -E SAME aaaaaa (0,0)(?,?) RE2/Go +E SAME aaaaaa (0,0)(0,0) E ([^ab]*)* ccccxx (0,6)(0,6) -#E SAME ababab (0,0)(0,0) -E SAME ababab (0,0)(?,?) RE2/Go +E SAME ababab (0,0)(0,0) E ((z)+|a)* zabcde (0,2)(1,2) @@ -65,8 +60,7 @@ B \(a*\)*\(x\)\(\1\) axa (0,3)(0,1)(1,2)(2,3) B \(a*\)*\(x\)\(\1\)\(x\) axax (0,4)(0,1)(1,2)(2,3)(3,4) B \(a*\)*\(x\)\(\1\)\(x\) axxa (0,3)(1,1)(1,2)(2,2)(2,3) -#E (a*)*(x) x (0,1)(0,0)(0,1) -E (a*)*(x) x (0,1)(?,?)(0,1) RE2/Go +E (a*)*(x) x (0,1)(0,0)(0,1) E (a*)*(x) ax (0,2)(0,1)(1,2) E (a*)*(x) axa (0,2)(0,1)(1,2) diff --git a/libgo/go/regexp/testdata/re2-exhaustive.txt.bz2 b/libgo/go/regexp/testdata/re2-exhaustive.txt.bz2 Binary files differindex a357f28..6638476 100644 --- a/libgo/go/regexp/testdata/re2-exhaustive.txt.bz2 +++ b/libgo/go/regexp/testdata/re2-exhaustive.txt.bz2 diff --git a/libgo/go/regexp/testdata/re2-search.txt b/libgo/go/regexp/testdata/re2-search.txt index 4d02e9c..8c4098a 100644 --- a/libgo/go/regexp/testdata/re2-search.txt +++ b/libgo/go/regexp/testdata/re2-search.txt @@ -1,5 +1,5 @@ # RE2 basic search tests built by make log -# Thu Sep 8 13:43:43 EDT 2011 +# Wed May 12 12:13:22 EDT 2021 Regexp.SearchTests strings "" @@ -227,22 +227,6 @@ regexps 0-0;0-0;0-0;0-0 strings "" -"" -regexps -"a*" -0-0;0-0;0-0;0-0 -0-0;0-0;0-0;0-0 -"^(?:a*)$" -0-0;0-0;0-0;0-0 -0-0;0-0;0-0;0-0 -"^(?:a*)" -0-0;0-0;0-0;0-0 -0-0;0-0;0-0;0-0 -"(?:a*)$" -0-0;0-0;0-0;0-0 -0-0;0-0;0-0;0-0 -strings -"" "xabcdx" regexps "ab|cd" @@ -3651,6 +3635,86 @@ regexps 0-1;0-1;0-1;0-1 strings "" +"a" +regexps +"a\\C+" +-;-;-;- +-;-;-;- +"^(?:a\\C+)$" +-;-;-;- +-;-;-;- +"^(?:a\\C+)" +-;-;-;- +-;-;-;- +"(?:a\\C+)$" +-;-;-;- +-;-;-;- +strings +"" +"a" +regexps +"a\\C?" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:a\\C?)$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:a\\C?)" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:a\\C?)$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"a" +regexps +"a\\C*?" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:a\\C*?)$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:a\\C*?)" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:a\\C*?)$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" +"a" +regexps +"a\\C+?" +-;-;-;- +-;-;-;- +"^(?:a\\C+?)$" +-;-;-;- +-;-;-;- +"^(?:a\\C+?)" +-;-;-;- +-;-;-;- +"(?:a\\C+?)$" +-;-;-;- +-;-;-;- +strings +"" +"a" +regexps +"a\\C??" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:a\\C??)$" +-;-;-;- +0-1;0-1;0-1;0-1 +"^(?:a\\C??)" +-;-;-;- +0-1;0-1;0-1;0-1 +"(?:a\\C??)$" +-;-;-;- +0-1;0-1;0-1;0-1 +strings +"" "baba" regexps "a\\C*|ba\\C" @@ -3666,7 +3730,50 @@ regexps -;-;-;- -;1-4;-;1-4 strings -"abc" +"" +"Inc." regexps -"a.*?c|a.*?b" +"\\w*I\\w*" +-;-;-;- +-;0-3;-;0-3 +"^(?:\\w*I\\w*)$" +-;-;-;- +-;-;-;- +"^(?:\\w*I\\w*)" +-;-;-;- +-;0-3;-;0-3 +"(?:\\w*I\\w*)$" +-;-;-;- +-;-;-;- +strings +"" +"aaa" +regexps +"(?:|a)*" +0-0;0-0;0-0;0-0 +0-3;0-0;0-3;0-3 +"^(?:(?:|a)*)$" +0-0;0-0;0-0;0-0 +0-3;0-3;0-3;0-3 +"^(?:(?:|a)*)" +0-0;0-0;0-0;0-0 +0-3;0-0;0-3;0-3 +"(?:(?:|a)*)$" +0-0;0-0;0-0;0-0 +0-3;0-3;0-3;0-3 +strings +"" +"aaa" +regexps +"(?:|a)+" +0-0;0-0;0-0;0-0 +0-3;0-0;0-3;0-3 +"^(?:(?:|a)+)$" +0-0;0-0;0-0;0-0 +0-3;0-3;0-3;0-3 +"^(?:(?:|a)+)" +0-0;0-0;0-0;0-0 +0-3;0-0;0-3;0-3 +"(?:(?:|a)+)$" +0-0;0-0;0-0;0-0 0-3;0-3;0-3;0-3 diff --git a/libgo/go/runtime/abi_test.go b/libgo/go/runtime/abi_test.go new file mode 100644 index 0000000..b27b012 --- /dev/null +++ b/libgo/go/runtime/abi_test.go @@ -0,0 +1,112 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build goexperiment.regabireflect +// +build goexperiment.regabireflect + +// This file contains tests specific to making sure the register ABI +// works in a bunch of contexts in the runtime. + +package runtime_test + +import ( + "internal/testenv" + "os" + "os/exec" + "runtime" + "strings" + "testing" + "time" +) + +var regConfirmRun chan int + +//go:registerparams +func regFinalizerPointer(v *Tint) (int, float32, [10]byte) { + regConfirmRun <- *(*int)(v) + return 5151, 4.0, [10]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} +} + +//go:registerparams +func regFinalizerIface(v Tinter) (int, float32, [10]byte) { + regConfirmRun <- *(*int)(v.(*Tint)) + return 5151, 4.0, [10]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} +} + +func TestFinalizerRegisterABI(t *testing.T) { + testenv.MustHaveExec(t) + + // Actually run the test in a subprocess because we don't want + // finalizers from other tests interfering. + if os.Getenv("TEST_FINALIZER_REGABI") != "1" { + cmd := testenv.CleanCmdEnv(exec.Command(os.Args[0], "-test.run=TestFinalizerRegisterABI", "-test.v")) + cmd.Env = append(cmd.Env, "TEST_FINALIZER_REGABI=1") + out, err := cmd.CombinedOutput() + if !strings.Contains(string(out), "PASS\n") || err != nil { + t.Fatalf("%s\n(exit status %v)", string(out), err) + } + return + } + + // Optimistically clear any latent finalizers from e.g. the testing + // package before continuing. + // + // It's possible that a finalizer only becomes available to run + // after this point, which would interfere with the test and could + // cause a crash, but because we're running in a separate process + // it's extremely unlikely. + runtime.GC() + runtime.GC() + + // fing will only pick the new IntRegArgs up if it's currently + // sleeping and wakes up, so wait for it to go to sleep. + success := false + for i := 0; i < 100; i++ { + if runtime.FinalizerGAsleep() { + success = true + break + } + time.Sleep(20 * time.Millisecond) + } + if !success { + t.Fatal("finalizer not asleep?") + } + + // argRegsBefore := runtime.SetIntArgRegs(abi.IntArgRegs) + // defer runtime.SetIntArgRegs(argRegsBefore) + + tests := []struct { + name string + fin interface{} + confirmValue int + }{ + {"Pointer", regFinalizerPointer, -1}, + {"Interface", regFinalizerIface, -2}, + } + for i := range tests { + test := &tests[i] + t.Run(test.name, func(t *testing.T) { + regConfirmRun = make(chan int) + + x := new(Tint) + *x = (Tint)(test.confirmValue) + runtime.SetFinalizer(x, test.fin) + + runtime.KeepAlive(x) + + // Queue the finalizer. + runtime.GC() + runtime.GC() + + select { + case <-time.After(time.Second): + t.Fatal("finalizer failed to execute") + case gotVal := <-regConfirmRun: + if gotVal != test.confirmValue { + t.Fatalf("wrong finalizer executed? got %d, want %d", gotVal, test.confirmValue) + } + } + }) + } +} diff --git a/libgo/go/runtime/alg.go b/libgo/go/runtime/alg.go index b5b22cf..4408eab 100644 --- a/libgo/go/runtime/alg.go +++ b/libgo/go/runtime/alg.go @@ -216,7 +216,6 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr { case kindStruct: s := (*structtype)(unsafe.Pointer(t)) for _, f := range s.fields { - // TODO: maybe we could hash several contiguous fields all at once. if f.name != nil && *f.name == "_" { continue } diff --git a/libgo/go/runtime/auxv_none.go b/libgo/go/runtime/auxv_none.go index 3ca617b..3178f1a 100644 --- a/libgo/go/runtime/auxv_none.go +++ b/libgo/go/runtime/auxv_none.go @@ -2,12 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !linux -// +build !darwin -// +build !dragonfly -// +build !freebsd -// +build !netbsd -// +build !solaris +//go:build !linux && !darwin && !dragonfly && !freebsd && !netbsd && !solaris +// +build !linux,!darwin,!dragonfly,!freebsd,!netbsd,!solaris package runtime diff --git a/libgo/go/runtime/cgo/handle.go b/libgo/go/runtime/cgo/handle.go new file mode 100644 index 0000000..720acca --- /dev/null +++ b/libgo/go/runtime/cgo/handle.go @@ -0,0 +1,109 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cgo + +import ( + "sync" + "sync/atomic" +) + +// Handle provides a way to pass values that contain Go pointers +// (pointers to memory allocated by Go) between Go and C without +// breaking the cgo pointer passing rules. A Handle is an integer +// value that can represent any Go value. A Handle can be passed +// through C and back to Go, and Go code can use the Handle to +// retrieve the original Go value. +// +// The underlying type of Handle is guaranteed to fit in an integer type +// that is large enough to hold the bit pattern of any pointer. The zero +// value of a Handle is not valid, and thus is safe to use as a sentinel +// in C APIs. +// +// For instance, on the Go side: +// +// package main +// +// /* +// #include <stdint.h> // for uintptr_t +// +// extern void MyGoPrint(uintptr_t handle); +// void myprint(uintptr_t handle); +// */ +// import "C" +// import "runtime/cgo" +// +// //export MyGoPrint +// func MyGoPrint(handle C.uintptr_t) { +// h := cgo.Handle(handle) +// val := h.Value().(string) +// println(val) +// h.Delete() +// } +// +// func main() { +// val := "hello Go" +// C.myprint(C.uintptr_t(cgo.NewHandle(val))) +// // Output: hello Go +// } +// +// and on the C side: +// +// #include <stdint.h> // for uintptr_t +// +// // A Go function +// extern void MyGoPrint(uintptr_t handle); +// +// // A C function +// void myprint(uintptr_t handle) { +// MyGoPrint(handle); +// } +type Handle uintptr + +// NewHandle returns a handle for a given value. +// +// The handle is valid until the program calls Delete on it. The handle +// uses resources, and this package assumes that C code may hold on to +// the handle, so a program must explicitly call Delete when the handle +// is no longer needed. +// +// The intended use is to pass the returned handle to C code, which +// passes it back to Go, which calls Value. +func NewHandle(v interface{}) Handle { + h := atomic.AddUintptr(&handleIdx, 1) + if h == 0 { + panic("runtime/cgo: ran out of handle space") + } + + handles.Store(h, v) + return Handle(h) +} + +// Value returns the associated Go value for a valid handle. +// +// The method panics if the handle is invalid. +func (h Handle) Value() interface{} { + v, ok := handles.Load(uintptr(h)) + if !ok { + panic("runtime/cgo: misuse of an invalid Handle") + } + return v +} + +// Delete invalidates a handle. This method should only be called once +// the program no longer needs to pass the handle to C and the C code +// no longer has a copy of the handle value. +// +// The method panics if the handle is invalid. +func (h Handle) Delete() { + _, ok := handles.LoadAndDelete(uintptr(h)) + if !ok { + panic("runtime/cgo: misuse of an invalid Handle") + } +} + +var ( + handles = sync.Map{} // map[Handle]interface{} + handleIdx uintptr // atomic +) diff --git a/libgo/go/runtime/cgo/handle_test.go b/libgo/go/runtime/cgo/handle_test.go new file mode 100644 index 0000000..738051a --- /dev/null +++ b/libgo/go/runtime/cgo/handle_test.go @@ -0,0 +1,103 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cgo + +import ( + "reflect" + "testing" +) + +func TestHandle(t *testing.T) { + v := 42 + + tests := []struct { + v1 interface{} + v2 interface{} + }{ + {v1: v, v2: v}, + {v1: &v, v2: &v}, + {v1: nil, v2: nil}, + } + + for _, tt := range tests { + h1 := NewHandle(tt.v1) + h2 := NewHandle(tt.v2) + + if uintptr(h1) == 0 || uintptr(h2) == 0 { + t.Fatalf("NewHandle returns zero") + } + + if uintptr(h1) == uintptr(h2) { + t.Fatalf("Duplicated Go values should have different handles, but got equal") + } + + h1v := h1.Value() + h2v := h2.Value() + if !reflect.DeepEqual(h1v, h2v) || !reflect.DeepEqual(h1v, tt.v1) { + t.Fatalf("Value of a Handle got wrong, got %+v %+v, want %+v", h1v, h2v, tt.v1) + } + + h1.Delete() + h2.Delete() + } + + siz := 0 + handles.Range(func(k, v interface{}) bool { + siz++ + return true + }) + if siz != 0 { + t.Fatalf("handles are not cleared, got %d, want %d", siz, 0) + } +} + +func TestInvalidHandle(t *testing.T) { + t.Run("zero", func(t *testing.T) { + h := Handle(0) + + defer func() { + if r := recover(); r != nil { + return + } + t.Fatalf("Delete of zero handle did not trigger a panic") + }() + + h.Delete() + }) + + t.Run("invalid", func(t *testing.T) { + h := NewHandle(42) + + defer func() { + if r := recover(); r != nil { + h.Delete() + return + } + t.Fatalf("Invalid handle did not trigger a panic") + }() + + Handle(h + 1).Delete() + }) +} + +func BenchmarkHandle(b *testing.B) { + b.Run("non-concurrent", func(b *testing.B) { + for i := 0; i < b.N; i++ { + h := NewHandle(i) + _ = h.Value() + h.Delete() + } + }) + b.Run("concurrent", func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + var v int + for pb.Next() { + h := NewHandle(v) + _ = h.Value() + h.Delete() + } + }) + }) +} diff --git a/libgo/go/runtime/cgocall.go b/libgo/go/runtime/cgocall.go index 79fe65c..0495d67 100644 --- a/libgo/go/runtime/cgocall.go +++ b/libgo/go/runtime/cgocall.go @@ -15,6 +15,8 @@ import ( //go:linkname cgoCheckPointer //go:linkname cgoCheckResult +var ncgocall uint64 // number of cgo calls in total for dead m + // Pointer checking for cgo code. // We want to detect all cases where a program that does not use diff --git a/libgo/go/runtime/chan_test.go b/libgo/go/runtime/chan_test.go index 85d3e04..4aae89f 100644 --- a/libgo/go/runtime/chan_test.go +++ b/libgo/go/runtime/chan_test.go @@ -636,7 +636,7 @@ func TestNoShrinkStackWhileParking(t *testing.T) { // channel. See issue 40641 for more details on the problem. // // The way we try to induce this failure is to set up two - // goroutines: a sender and a reciever that communicate across + // goroutines: a sender and a receiver that communicate across // a channel. We try to set up a situation where the sender // grows its stack temporarily then *fully* blocks on a channel // often. Meanwhile a GC is triggered so that we try to get a @@ -676,7 +676,7 @@ func TestNoShrinkStackWhileParking(t *testing.T) { go send(c, done) // Wait a little bit before triggering // the GC to make sure the sender and - // reciever have gotten into their groove. + // receiver have gotten into their groove. time.Sleep(50 * time.Microsecond) runtime.GC() <-done @@ -713,8 +713,6 @@ func TestSelectDuplicateChannel(t *testing.T) { c <- 8 // wake up B. This operation used to fail because c.recvq was corrupted (it tries to wake up an already running G instead of B) } -var selectSink interface{} - func TestSelectStackAdjust(t *testing.T) { // Test that channel receive slots that contain local stack // pointers are adjusted correctly by stack shrinking. @@ -771,20 +769,8 @@ func TestSelectStackAdjust(t *testing.T) { <-ready2 time.Sleep(10 * time.Millisecond) - // Force concurrent GC a few times. - var before, after runtime.MemStats - runtime.ReadMemStats(&before) - for i := 0; i < 100; i++ { - selectSink = new([1 << 20]byte) - runtime.ReadMemStats(&after) - if after.NumGC-before.NumGC >= 2 { - goto done - } - runtime.Gosched() - } - t.Fatal("failed to trigger concurrent GC") -done: - selectSink = nil + // Force concurrent GC to shrink the stacks. + runtime.GC() // Wake selects. close(d) diff --git a/libgo/go/runtime/checkptr.go b/libgo/go/runtime/checkptr.go index e52f7df..ad3ad29 100644 --- a/libgo/go/runtime/checkptr.go +++ b/libgo/go/runtime/checkptr.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore package runtime @@ -9,6 +10,11 @@ package runtime import "unsafe" func checkptrAlignment(p unsafe.Pointer, elem *_type, n uintptr) { + // nil pointer is always suitably aligned (#47430). + if p == nil { + return + } + // Check that (*[n]elem)(p) is appropriately aligned. // Note that we allow unaligned pointers if the types they point to contain // no pointers themselves. See issue 37298. @@ -18,11 +24,32 @@ func checkptrAlignment(p unsafe.Pointer, elem *_type, n uintptr) { } // Check that (*[n]elem)(p) doesn't straddle multiple heap objects. - if size := n * elem.size; size > 1 && checkptrBase(p) != checkptrBase(add(p, size-1)) { + // TODO(mdempsky): Fix #46938 so we don't need to worry about overflow here. + if checkptrStraddles(p, n*elem.size) { throw("checkptr: converted pointer straddles multiple allocations") } } +// checkptrStraddles reports whether the first size-bytes of memory +// addressed by ptr is known to straddle more than one Go allocation. +func checkptrStraddles(ptr unsafe.Pointer, size uintptr) bool { + if size <= 1 { + return false + } + + // Check that add(ptr, size-1) won't overflow. This avoids the risk + // of producing an illegal pointer value (assuming ptr is legal). + if uintptr(ptr) >= -(size - 1) { + return true + } + end := add(ptr, size-1) + + // TODO(mdempsky): Detect when [ptr, end] contains Go allocations, + // but neither ptr nor end point into one themselves. + + return checkptrBase(ptr) != checkptrBase(end) +} + func checkptrArithmetic(p unsafe.Pointer, originals []unsafe.Pointer) { if 0 < uintptr(p) && uintptr(p) < minLegalPointer { throw("checkptr: pointer arithmetic computed bad pointer value") diff --git a/libgo/go/runtime/checkptr_test.go b/libgo/go/runtime/checkptr_test.go index bd2d00f..3e42469 100644 --- a/libgo/go/runtime/checkptr_test.go +++ b/libgo/go/runtime/checkptr_test.go @@ -30,10 +30,13 @@ func TestCheckPtr(t *testing.T) { }{ {"CheckPtrAlignmentPtr", "fatal error: checkptr: misaligned pointer conversion\n"}, {"CheckPtrAlignmentNoPtr", ""}, + {"CheckPtrAlignmentNilPtr", ""}, {"CheckPtrArithmetic", "fatal error: checkptr: pointer arithmetic result points to invalid allocation\n"}, {"CheckPtrArithmetic2", "fatal error: checkptr: pointer arithmetic result points to invalid allocation\n"}, {"CheckPtrSize", "fatal error: checkptr: converted pointer straddles multiple allocations\n"}, {"CheckPtrSmall", "fatal error: checkptr: pointer arithmetic computed bad pointer value\n"}, + {"CheckPtrSliceOK", ""}, + {"CheckPtrSliceFail", "fatal error: checkptr: unsafe.Slice result straddles multiple allocations\n"}, } for _, tc := range testCases { diff --git a/libgo/go/runtime/cpuprof.go b/libgo/go/runtime/cpuprof.go index 43f0a67..55ad0d1 100644 --- a/libgo/go/runtime/cpuprof.go +++ b/libgo/go/runtime/cpuprof.go @@ -103,7 +103,16 @@ func (p *cpuProfile) add(gp *g, stk []uintptr) { // because otherwise its write barrier behavior may not // be correct. See the long comment there before // changing the argument here. - cpuprof.log.write(&gp.labels, nanotime(), hdr[:], stk) + // + // Note: it can happen on Windows, where we are calling + // p.add with a gp that is not the current g, that gp is nil, + // meaning we interrupted a system thread with no g. + // Avoid faulting in that case. + var tagPtr *unsafe.Pointer + if gp != nil { + tagPtr = &gp.labels + } + cpuprof.log.write(tagPtr, nanotime(), hdr[:], stk) } atomic.Store(&prof.signalLock, 0) diff --git a/libgo/go/runtime/cputicks.go b/libgo/go/runtime/cputicks.go index c41a58b..84e3ce3 100644 --- a/libgo/go/runtime/cputicks.go +++ b/libgo/go/runtime/cputicks.go @@ -2,13 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// // +build !arm -// // +build !arm64 -// // +build !mips64 -// // +build !mips64le -// // +build !mips -// // +build !mipsle -// // +build !wasm +//-go:build !arm && !arm64 && !mips64 && !mips64le && !mips && !mipsle && !wasm +// -build !arm,!arm64,!mips64,!mips64le,!mips,!mipsle,!wasm package runtime diff --git a/libgo/go/runtime/crash_cgo_test.go b/libgo/go/runtime/crash_cgo_test.go index b0198ff..6ad42b2 100644 --- a/libgo/go/runtime/crash_cgo_test.go +++ b/libgo/go/runtime/crash_cgo_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cgo // +build cgo package runtime_test @@ -290,6 +291,18 @@ func TestCgoTracebackContext(t *testing.T) { } } +func TestCgoTracebackContextPreemption(t *testing.T) { + t.Parallel() + if runtime.Compiler == "gccgo" { + t.Skip("gccgo does not have SetCgoTraceback") + } + got := runTestProg(t, "testprogcgo", "TracebackContextPreemption") + want := "OK\n" + if got != want { + t.Errorf("expected %q got %v", want, got) + } +} + func testCgoPprof(t *testing.T, buildArg, runArg, top, bottom string) { t.Parallel() if runtime.GOOS != "linux" || (runtime.GOARCH != "amd64" && runtime.GOARCH != "ppc64le") { diff --git a/libgo/go/runtime/crash_nonunix_test.go b/libgo/go/runtime/crash_nonunix_test.go index 06c197e..5f61476 100644 --- a/libgo/go/runtime/crash_nonunix_test.go +++ b/libgo/go/runtime/crash_nonunix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows || plan9 || (js && wasm) // +build windows plan9 js,wasm package runtime_test diff --git a/libgo/go/runtime/crash_test.go b/libgo/go/runtime/crash_test.go index 102b1a5..15c6000 100644 --- a/libgo/go/runtime/crash_test.go +++ b/libgo/go/runtime/crash_test.go @@ -474,14 +474,6 @@ func TestRecoverBeforePanicAfterGoexit2(t *testing.T) { } func TestNetpollDeadlock(t *testing.T) { - if os.Getenv("GO_BUILDER_NAME") == "darwin-amd64-10_12" { - // A suspected kernel bug in macOS 10.12 occasionally results in - // an apparent deadlock when dialing localhost. The errors have not - // been observed on newer versions of the OS, so we don't plan to work - // around them. See https://golang.org/issue/22019. - testenv.SkipFlaky(t, 22019) - } - t.Parallel() output := runTestProg(t, "testprognet", "NetpollDeadlock") want := "done\n" diff --git a/libgo/go/runtime/crash_unix_test.go b/libgo/go/runtime/crash_unix_test.go index 69aecd5..9dac167 100644 --- a/libgo/go/runtime/crash_unix_test.go +++ b/libgo/go/runtime/crash_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package runtime_test @@ -12,7 +13,6 @@ import ( "io" "os" "os/exec" - "path/filepath" "runtime" "strings" "sync" @@ -69,7 +69,8 @@ func TestCrashDumpsAllThreads(t *testing.T) { t.Skipf("skipping; not supported on %v", runtime.GOOS) } - if runtime.GOOS == "openbsd" && runtime.GOARCH == "mips64" { + if runtime.GOOS == "openbsd" && (runtime.GOARCH == "arm" || runtime.GOARCH == "mips64") { + // This may be ncpu < 2 related... t.Skipf("skipping; test fails on %s/%s - see issue #42464", runtime.GOOS, runtime.GOARCH) } @@ -77,31 +78,14 @@ func TestCrashDumpsAllThreads(t *testing.T) { t.Skip("skipping; SIGQUIT is blocked, see golang.org/issue/19196") } - // We don't use executeTest because we need to kill the - // program while it is running. - testenv.MustHaveGoBuild(t) - t.Parallel() - - dir, err := os.MkdirTemp("", "go-build") - if err != nil { - t.Fatalf("failed to create temp directory: %v", err) - } - defer os.RemoveAll(dir) - - if err := os.WriteFile(filepath.Join(dir, "main.go"), []byte(crashDumpsAllThreadsSource), 0666); err != nil { - t.Fatalf("failed to create Go file: %v", err) - } - - cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "a.exe", "main.go") - cmd.Dir = dir - out, err := testenv.CleanCmdEnv(cmd).CombinedOutput() + exe, err := buildTestProg(t, "testprog") if err != nil { - t.Fatalf("building source: %v\n%s", err, out) + t.Fatal(err) } - cmd = exec.Command(filepath.Join(dir, "a.exe")) + cmd := exec.Command(exe, "CrashDumpsAllThreads") cmd = testenv.CleanCmdEnv(cmd) cmd.Env = append(cmd.Env, "GOTRACEBACK=crash", @@ -123,9 +107,12 @@ func TestCrashDumpsAllThreads(t *testing.T) { if err != nil { t.Fatal(err) } + defer rp.Close() + cmd.ExtraFiles = []*os.File{wp} if err := cmd.Start(); err != nil { + wp.Close() t.Fatalf("starting program: %v", err) } @@ -147,59 +134,14 @@ func TestCrashDumpsAllThreads(t *testing.T) { // We want to see a stack trace for each thread. // Before https://golang.org/cl/2811 running threads would say // "goroutine running on other thread; stack unavailable". - out = outbuf.Bytes() - n := bytes.Count(out, []byte("main.loop")) + out := outbuf.Bytes() + n := bytes.Count(out, []byte("main.crashDumpsAllThreadsLoop")) if n != 4 { t.Errorf("found %d instances of main.loop; expected 4", n) t.Logf("%s", out) } } -const crashDumpsAllThreadsSource = ` -package main - -import ( - "fmt" - "os" - "runtime" - "time" -) - -func main() { - const count = 4 - runtime.GOMAXPROCS(count + 1) - - chans := make([]chan bool, count) - for i := range chans { - chans[i] = make(chan bool) - go loop(i, chans[i]) - } - - // Wait for all the goroutines to start executing. - for _, c := range chans { - <-c - } - - time.Sleep(time.Millisecond) - - // Tell our parent that all the goroutines are executing. - if _, err := os.NewFile(3, "pipe").WriteString("x"); err != nil { - fmt.Fprintf(os.Stderr, "write to pipe failed: %v\n", err) - os.Exit(2) - } - - select {} -} - -func loop(i int, c chan bool) { - close(c) - for { - for j := 0; j < 0x7fffffff; j++ { - } - } -} -` - func TestPanicSystemstack(t *testing.T) { // Test that GOTRACEBACK=crash prints both the system and user // stack of other threads. diff --git a/libgo/go/runtime/debug.go b/libgo/go/runtime/debug.go index 5fb02cb..0cd613a 100644 --- a/libgo/go/runtime/debug.go +++ b/libgo/go/runtime/debug.go @@ -45,7 +45,7 @@ func NumCPU() int { // NumCgoCall returns the number of cgo calls made by the current process. func NumCgoCall() int64 { - var n int64 + var n = int64(atomic.Load64(&ncgocall)) for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink { n += int64(mp.ncgocall) } diff --git a/libgo/go/runtime/debug/panic_test.go b/libgo/go/runtime/debug/panic_test.go index b67a3de..65f9555 100644 --- a/libgo/go/runtime/debug/panic_test.go +++ b/libgo/go/runtime/debug/panic_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd // +build aix darwin dragonfly freebsd linux netbsd openbsd // TODO: test on Windows? @@ -23,6 +24,9 @@ func TestPanicOnFault(t *testing.T) { if runtime.GOOS == "ios" { t.Skip("iOS doesn't provide fault addresses") } + if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm" { + t.Skip("netbsd-arm doesn't provide fault address (golang.org/issue/45026)") + } m, err := syscall.Mmap(-1, 0, 0x1000, syscall.PROT_READ /* Note: no PROT_WRITE */, syscall.MAP_SHARED|syscall.MAP_ANON) if err != nil { t.Fatalf("can't map anonymous memory: %s", err) diff --git a/libgo/go/runtime/debug_test.go b/libgo/go/runtime/debug_test.go deleted file mode 100644 index 46261bc..0000000 --- a/libgo/go/runtime/debug_test.go +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// TODO: This test could be implemented on all (most?) UNIXes if we -// added syscall.Tgkill more widely. - -// We skip all of these tests under race mode because our test thread -// spends all of its time in the race runtime, which isn't a safe -// point. - -// +build ignore_for_gccgo -// +build amd64 -// +build linux -// +build !race - -package runtime_test - -import ( - "fmt" - "os" - "regexp" - "runtime" - "runtime/debug" - "sync/atomic" - "syscall" - "testing" -) - -func startDebugCallWorker(t *testing.T) (g *runtime.G, after func()) { - // This can deadlock if run under a debugger because it - // depends on catching SIGTRAP, which is usually swallowed by - // a debugger. - skipUnderDebugger(t) - - // This can deadlock if there aren't enough threads or if a GC - // tries to interrupt an atomic loop (see issue #10958). We - // use 8 Ps so there's room for the debug call worker, - // something that's trying to preempt the call worker, and the - // goroutine that's trying to stop the call worker. - ogomaxprocs := runtime.GOMAXPROCS(8) - ogcpercent := debug.SetGCPercent(-1) - - // ready is a buffered channel so debugCallWorker won't block - // on sending to it. This makes it less likely we'll catch - // debugCallWorker while it's in the runtime. - ready := make(chan *runtime.G, 1) - var stop uint32 - done := make(chan error) - go debugCallWorker(ready, &stop, done) - g = <-ready - return g, func() { - atomic.StoreUint32(&stop, 1) - err := <-done - if err != nil { - t.Fatal(err) - } - runtime.GOMAXPROCS(ogomaxprocs) - debug.SetGCPercent(ogcpercent) - } -} - -func debugCallWorker(ready chan<- *runtime.G, stop *uint32, done chan<- error) { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - ready <- runtime.Getg() - - x := 2 - debugCallWorker2(stop, &x) - if x != 1 { - done <- fmt.Errorf("want x = 2, got %d; register pointer not adjusted?", x) - } - close(done) -} - -// Don't inline this function, since we want to test adjusting -// pointers in the arguments. -// -//go:noinline -func debugCallWorker2(stop *uint32, x *int) { - for atomic.LoadUint32(stop) == 0 { - // Strongly encourage x to live in a register so we - // can test pointer register adjustment. - *x++ - } - *x = 1 -} - -func debugCallTKill(tid int) error { - return syscall.Tgkill(syscall.Getpid(), tid, syscall.SIGTRAP) -} - -// skipUnderDebugger skips the current test when running under a -// debugger (specifically if this process has a tracer). This is -// Linux-specific. -func skipUnderDebugger(t *testing.T) { - pid := syscall.Getpid() - status, err := os.ReadFile(fmt.Sprintf("/proc/%d/status", pid)) - if err != nil { - t.Logf("couldn't get proc tracer: %s", err) - return - } - re := regexp.MustCompile(`TracerPid:\s+([0-9]+)`) - sub := re.FindSubmatch(status) - if sub == nil { - t.Logf("couldn't find proc tracer PID") - return - } - if string(sub[1]) == "0" { - return - } - t.Skip("test will deadlock under a debugger") -} - -func TestDebugCall(t *testing.T) { - g, after := startDebugCallWorker(t) - defer after() - - // Inject a call into the debugCallWorker goroutine and test - // basic argument and result passing. - var args struct { - x int - yRet int - } - fn := func(x int) (yRet int) { - return x + 1 - } - args.x = 42 - if _, err := runtime.InjectDebugCall(g, fn, &args, debugCallTKill, false); err != nil { - t.Fatal(err) - } - if args.yRet != 43 { - t.Fatalf("want 43, got %d", args.yRet) - } -} - -func TestDebugCallLarge(t *testing.T) { - g, after := startDebugCallWorker(t) - defer after() - - // Inject a call with a large call frame. - const N = 128 - var args struct { - in [N]int - out [N]int - } - fn := func(in [N]int) (out [N]int) { - for i := range in { - out[i] = in[i] + 1 - } - return - } - var want [N]int - for i := range args.in { - args.in[i] = i - want[i] = i + 1 - } - if _, err := runtime.InjectDebugCall(g, fn, &args, debugCallTKill, false); err != nil { - t.Fatal(err) - } - if want != args.out { - t.Fatalf("want %v, got %v", want, args.out) - } -} - -func TestDebugCallGC(t *testing.T) { - g, after := startDebugCallWorker(t) - defer after() - - // Inject a call that performs a GC. - if _, err := runtime.InjectDebugCall(g, runtime.GC, nil, debugCallTKill, false); err != nil { - t.Fatal(err) - } -} - -func TestDebugCallGrowStack(t *testing.T) { - g, after := startDebugCallWorker(t) - defer after() - - // Inject a call that grows the stack. debugCallWorker checks - // for stack pointer breakage. - if _, err := runtime.InjectDebugCall(g, func() { growStack(nil) }, nil, debugCallTKill, false); err != nil { - t.Fatal(err) - } -} - -//go:nosplit -func debugCallUnsafePointWorker(gpp **runtime.G, ready, stop *uint32) { - // The nosplit causes this function to not contain safe-points - // except at calls. - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - *gpp = runtime.Getg() - - for atomic.LoadUint32(stop) == 0 { - atomic.StoreUint32(ready, 1) - } -} - -func TestDebugCallUnsafePoint(t *testing.T) { - skipUnderDebugger(t) - - // This can deadlock if there aren't enough threads or if a GC - // tries to interrupt an atomic loop (see issue #10958). - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(8)) - defer debug.SetGCPercent(debug.SetGCPercent(-1)) - - // Test that the runtime refuses call injection at unsafe points. - var g *runtime.G - var ready, stop uint32 - defer atomic.StoreUint32(&stop, 1) - go debugCallUnsafePointWorker(&g, &ready, &stop) - for atomic.LoadUint32(&ready) == 0 { - runtime.Gosched() - } - - _, err := runtime.InjectDebugCall(g, func() {}, nil, debugCallTKill, true) - if msg := "call not at safe point"; err == nil || err.Error() != msg { - t.Fatalf("want %q, got %s", msg, err) - } -} - -func TestDebugCallPanic(t *testing.T) { - skipUnderDebugger(t) - - // This can deadlock if there aren't enough threads. - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(8)) - - ready := make(chan *runtime.G) - var stop uint32 - defer atomic.StoreUint32(&stop, 1) - go func() { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - ready <- runtime.Getg() - for atomic.LoadUint32(&stop) == 0 { - } - }() - g := <-ready - - p, err := runtime.InjectDebugCall(g, func() { panic("test") }, nil, debugCallTKill, false) - if err != nil { - t.Fatal(err) - } - if ps, ok := p.(string); !ok || ps != "test" { - t.Fatalf("wanted panic %v, got %v", "test", p) - } -} diff --git a/libgo/go/runtime/debuglog_off.go b/libgo/go/runtime/debuglog_off.go index bb3e172..dd38156 100644 --- a/libgo/go/runtime/debuglog_off.go +++ b/libgo/go/runtime/debuglog_off.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !debuglog // +build !debuglog package runtime diff --git a/libgo/go/runtime/debuglog_on.go b/libgo/go/runtime/debuglog_on.go index 3d477e8..2fcdbe7 100644 --- a/libgo/go/runtime/debuglog_on.go +++ b/libgo/go/runtime/debuglog_on.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build debuglog // +build debuglog package runtime diff --git a/libgo/go/runtime/defer_test.go b/libgo/go/runtime/defer_test.go index 9a40ea1..fc96144 100644 --- a/libgo/go/runtime/defer_test.go +++ b/libgo/go/runtime/defer_test.go @@ -370,7 +370,7 @@ func g2() { defer ap.method2() defer ap.method1() ff1(ap, 1, 2, 3, 4, 5, 6, 7, 8, 9) - // Try to get the stack to be be moved by growing it too large, so + // Try to get the stack to be moved by growing it too large, so // existing stack-allocated defer becomes invalid. rec1(2000) } diff --git a/libgo/go/runtime/defs_windows_arm64.go b/libgo/go/runtime/defs_windows_arm64.go new file mode 100644 index 0000000..9ccce46 --- /dev/null +++ b/libgo/go/runtime/defs_windows_arm64.go @@ -0,0 +1,83 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +// NOTE(rsc): _CONTEXT_CONTROL is actually 0x400001 and should include PC, SP, and LR. +// However, empirically, LR doesn't come along on Windows 10 +// unless you also set _CONTEXT_INTEGER (0x400002). +// Without LR, we skip over the next-to-bottom function in profiles +// when the bottom function is frameless. +// So we set both here, to make a working _CONTEXT_CONTROL. +const _CONTEXT_CONTROL = 0x400003 + +type neon128 struct { + low uint64 + high int64 +} + +// See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-arm64_nt_context +type context struct { + contextflags uint32 + cpsr uint32 + x [31]uint64 // fp is x[29], lr is x[30] + xsp uint64 + pc uint64 + v [32]neon128 + fpcr uint32 + fpsr uint32 + bcr [8]uint32 + bvr [8]uint64 + wcr [2]uint32 + wvr [2]uint64 +} + +func (c *context) ip() uintptr { return uintptr(c.pc) } +func (c *context) sp() uintptr { return uintptr(c.xsp) } +func (c *context) lr() uintptr { return uintptr(c.x[30]) } + +func (c *context) set_ip(x uintptr) { c.pc = uint64(x) } +func (c *context) set_sp(x uintptr) { c.xsp = uint64(x) } +func (c *context) set_lr(x uintptr) { c.x[30] = uint64(x) } + +func dumpregs(r *context) { + print("r0 ", hex(r.x[0]), "\n") + print("r1 ", hex(r.x[1]), "\n") + print("r2 ", hex(r.x[2]), "\n") + print("r3 ", hex(r.x[3]), "\n") + print("r4 ", hex(r.x[4]), "\n") + print("r5 ", hex(r.x[5]), "\n") + print("r6 ", hex(r.x[6]), "\n") + print("r7 ", hex(r.x[7]), "\n") + print("r8 ", hex(r.x[8]), "\n") + print("r9 ", hex(r.x[9]), "\n") + print("r10 ", hex(r.x[10]), "\n") + print("r11 ", hex(r.x[11]), "\n") + print("r12 ", hex(r.x[12]), "\n") + print("r13 ", hex(r.x[13]), "\n") + print("r14 ", hex(r.x[14]), "\n") + print("r15 ", hex(r.x[15]), "\n") + print("r16 ", hex(r.x[16]), "\n") + print("r17 ", hex(r.x[17]), "\n") + print("r18 ", hex(r.x[18]), "\n") + print("r19 ", hex(r.x[19]), "\n") + print("r20 ", hex(r.x[20]), "\n") + print("r21 ", hex(r.x[21]), "\n") + print("r22 ", hex(r.x[22]), "\n") + print("r23 ", hex(r.x[23]), "\n") + print("r24 ", hex(r.x[24]), "\n") + print("r25 ", hex(r.x[25]), "\n") + print("r26 ", hex(r.x[26]), "\n") + print("r27 ", hex(r.x[27]), "\n") + print("r28 ", hex(r.x[28]), "\n") + print("r29 ", hex(r.x[29]), "\n") + print("lr ", hex(r.x[30]), "\n") + print("sp ", hex(r.xsp), "\n") + print("pc ", hex(r.pc), "\n") + print("cpsr ", hex(r.cpsr), "\n") +} + +func stackcheck() { + // TODO: not implemented on ARM +} diff --git a/libgo/go/runtime/env_posix.go b/libgo/go/runtime/env_posix.go index 48b9c4a3..8893c4a 100644 --- a/libgo/go/runtime/env_posix.go +++ b/libgo/go/runtime/env_posix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows || plan9 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris windows plan9 package runtime diff --git a/libgo/go/runtime/example_test.go b/libgo/go/runtime/example_test.go index 8dac9297..e7f8dbc 100644 --- a/libgo/go/runtime/example_test.go +++ b/libgo/go/runtime/example_test.go @@ -12,12 +12,15 @@ import ( func ExampleFrames() { c := func() { - // Ask runtime.Callers for up to 10 pcs, including runtime.Callers itself. + // Ask runtime.Callers for up to 10 PCs, including runtime.Callers itself. pc := make([]uintptr, 10) n := runtime.Callers(0, pc) if n == 0 { - // No pcs available. Stop now. - // This can happen if the first argument to runtime.Callers is large. + // No PCs available. This can happen if the first argument to + // runtime.Callers is large. + // + // Return now to avoid processing the zero Frame that would + // otherwise be returned by frames.Next below. return } @@ -25,9 +28,12 @@ func ExampleFrames() { frames := runtime.CallersFrames(pc) // Loop to get frames. - // A fixed number of pcs can expand to an indefinite number of Frames. + // A fixed number of PCs can expand to an indefinite number of Frames. for { frame, more := frames.Next() + + // Process this frame. + // // To keep this example's output stable // even if there are changes in the testing package, // stop unwinding when we leave package runtime. @@ -35,6 +41,8 @@ func ExampleFrames() { break } fmt.Printf("- more:%v | %s\n", more, frame.Function) + + // Check whether there are more frames to process after this one. if !more { break } diff --git a/libgo/go/runtime/export_debug_test.go b/libgo/go/runtime/export_debug_test.go deleted file mode 100644 index c1cc44f..0000000 --- a/libgo/go/runtime/export_debug_test.go +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore_for_gccgo -// +build amd64 -// +build linux - -package runtime - -import ( - "runtime/internal/sys" - "unsafe" -) - -// InjectDebugCall injects a debugger call to fn into g. args must be -// a pointer to a valid call frame (including arguments and return -// space) for fn, or nil. tkill must be a function that will send -// SIGTRAP to thread ID tid. gp must be locked to its OS thread and -// running. -// -// On success, InjectDebugCall returns the panic value of fn or nil. -// If fn did not panic, its results will be available in args. -func InjectDebugCall(gp *g, fn, args interface{}, tkill func(tid int) error, returnOnUnsafePoint bool) (interface{}, error) { - if gp.lockedm == 0 { - return nil, plainError("goroutine not locked to thread") - } - - tid := int(gp.lockedm.ptr().procid) - if tid == 0 { - return nil, plainError("missing tid") - } - - f := efaceOf(&fn) - if f._type == nil || f._type.kind&kindMask != kindFunc { - return nil, plainError("fn must be a function") - } - fv := (*funcval)(f.data) - - a := efaceOf(&args) - if a._type != nil && a._type.kind&kindMask != kindPtr { - return nil, plainError("args must be a pointer or nil") - } - argp := a.data - var argSize uintptr - if argp != nil { - argSize = (*ptrtype)(unsafe.Pointer(a._type)).elem.size - } - - h := new(debugCallHandler) - h.gp = gp - // gp may not be running right now, but we can still get the M - // it will run on since it's locked. - h.mp = gp.lockedm.ptr() - h.fv, h.argp, h.argSize = fv, argp, argSize - h.handleF = h.handle // Avoid allocating closure during signal - - defer func() { testSigtrap = nil }() - for i := 0; ; i++ { - testSigtrap = h.inject - noteclear(&h.done) - h.err = "" - - if err := tkill(tid); err != nil { - return nil, err - } - // Wait for completion. - notetsleepg(&h.done, -1) - if h.err != "" { - switch h.err { - case "call not at safe point": - if returnOnUnsafePoint { - // This is for TestDebugCallUnsafePoint. - return nil, h.err - } - fallthrough - case "retry _Grunnable", "executing on Go runtime stack", "call from within the Go runtime": - // These are transient states. Try to get out of them. - if i < 100 { - usleep(100) - Gosched() - continue - } - } - return nil, h.err - } - return h.panic, nil - } -} - -type debugCallHandler struct { - gp *g - mp *m - fv *funcval - argp unsafe.Pointer - argSize uintptr - panic interface{} - - handleF func(info *siginfo, ctxt *sigctxt, gp2 *g) bool - - err plainError - done note - savedRegs sigcontext - savedFP fpstate1 -} - -func (h *debugCallHandler) inject(info *siginfo, ctxt *sigctxt, gp2 *g) bool { - switch h.gp.atomicstatus { - case _Grunning: - if getg().m != h.mp { - println("trap on wrong M", getg().m, h.mp) - return false - } - // Push current PC on the stack. - rsp := ctxt.rsp() - sys.PtrSize - *(*uint64)(unsafe.Pointer(uintptr(rsp))) = ctxt.rip() - ctxt.set_rsp(rsp) - // Write the argument frame size. - *(*uintptr)(unsafe.Pointer(uintptr(rsp - 16))) = h.argSize - // Save current registers. - h.savedRegs = *ctxt.regs() - h.savedFP = *h.savedRegs.fpstate - h.savedRegs.fpstate = nil - // Set PC to debugCallV1. - ctxt.set_rip(uint64(funcPC(debugCallV1))) - // Call injected. Switch to the debugCall protocol. - testSigtrap = h.handleF - case _Grunnable: - // Ask InjectDebugCall to pause for a bit and then try - // again to interrupt this goroutine. - h.err = plainError("retry _Grunnable") - notewakeup(&h.done) - default: - h.err = plainError("goroutine in unexpected state at call inject") - notewakeup(&h.done) - } - // Resume execution. - return true -} - -func (h *debugCallHandler) handle(info *siginfo, ctxt *sigctxt, gp2 *g) bool { - // Sanity check. - if getg().m != h.mp { - println("trap on wrong M", getg().m, h.mp) - return false - } - f := findfunc(uintptr(ctxt.rip())) - if !(hasPrefix(funcname(f), "runtime.debugCall") || hasPrefix(funcname(f), "debugCall")) { - println("trap in unknown function", funcname(f)) - return false - } - if *(*byte)(unsafe.Pointer(uintptr(ctxt.rip() - 1))) != 0xcc { - println("trap at non-INT3 instruction pc =", hex(ctxt.rip())) - return false - } - - switch status := ctxt.rax(); status { - case 0: - // Frame is ready. Copy the arguments to the frame. - sp := ctxt.rsp() - memmove(unsafe.Pointer(uintptr(sp)), h.argp, h.argSize) - // Push return PC. - sp -= sys.PtrSize - ctxt.set_rsp(sp) - *(*uint64)(unsafe.Pointer(uintptr(sp))) = ctxt.rip() - // Set PC to call and context register. - ctxt.set_rip(uint64(h.fv.fn)) - ctxt.regs().rcx = uint64(uintptr(unsafe.Pointer(h.fv))) - case 1: - // Function returned. Copy frame back out. - sp := ctxt.rsp() - memmove(h.argp, unsafe.Pointer(uintptr(sp)), h.argSize) - case 2: - // Function panicked. Copy panic out. - sp := ctxt.rsp() - memmove(unsafe.Pointer(&h.panic), unsafe.Pointer(uintptr(sp)), 2*sys.PtrSize) - case 8: - // Call isn't safe. Get the reason. - sp := ctxt.rsp() - reason := *(*string)(unsafe.Pointer(uintptr(sp))) - h.err = plainError(reason) - // Don't wake h.done. We need to transition to status 16 first. - case 16: - // Restore all registers except RIP and RSP. - rip, rsp := ctxt.rip(), ctxt.rsp() - fp := ctxt.regs().fpstate - *ctxt.regs() = h.savedRegs - ctxt.regs().fpstate = fp - *fp = h.savedFP - ctxt.set_rip(rip) - ctxt.set_rsp(rsp) - // Done - notewakeup(&h.done) - default: - h.err = plainError("unexpected debugCallV1 status") - notewakeup(&h.done) - } - // Resume execution. - return true -} diff --git a/libgo/go/runtime/export_mmap_test.go b/libgo/go/runtime/export_mmap_test.go index 000948b..aa498bb 100644 --- a/libgo/go/runtime/export_mmap_test.go +++ b/libgo/go/runtime/export_mmap_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris // Export guts for testing. diff --git a/libgo/go/runtime/export_pipe2_test.go b/libgo/go/runtime/export_pipe2_test.go index 209c6b1..22ac4b7 100644 --- a/libgo/go/runtime/export_pipe2_test.go +++ b/libgo/go/runtime/export_pipe2_test.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build freebsd hurd linux netbsd openbsd solaris +//go:build dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris +// +build dragonfly freebsd hurd linux netbsd openbsd solaris package runtime diff --git a/libgo/go/runtime/export_pipe_test.go b/libgo/go/runtime/export_pipe_test.go index 8f66770..a0c6c04 100644 --- a/libgo/go/runtime/export_pipe_test.go +++ b/libgo/go/runtime/export_pipe_test.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly +//go:build aix || darwin +// +build aix darwin package runtime diff --git a/libgo/go/runtime/export_test.go b/libgo/go/runtime/export_test.go index 1455c22..5255a70 100644 --- a/libgo/go/runtime/export_test.go +++ b/libgo/go/runtime/export_test.go @@ -46,6 +46,14 @@ var NetpollGenericInit = netpollGenericInit var Memmove = memmove var MemclrNoHeapPointers = memclrNoHeapPointers +var LockPartialOrder = lockPartialOrder + +type LockRank lockRank + +func (l LockRank) String() string { + return lockRank(l).String() +} + const PreemptMSupported = preemptMSupported type LFNode struct { @@ -136,35 +144,47 @@ func RunSchedLocalQueueStealTest() { } } +// Temporary to enable register ABI bringup. +// TODO(register args): convert back to local variables in RunSchedLocalQueueEmptyTest that +// get passed to the "go" stmts there. +var RunSchedLocalQueueEmptyState struct { + done chan bool + ready *uint32 + p *p +} + func RunSchedLocalQueueEmptyTest(iters int) { // Test that runq is not spuriously reported as empty. // Runq emptiness affects scheduling decisions and spurious emptiness // can lead to underutilization (both runnable Gs and idle Ps coexist // for arbitrary long time). done := make(chan bool, 1) - _p_ := new(p) + RunSchedLocalQueueEmptyState.done = done + p := new(p) + RunSchedLocalQueueEmptyState.p = p gs := make([]g, 2) ready := new(uint32) + RunSchedLocalQueueEmptyState.ready = ready for i := 0; i < iters; i++ { *ready = 0 next0 := (i & 1) == 0 next1 := (i & 2) == 0 - runqput(_p_, &gs[0], next0) - go func(done chan bool, p *p, ready *uint32, next0, next1 bool) { - for atomic.Xadd(ready, 1); atomic.Load(ready) != 2; { + runqput(p, &gs[0], next0) + go func() { + for atomic.Xadd(RunSchedLocalQueueEmptyState.ready, 1); atomic.Load(RunSchedLocalQueueEmptyState.ready) != 2; { } - if runqempty(p) { - println("next:", next0, next1) + if runqempty(RunSchedLocalQueueEmptyState.p) { + //println("next:", next0, next1) throw("queue is empty") } - done <- true - }(done, _p_, ready, next0, next1) + RunSchedLocalQueueEmptyState.done <- true + }() for atomic.Xadd(ready, 1); atomic.Load(ready) != 2; { } - runqput(_p_, &gs[1], next1) - runqget(_p_) + runqput(p, &gs[1], next1) + runqget(p) <-done - runqget(_p_) + runqget(p) } } @@ -195,8 +215,6 @@ var HashLoad = &hashLoad // return //} -type Uintreg sys.Uintreg - var Open = open var Close = closefd var Read = read @@ -370,7 +388,7 @@ func ReadMemStatsSlow() (base, slow MemStats) { bySize[i].Mallocs += uint64(m.smallFreeCount[i]) smallFree += uint64(m.smallFreeCount[i]) * uint64(class_to_size[i]) } - slow.Frees += memstats.tinyallocs + uint64(m.largeFreeCount) + slow.Frees += uint64(m.tinyAllocCount) + uint64(m.largeFreeCount) slow.Mallocs += slow.Frees slow.TotalAlloc = slow.Alloc + uint64(m.largeFree) + smallFree @@ -393,9 +411,6 @@ func ReadMemStatsSlow() (base, slow MemStats) { slow.HeapReleased += uint64(pg) * pageSize } - // Unused space in the current arena also counts as released space. - slow.HeapReleased += uint64(mheap_.curArena.end - mheap_.curArena.base) - getg().m.mallocing-- }) @@ -1127,31 +1142,6 @@ func SemNwait(addr *uint32) uint32 { return atomic.Load(&root.nwait) } -// MapHashCheck computes the hash of the key k for the map m, twice. -// Method 1 uses the built-in hasher for the map. -// Method 2 uses the typehash function (the one used by reflect). -// Returns the two hash values, which should always be equal. -func MapHashCheck(m interface{}, k interface{}) (uintptr, uintptr) { - // Unpack m. - mt := (*maptype)(unsafe.Pointer(efaceOf(&m)._type)) - mh := (*hmap)(efaceOf(&m).data) - - // Unpack k. - kt := efaceOf(&k)._type - var p unsafe.Pointer - if isDirectIface(kt) { - q := efaceOf(&k).data - p = unsafe.Pointer(&q) - } else { - p = efaceOf(&k).data - } - - // Compute the hash functions. - x := mt.hasher(noescape(p), uintptr(mh.hash0)) - y := typehash(kt, noescape(p), uintptr(mh.hash0)) - return x, y -} - // mspan wrapper for testing. //go:notinheap type MSpan mspan @@ -1210,3 +1200,28 @@ func (th *TimeHistogram) Record(duration int64) { } var Pusestackmaps = &usestackmaps + +func FinalizerGAsleep() bool { + lock(&finlock) + result := fingwait + unlock(&finlock) + return result +} + +// For GCTestIsReachable, it's important that we do this as a call so +// escape analysis can see through it. +func GCTestIsReachable(ptrs ...unsafe.Pointer) (mask uint64) { + return gcTestIsReachable(ptrs...) +} + +// For GCTestPointerClass, it's important that we do this as a call so +// escape analysis can see through it. +// +// This is nosplit because gcTestPointerClass is. +// +//go:nosplit +func GCTestPointerClass(p unsafe.Pointer) string { + return gcTestPointerClass(p) +} + +const Raceenabled = raceenabled diff --git a/libgo/go/runtime/export_unix_test.go b/libgo/go/runtime/export_unix_test.go index 801786d..180af01 100644 --- a/libgo/go/runtime/export_unix_test.go +++ b/libgo/go/runtime/export_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package runtime diff --git a/libgo/go/runtime/extern.go b/libgo/go/runtime/extern.go index 8d10c85..0d7f357 100644 --- a/libgo/go/runtime/extern.go +++ b/libgo/go/runtime/extern.go @@ -110,8 +110,6 @@ It is a comma-separated list of name=val pairs setting these named variables: with a trivial allocator that obtains memory from the operating system and never reclaims any memory. - scavenge: scavenge=1 enables debugging mode of heap scavenger. - scavtrace: setting scavtrace=1 causes the runtime to emit a single line to standard error, roughly once per GC cycle, summarizing the amount of work done by the scavenger as well as the total amount of memory returned to the operating system @@ -213,6 +211,8 @@ func Caller(skip int) (pc uintptr, file string, line int, ok bool) // program counter adjustment. func Callers(skip int, pc []uintptr) int +var defaultGOROOT string // set by cmd/link + // GOROOT returns the root of the Go tree. It uses the // GOROOT environment variable, if set at process start, // or else the root used during the Go build. @@ -221,14 +221,24 @@ func GOROOT() string { if s != "" { return s } - return sys.DefaultGoroot + return defaultGOROOT } +// buildVersion is the Go tree's version string at build time. +// +// If any GOEXPERIMENTs are set to non-default values, it will include +// "X:<GOEXPERIMENT>". +// +// This is set by the linker. +// +// This is accessed by "go version <binary>". +var buildVersion string + // Version returns the Go tree's version string. // It is either the commit hash and date at the time of the build or, // when possible, a release tag like "go1.3". func Version() string { - return sys.TheVersion + return buildVersion } // GOOS is the running program's operating system target: diff --git a/libgo/go/runtime/gc_test.go b/libgo/go/runtime/gc_test.go index cde2e14..bb5e1ae 100644 --- a/libgo/go/runtime/gc_test.go +++ b/libgo/go/runtime/gc_test.go @@ -208,6 +208,126 @@ func TestGcZombieReporting(t *testing.T) { } } +/* + +func TestGCTestMoveStackOnNextCall(t *testing.T) { + t.Parallel() + var onStack int + // GCTestMoveStackOnNextCall can fail in rare cases if there's + // a preemption. This won't happen many times in quick + // succession, so just retry a few times. + for retry := 0; retry < 5; retry++ { + runtime.GCTestMoveStackOnNextCall() + if moveStackCheck(t, &onStack, uintptr(unsafe.Pointer(&onStack))) { + // Passed. + return + } + } + t.Fatal("stack did not move") +} + +// This must not be inlined because the point is to force a stack +// growth check and move the stack. +// +//go:noinline +func moveStackCheck(t *testing.T, new *int, old uintptr) bool { + // new should have been updated by the stack move; + // old should not have. + + // Capture new's value before doing anything that could + // further move the stack. + new2 := uintptr(unsafe.Pointer(new)) + + t.Logf("old stack pointer %x, new stack pointer %x", old, new2) + if new2 == old { + // Check that we didn't screw up the test's escape analysis. + if cls := runtime.GCTestPointerClass(unsafe.Pointer(new)); cls != "stack" { + t.Fatalf("test bug: new (%#x) should be a stack pointer, not %s", new2, cls) + } + // This was a real failure. + return false + } + return true +} + +func TestGCTestMoveStackRepeatedly(t *testing.T) { + // Move the stack repeatedly to make sure we're not doubling + // it each time. + for i := 0; i < 100; i++ { + runtime.GCTestMoveStackOnNextCall() + moveStack1(false) + } +} + +//go:noinline +func moveStack1(x bool) { + // Make sure this function doesn't get auto-nosplit. + if x { + println("x") + } +} + +*/ + +func TestGCTestIsReachable(t *testing.T) { + var all, half []unsafe.Pointer + var want uint64 + for i := 0; i < 16; i++ { + // The tiny allocator muddies things, so we use a + // scannable type. + p := unsafe.Pointer(new(*int)) + all = append(all, p) + if i%2 == 0 { + half = append(half, p) + want |= 1 << i + } + } + + got := runtime.GCTestIsReachable(all...) + if want != got { + // gccgo's conservative GC means that we sometimes + // keep data we shouldn't. + if runtime.Compiler == "gccgo" { + if ((got ^ want) & want) != 0 { + t.Fatalf("some expected bits not set: want %b, got %b", want, got) + } + } else { + t.Fatalf("did not get expected reachable set; want %b, got %b", want, got) + } + } + runtime.KeepAlive(half) +} + +var pointerClassSink *int +var pointerClassData = 42 + +func TestGCTestPointerClass(t *testing.T) { + if runtime.Compiler == "gccgo" { + // gofrontend escape analysis doesn't handle passing + // &onStack through a closure. + t.Skip("skipping for gofrontend") + } + + t.Parallel() + check := func(p unsafe.Pointer, want string) { + t.Helper() + got := runtime.GCTestPointerClass(p) + if got != want { + // Convert the pointer to a uintptr to avoid + // escaping it. + t.Errorf("for %#x, want class %s, got %s", uintptr(p), want, got) + } + } + var onStack int + var notOnStack int + pointerClassSink = ¬OnStack + check(unsafe.Pointer(&onStack), "stack") + check(unsafe.Pointer(¬OnStack), "heap") + check(unsafe.Pointer(&pointerClassSink), "bss") + check(unsafe.Pointer(&pointerClassData), "data") + check(nil, "other") +} + func BenchmarkSetTypePtr(b *testing.B) { benchSetType(b, new(*byte)) } diff --git a/libgo/go/runtime/hash32.go b/libgo/go/runtime/hash32.go index 89efc1c..58ae38b 100644 --- a/libgo/go/runtime/hash32.go +++ b/libgo/go/runtime/hash32.go @@ -3,10 +3,10 @@ // license that can be found in the LICENSE file. // Hashing algorithm inspired by -// xxhash: https://code.google.com/p/xxhash/ -// cityhash: https://code.google.com/p/cityhash/ +// wyhash: https://github.com/wangyi-fudan/wyhash/blob/ceb019b530e2c1c14d70b79bfa2bc49de7d95bc1/Modern%20Non-Cryptographic%20Hash%20Function%20and%20Pseudorandom%20Number%20Generator.pdf -// +build 386 arm armbe m68k mips mipsle nios2 ppc riscv s390 sh shbe sparc +//go:build 386 || arm || mips || mipsle || armbe || m68k || nios2 || ppc || riscv || s390 || sh || shbe || sparc +// +build 386 arm mips mipsle armbe m68k nios2 ppc riscv s390 sh shbe sparc package runtime @@ -16,104 +16,54 @@ import "unsafe" // //go:linkname memhash -const ( - // Constants for multiplication: four random odd 32-bit numbers. - m1 = 3168982561 - m2 = 3339683297 - m3 = 832293441 - m4 = 2336365089 -) +func memhash32(p unsafe.Pointer, seed uintptr) uintptr { + a, b := mix32(uint32(seed), uint32(4^hashkey[0])) + t := readUnaligned32(p) + a ^= t + b ^= t + a, b = mix32(a, b) + a, b = mix32(a, b) + return uintptr(a ^ b) +} + +func memhash64(p unsafe.Pointer, seed uintptr) uintptr { + a, b := mix32(uint32(seed), uint32(8^hashkey[0])) + a ^= readUnaligned32(p) + b ^= readUnaligned32(add(p, 4)) + a, b = mix32(a, b) + a, b = mix32(a, b) + return uintptr(a ^ b) +} func memhash(p unsafe.Pointer, seed, s uintptr) uintptr { if GOARCH == "386" && GOOS != "nacl" && useAeshash { return aeshash(p, seed, s) } - h := uint32(seed + s*hashkey[0]) -tail: - switch { - case s == 0: - case s < 4: - h ^= uint32(*(*byte)(p)) - h ^= uint32(*(*byte)(add(p, s>>1))) << 8 - h ^= uint32(*(*byte)(add(p, s-1))) << 16 - h = rotl_15(h*m1) * m2 - case s == 4: - h ^= readUnaligned32(p) - h = rotl_15(h*m1) * m2 - case s <= 8: - h ^= readUnaligned32(p) - h = rotl_15(h*m1) * m2 - h ^= readUnaligned32(add(p, s-4)) - h = rotl_15(h*m1) * m2 - case s <= 16: - h ^= readUnaligned32(p) - h = rotl_15(h*m1) * m2 - h ^= readUnaligned32(add(p, 4)) - h = rotl_15(h*m1) * m2 - h ^= readUnaligned32(add(p, s-8)) - h = rotl_15(h*m1) * m2 - h ^= readUnaligned32(add(p, s-4)) - h = rotl_15(h*m1) * m2 - default: - v1 := h - v2 := uint32(seed * hashkey[1]) - v3 := uint32(seed * hashkey[2]) - v4 := uint32(seed * hashkey[3]) - for s >= 16 { - v1 ^= readUnaligned32(p) - v1 = rotl_15(v1*m1) * m2 - p = add(p, 4) - v2 ^= readUnaligned32(p) - v2 = rotl_15(v2*m2) * m3 - p = add(p, 4) - v3 ^= readUnaligned32(p) - v3 = rotl_15(v3*m3) * m4 - p = add(p, 4) - v4 ^= readUnaligned32(p) - v4 = rotl_15(v4*m4) * m1 - p = add(p, 4) - s -= 16 - } - h = v1 ^ v2 ^ v3 ^ v4 - goto tail + a, b := mix32(uint32(seed), uint32(s^hashkey[0])) + if s == 0 { + return uintptr(a ^ b) } - h ^= h >> 17 - h *= m3 - h ^= h >> 13 - h *= m4 - h ^= h >> 16 - return uintptr(h) -} - -func memhash32(p unsafe.Pointer, seed uintptr) uintptr { - h := uint32(seed + 4*hashkey[0]) - h ^= readUnaligned32(p) - h = rotl_15(h*m1) * m2 - h ^= h >> 17 - h *= m3 - h ^= h >> 13 - h *= m4 - h ^= h >> 16 - return uintptr(h) -} - -func memhash64(p unsafe.Pointer, seed uintptr) uintptr { - h := uint32(seed + 8*hashkey[0]) - h ^= readUnaligned32(p) - h = rotl_15(h*m1) * m2 - h ^= readUnaligned32(add(p, 4)) - h = rotl_15(h*m1) * m2 - h ^= h >> 17 - h *= m3 - h ^= h >> 13 - h *= m4 - h ^= h >> 16 - return uintptr(h) + for ; s > 8; s -= 8 { + a ^= readUnaligned32(p) + b ^= readUnaligned32(add(p, 4)) + a, b = mix32(a, b) + p = add(p, 8) + } + if s >= 4 { + a ^= readUnaligned32(p) + b ^= readUnaligned32(add(p, s-4)) + } else { + t := uint32(*(*byte)(p)) + t |= uint32(*(*byte)(add(p, s>>1))) << 8 + t |= uint32(*(*byte)(add(p, s-1))) << 16 + b ^= t + } + a, b = mix32(a, b) + a, b = mix32(a, b) + return uintptr(a ^ b) } -// Note: in order to get the compiler to issue rotl instructions, we -// need to constant fold the shift amount by hand. -// TODO: convince the compiler to issue rotl instructions after inlining. -func rotl_15(x uint32) uint32 { - return (x << 15) | (x >> (32 - 15)) +func mix32(a, b uint32) (uint32, uint32) { + c := uint64(a^uint32(hashkey[1])) * uint64(b^uint32(hashkey[2])) + return uint32(c), uint32(c >> 32) } diff --git a/libgo/go/runtime/hash64.go b/libgo/go/runtime/hash64.go index 704bbe6..4b32d51 100644 --- a/libgo/go/runtime/hash64.go +++ b/libgo/go/runtime/hash64.go @@ -3,113 +3,98 @@ // license that can be found in the LICENSE file. // Hashing algorithm inspired by -// xxhash: https://code.google.com/p/xxhash/ -// cityhash: https://code.google.com/p/cityhash/ +// wyhash: https://github.com/wangyi-fudan/wyhash +//go:build amd64 || arm64 || mips64 || mips64le || ppc64 || ppc64le || riscv64 || s390x || wasm || alpha || amd64p32 || arm64be || ia64 || mips64p32 || mips64p32le || sparc64 // +build amd64 arm64 mips64 mips64le ppc64 ppc64le riscv64 s390x wasm alpha amd64p32 arm64be ia64 mips64p32 mips64p32le sparc64 package runtime -import "unsafe" +import ( + "runtime/internal/math" + "unsafe" +) // For gccgo, use go:linkname to export compiler-called functions. // //go:linkname memhash const ( - // Constants for multiplication: four random odd 64-bit numbers. - m1 = 16877499708836156737 - m2 = 2820277070424839065 - m3 = 9497967016996688599 - m4 = 15839092249703872147 + m1 = 0xa0761d6478bd642f + m2 = 0xe7037ed1a0b428db + m3 = 0x8ebc6af09c88c6e3 + m4 = 0x589965cc75374cc3 + m5 = 0x1d8e4e27c47d124f ) func memhash(p unsafe.Pointer, seed, s uintptr) uintptr { if (GOARCH == "amd64" || GOARCH == "arm64") && useAeshash { return aeshash(p, seed, s) } - h := uint64(seed + s*hashkey[0]) -tail: + var a, b uintptr + seed ^= hashkey[0] ^ m1 switch { case s == 0: + return seed case s < 4: - h ^= uint64(*(*byte)(p)) - h ^= uint64(*(*byte)(add(p, s>>1))) << 8 - h ^= uint64(*(*byte)(add(p, s-1))) << 16 - h = rotl_31(h*m1) * m2 - case s <= 8: - h ^= uint64(readUnaligned32(p)) - h ^= uint64(readUnaligned32(add(p, s-4))) << 32 - h = rotl_31(h*m1) * m2 + a = uintptr(*(*byte)(p)) + a |= uintptr(*(*byte)(add(p, s>>1))) << 8 + a |= uintptr(*(*byte)(add(p, s-1))) << 16 + case s == 4: + a = r4(p) + b = a + case s < 8: + a = r4(p) + b = r4(add(p, s-4)) + case s == 8: + a = r8(p) + b = a case s <= 16: - h ^= readUnaligned64(p) - h = rotl_31(h*m1) * m2 - h ^= readUnaligned64(add(p, s-8)) - h = rotl_31(h*m1) * m2 - case s <= 32: - h ^= readUnaligned64(p) - h = rotl_31(h*m1) * m2 - h ^= readUnaligned64(add(p, 8)) - h = rotl_31(h*m1) * m2 - h ^= readUnaligned64(add(p, s-16)) - h = rotl_31(h*m1) * m2 - h ^= readUnaligned64(add(p, s-8)) - h = rotl_31(h*m1) * m2 + a = r8(p) + b = r8(add(p, s-8)) default: - v1 := h - v2 := uint64(seed * hashkey[1]) - v3 := uint64(seed * hashkey[2]) - v4 := uint64(seed * hashkey[3]) - for s >= 32 { - v1 ^= readUnaligned64(p) - v1 = rotl_31(v1*m1) * m2 - p = add(p, 8) - v2 ^= readUnaligned64(p) - v2 = rotl_31(v2*m2) * m3 - p = add(p, 8) - v3 ^= readUnaligned64(p) - v3 = rotl_31(v3*m3) * m4 - p = add(p, 8) - v4 ^= readUnaligned64(p) - v4 = rotl_31(v4*m4) * m1 - p = add(p, 8) - s -= 32 + l := s + if l > 48 { + seed1 := seed + seed2 := seed + for ; l > 48; l -= 48 { + seed = mix(r8(p)^m2, r8(add(p, 8))^seed) + seed1 = mix(r8(add(p, 16))^m3, r8(add(p, 24))^seed1) + seed2 = mix(r8(add(p, 32))^m4, r8(add(p, 40))^seed2) + p = add(p, 48) + } + seed ^= seed1 ^ seed2 + } + for ; l > 16; l -= 16 { + seed = mix(r8(p)^m2, r8(add(p, 8))^seed) + p = add(p, 16) } - h = v1 ^ v2 ^ v3 ^ v4 - goto tail + a = r8(add(p, l-16)) + b = r8(add(p, l-8)) } - h ^= h >> 29 - h *= m3 - h ^= h >> 32 - return uintptr(h) + return mix(m5^s, mix(a^m2, b^seed)) } func memhash32(p unsafe.Pointer, seed uintptr) uintptr { - h := uint64(seed + 4*hashkey[0]) - v := uint64(readUnaligned32(p)) - h ^= v - h ^= v << 32 - h = rotl_31(h*m1) * m2 - h ^= h >> 29 - h *= m3 - h ^= h >> 32 - return uintptr(h) + a := r4(p) + return mix(m5^4, mix(a^m2, a^seed^hashkey[0]^m1)) } func memhash64(p unsafe.Pointer, seed uintptr) uintptr { - h := uint64(seed + 8*hashkey[0]) - h ^= uint64(readUnaligned32(p)) | uint64(readUnaligned32(add(p, 4)))<<32 - h = rotl_31(h*m1) * m2 - h ^= h >> 29 - h *= m3 - h ^= h >> 32 - return uintptr(h) + a := r8(p) + return mix(m5^8, mix(a^m2, a^seed^hashkey[0]^m1)) +} + +func mix(a, b uintptr) uintptr { + hi, lo := math.Mul64(uint64(a), uint64(b)) + return uintptr(hi ^ lo) +} + +func r4(p unsafe.Pointer) uintptr { + return uintptr(readUnaligned32(p)) } -// Note: in order to get the compiler to issue rotl instructions, we -// need to constant fold the shift amount by hand. -// TODO: convince the compiler to issue rotl instructions after inlining. -func rotl_31(x uint64) uint64 { - return (x << 31) | (x >> (64 - 31)) +func r8(p unsafe.Pointer) uintptr { + return uintptr(readUnaligned64(p)) } diff --git a/libgo/go/runtime/hash_test.go b/libgo/go/runtime/hash_test.go index 60a8601..753b129 100644 --- a/libgo/go/runtime/hash_test.go +++ b/libgo/go/runtime/hash_test.go @@ -8,7 +8,6 @@ import ( "fmt" "math" "math/rand" - "reflect" . "runtime" "strings" "testing" @@ -49,54 +48,6 @@ func TestMemHash64Equality(t *testing.T) { } } -func TestCompilerVsRuntimeHash(t *testing.T) { - // Test to make sure the compiler's hash function and the runtime's hash function agree. - // See issue 37716. - for _, m := range []interface{}{ - map[bool]int{}, - map[int8]int{}, - map[uint8]int{}, - map[int16]int{}, - map[uint16]int{}, - map[int32]int{}, - map[uint32]int{}, - map[int64]int{}, - map[uint64]int{}, - map[int]int{}, - map[uint]int{}, - map[uintptr]int{}, - map[*byte]int{}, - map[chan int]int{}, - map[unsafe.Pointer]int{}, - map[float32]int{}, - map[float64]int{}, - map[complex64]int{}, - map[complex128]int{}, - map[string]int{}, - //map[interface{}]int{}, - //map[interface{F()}]int{}, - map[[8]uint64]int{}, - map[[8]string]int{}, - map[struct{ a, b, c, d int32 }]int{}, // Note: tests AMEM128 - map[struct{ a, b, _, d int32 }]int{}, - map[struct { - a, b int32 - c float32 - d, e [8]byte - }]int{}, - map[struct { - a int16 - b int64 - }]int{}, - } { - k := reflect.New(reflect.TypeOf(m).Key()).Elem().Interface() // the zero key - x, y := MapHashCheck(m, k) - if x != y { - t.Errorf("hashes did not match (%x vs %x) for map %T", x, y, m) - } - } -} - // Smhasher is a torture test for hash functions. // https://code.google.com/p/smhasher/ // This code is a port of some of the Smhasher tests to Go. diff --git a/libgo/go/runtime/heapdump.go b/libgo/go/runtime/heapdump.go index f3f7382..171acb8 100644 --- a/libgo/go/runtime/heapdump.go +++ b/libgo/go/runtime/heapdump.go @@ -294,9 +294,10 @@ func dumpgoroutine(gp *g) { } func dumpgs() { + assertWorldStopped() + // goroutines & stacks - for i := 0; uintptr(i) < allglen; i++ { - gp := allgs[i] + forEachG(func(gp *g) { status := readgstatus(gp) // The world is stopped so gp will not be in a scan state. switch status { default: @@ -309,7 +310,7 @@ func dumpgs() { _Gwaiting: dumpgoroutine(gp) } - } + }) } func finq_callback(fn *funcval, obj unsafe.Pointer, ft *functype, ot *ptrtype) { @@ -409,7 +410,7 @@ func dumpparams() { dumpint(uint64(arenaStart)) dumpint(uint64(arenaEnd)) dumpstr(sys.GOARCH) - dumpstr(sys.Goexperiment) + dumpstr(buildVersion) dumpint(uint64(ncpu)) } diff --git a/libgo/go/runtime/histogram.go b/libgo/go/runtime/histogram.go index da4910d..0cccbcc 100644 --- a/libgo/go/runtime/histogram.go +++ b/libgo/go/runtime/histogram.go @@ -81,6 +81,10 @@ type timeHistogram struct { } // record adds the given duration to the distribution. +// +// Disallow preemptions and stack growths because this function +// may run in sensitive locations. +//go:nosplit func (h *timeHistogram) record(duration int64) { if duration < 0 { atomic.Xadd64(&h.underflow, 1) diff --git a/libgo/go/runtime/internal/math/math.go b/libgo/go/runtime/internal/math/math.go index 5385f5d..b6bd12d 100644 --- a/libgo/go/runtime/internal/math/math.go +++ b/libgo/go/runtime/internal/math/math.go @@ -17,3 +17,24 @@ func MulUintptr(a, b uintptr) (uintptr, bool) { overflow := b > MaxUintptr/a return a * b, overflow } + +// Mul64 returns the 128-bit product of x and y: (hi, lo) = x * y +// with the product bits' upper half returned in hi and the lower +// half returned in lo. +// This is a copy from math/bits.Mul64 +// On supported platforms this is an intrinsic lowered by the compiler. +func Mul64(x, y uint64) (hi, lo uint64) { + const mask32 = 1<<32 - 1 + x0 := x & mask32 + x1 := x >> 32 + y0 := y & mask32 + y1 := y >> 32 + w0 := x0 * y0 + t := x1*y0 + w0>>32 + w1 := t & mask32 + w2 := t >> 32 + w1 += x0 * y1 + hi = x1*y1 + w2 + w1>>32 + lo = x * y + return +} diff --git a/libgo/go/runtime/internal/sys/arch.go b/libgo/go/runtime/internal/sys/arch.go new file mode 100644 index 0000000..7e09c10 --- /dev/null +++ b/libgo/go/runtime/internal/sys/arch.go @@ -0,0 +1,41 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sys + +type ArchFamilyType int + +// PtrSize is the size of a pointer in bytes - unsafe.Sizeof(uintptr(0)) but as an ideal constant. +// It is also the size of the machine's native word size (that is, 4 on 32-bit systems, 8 on 64-bit). +const PtrSize = 4 << (^uintptr(0) >> 63) + +// AIX requires a larger stack for syscalls. +const StackGuardMultiplier = StackGuardMultiplierDefault*(1-GoosAix) + 2*GoosAix + +// ArchFamily is the architecture family (AMD64, ARM, ...) +const ArchFamily ArchFamilyType = _ArchFamily + +// BigEndian reports whether the architecture is big-endian. +const BigEndian = _BigEndian + +// DefaultPhysPageSize is the default physical page size. +const DefaultPhysPageSize = _DefaultPhysPageSize + +// PCQuantum is the minimal unit for a program counter (1 on x86, 4 on most other systems). +// The various PC tables record PC deltas pre-divided by PCQuantum. +const PCQuantum = _PCQuantum + +// Int64Align is the required alignment for a 64-bit integer (4 on 32-bit systems, 8 on 64-bit). +const Int64Align = _Int64Align + +// MinFrameSize is the size of the system-reserved words at the bottom +// of a frame (just above the architectural stack pointer). +// It is zero on x86 and PtrSize on most non-x86 (LR-based) systems. +// On PowerPC it is larger, to cover three more reserved words: +// the compiler word, the link editor word, and the TOC save word. +const MinFrameSize = _MinFrameSize + +// StackAlign is the required alignment of the SP register. +// The stack must be at least word aligned, but some architectures require more. +const StackAlign = _StackAlign diff --git a/libgo/go/runtime/internal/sys/stubs.go b/libgo/go/runtime/internal/sys/stubs.go deleted file mode 100644 index 5328023..0000000 --- a/libgo/go/runtime/internal/sys/stubs.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package sys - -// Declarations for runtime services implemented in C or assembly. - -const PtrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const -const RegSize = 4 << (^Uintreg(0) >> 63) // unsafe.Sizeof(uintreg(0)) but an ideal const -const SpAlign = 1*(1-GoarchArm64) + 16*GoarchArm64 // SP alignment: 1 normally, 16 for ARM64 - -var DefaultGoroot string // set at link time diff --git a/libgo/go/runtime/lfstack_32bit.go b/libgo/go/runtime/lfstack_32bit.go index b3194dc..c0eb665 100644 --- a/libgo/go/runtime/lfstack_32bit.go +++ b/libgo/go/runtime/lfstack_32bit.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build 386 amd64p32 arm armbe m68k mips mipsle mips64p32 mips64p32le nios2 ppc riscv s390 sh shbe sparc +//go:build 386 || arm || mips || mipsle || amd64p32 || armbe || m68k || mips64p32 || mips64p32le || nios2 || ppc || riscv || s390 || sh || shbe || sparc +// +build 386 arm mips mipsle amd64p32 armbe m68k mips64p32 mips64p32le nios2 ppc riscv s390 sh shbe sparc package runtime diff --git a/libgo/go/runtime/lfstack_64bit.go b/libgo/go/runtime/lfstack_64bit.go index af9e7d1..44e6812 100644 --- a/libgo/go/runtime/lfstack_64bit.go +++ b/libgo/go/runtime/lfstack_64bit.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build amd64 || arm64 || mips64 || mips64le || ppc64 || ppc64le || riscv64 || s390x || wasm || arm64be || alpha || sparc64 || ia64 // +build amd64 arm64 mips64 mips64le ppc64 ppc64le riscv64 s390x wasm arm64be alpha sparc64 ia64 package runtime diff --git a/libgo/go/runtime/libfuzzer.go b/libgo/go/runtime/libfuzzer.go index 0161955..578bce0 100644 --- a/libgo/go/runtime/libfuzzer.go +++ b/libgo/go/runtime/libfuzzer.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build libfuzzer // +build libfuzzer package runtime diff --git a/libgo/go/runtime/lock_futex.go b/libgo/go/runtime/lock_futex.go index 21d7e0d..74f6428 100644 --- a/libgo/go/runtime/lock_futex.go +++ b/libgo/go/runtime/lock_futex.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build dragonfly || freebsd || linux // +build dragonfly freebsd linux package runtime @@ -249,7 +250,7 @@ func notetsleepg(n *note, ns int64) bool { return ok } -func beforeIdle(int64) (*g, bool) { +func beforeIdle(int64, int64) (*g, bool) { return nil, false } diff --git a/libgo/go/runtime/lock_js.go b/libgo/go/runtime/lock_js.go index 14bdc76..0ca3512 100644 --- a/libgo/go/runtime/lock_js.go +++ b/libgo/go/runtime/lock_js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package runtime @@ -175,7 +176,12 @@ var idleID int32 // If an event handler returned, we resume it and it will pause the execution. // beforeIdle either returns the specific goroutine to schedule next or // indicates with otherReady that some goroutine became ready. -func beforeIdle(delay int64) (gp *g, otherReady bool) { +func beforeIdle(now, pollUntil int64) (gp *g, otherReady bool) { + delay := int64(-1) + if pollUntil != 0 { + delay = pollUntil - now + } + if delay > 0 { clearIdleID() if delay < 1e6 { diff --git a/libgo/go/runtime/lock_sema.go b/libgo/go/runtime/lock_sema.go index fe17384..bcd8a86 100644 --- a/libgo/go/runtime/lock_sema.go +++ b/libgo/go/runtime/lock_sema.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || hurd || netbsd || openbsd || plan9 || solaris || windows // +build aix darwin hurd netbsd openbsd plan9 solaris windows package runtime @@ -308,7 +309,7 @@ func notetsleepg(n *note, ns int64) bool { return ok } -func beforeIdle(int64) (*g, bool) { +func beforeIdle(int64, int64) (*g, bool) { return nil, false } diff --git a/libgo/go/runtime/lockrank.go b/libgo/go/runtime/lockrank.go index b3c01ba..dde9f7c 100644 --- a/libgo/go/runtime/lockrank.go +++ b/libgo/go/runtime/lockrank.go @@ -44,7 +44,6 @@ const ( lockRankPollDesc lockRankSched lockRankDeadlock - lockRankPanic lockRankAllg lockRankAllp @@ -92,6 +91,7 @@ const ( // rank, we don't allow any further locks to be acquired other than more // hchan locks. lockRankHchanLeaf + lockRankPanic // Leaf locks with no dependencies, so these constants are not actually used anywhere. // There are other architecture-dependent leaf locks as well. @@ -123,7 +123,6 @@ var lockNames = []string{ lockRankPollDesc: "pollDesc", lockRankSched: "sched", lockRankDeadlock: "deadlock", - lockRankPanic: "panic", lockRankAllg: "allg", lockRankAllp: "allp", @@ -162,6 +161,7 @@ var lockNames = []string{ lockRankGFree: "gFree", lockRankHchanLeaf: "hchanLeaf", + lockRankPanic: "panic", lockRankNewmHandoff: "newmHandoff.lock", lockRankDebugPtrmask: "debugPtrmask.lock", @@ -202,10 +202,9 @@ var lockPartialOrder [][]lockRank = [][]lockRank{ lockRankPollDesc: {}, lockRankSched: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc}, lockRankDeadlock: {lockRankDeadlock}, - lockRankPanic: {lockRankDeadlock}, - lockRankAllg: {lockRankSysmon, lockRankSched, lockRankPanic}, + lockRankAllg: {lockRankSysmon, lockRankSched}, lockRankAllp: {lockRankSysmon, lockRankSched}, - lockRankTimers: {lockRankSysmon, lockRankScavenge, lockRankSched, lockRankAllp, lockRankPollDesc, lockRankTimers}, + lockRankTimers: {lockRankSysmon, lockRankScavenge, lockRankPollDesc, lockRankSched, lockRankAllp, lockRankTimers}, lockRankItab: {}, lockRankReflectOffs: {lockRankItab}, lockRankHchan: {lockRankScavenge, lockRankSweep, lockRankHchan}, @@ -214,29 +213,30 @@ var lockPartialOrder [][]lockRank = [][]lockRank{ lockRankTraceBuf: {lockRankSysmon, lockRankScavenge}, lockRankTraceStrings: {lockRankTraceBuf}, lockRankMspanSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings}, - lockRankProf: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan}, - lockRankGcBitsArenas: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan}, + lockRankProf: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings}, + lockRankGcBitsArenas: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings}, lockRankRoot: {}, - lockRankTrace: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankSched, lockRankHchan, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankSweep}, - lockRankTraceStackTab: {lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankTrace}, + lockRankTrace: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankHchan, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot}, + lockRankTraceStackTab: {lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankTrace}, lockRankNetpollInit: {lockRankTimers}, lockRankRwmutexW: {}, lockRankRwmutexR: {lockRankSysmon, lockRankRwmutexW}, - lockRankSpanSetSpine: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan}, - lockRankGscan: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankNotifyList, lockRankProf, lockRankGcBitsArenas, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankSpanSetSpine}, - lockRankStackpool: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankPollDesc, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankRwmutexR, lockRankSpanSetSpine, lockRankGscan}, + lockRankSpanSetSpine: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings}, + lockRankGscan: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankSpanSetSpine}, + lockRankStackpool: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankRwmutexR, lockRankSpanSetSpine, lockRankGscan}, lockRankStackLarge: {lockRankSysmon, lockRankAssistQueue, lockRankSched, lockRankItab, lockRankHchan, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan}, lockRankDefer: {}, - lockRankSudog: {lockRankNotifyList, lockRankHchan}, - lockRankWbufSpans: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankPollDesc, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankRoot, lockRankGscan, lockRankDefer, lockRankSudog}, - lockRankMheap: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankFin, lockRankPollDesc, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan, lockRankMspanSpecial, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans, lockRankSpanSetSpine}, - lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan}, + lockRankSudog: {lockRankHchan, lockRankNotifyList}, + lockRankWbufSpans: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankRoot, lockRankGscan, lockRankDefer, lockRankSudog}, + lockRankMheap: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans}, + lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings}, lockRankGlobalAlloc: {lockRankProf, lockRankSpanSetSpine, lockRankMheap, lockRankMheapSpecial}, lockRankGFree: {lockRankSched}, lockRankHchanLeaf: {lockRankGscan, lockRankHchanLeaf}, + lockRankPanic: {lockRankDeadlock}, // plus any other lock held on throw. lockRankNewmHandoff: {}, lockRankDebugPtrmask: {}, diff --git a/libgo/go/runtime/lockrank_off.go b/libgo/go/runtime/lockrank_off.go index 7dcd8f5..f3d2c00 100644 --- a/libgo/go/runtime/lockrank_off.go +++ b/libgo/go/runtime/lockrank_off.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !goexperiment.staticlockranking // +build !goexperiment.staticlockranking package runtime diff --git a/libgo/go/runtime/lockrank_on.go b/libgo/go/runtime/lockrank_on.go index 88ac95a..fc8d2dc 100644 --- a/libgo/go/runtime/lockrank_on.go +++ b/libgo/go/runtime/lockrank_on.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build goexperiment.staticlockranking // +build goexperiment.staticlockranking package runtime @@ -24,19 +25,6 @@ type lockRankStruct struct { pad int } -// init checks that the partial order in lockPartialOrder fits within the total -// order determined by the order of the lockRank constants. -func init() { - for rank, list := range lockPartialOrder { - for _, entry := range list { - if entry > lockRank(rank) { - println("lockPartial order row", lockRank(rank).String(), "entry", entry.String()) - throw("lockPartialOrder table is inconsistent with total lock ranking order") - } - } - } -} - func lockInit(l *mutex, rank lockRank) { l.rank = rank } @@ -64,12 +52,11 @@ func lockWithRank(l *mutex, rank lockRank) { // rank recording for it, since print/println are used when // printing out a lock ordering problem below. // - // paniclk has an ordering problem, since it can be acquired - // during a panic with any other locks held (especially if the - // panic is because of a directed segv), and yet also allg is - // acquired after paniclk in tracebackothers()). This is a genuine - // problem, so for now we don't do lock rank recording for paniclk - // either. + // paniclk is only used for fatal throw/panic. Don't do lock + // ranking recording for it, since we throw after reporting a + // lock ordering problem. Additionally, paniclk may be taken + // after effectively any lock (anywhere we might panic), which + // the partial order doesn't cover. lock2(l) return } @@ -219,7 +206,7 @@ func releaseLockRank(rank lockRank) { func lockWithRankMayAcquire(l *mutex, rank lockRank) { gp := getg() if gp.m.locksHeldLen == 0 { - // No possibilty of lock ordering problem if no other locks held + // No possibility of lock ordering problem if no other locks held return } diff --git a/libgo/go/runtime/lockrank_test.go b/libgo/go/runtime/lockrank_test.go new file mode 100644 index 0000000..4b2fc0e --- /dev/null +++ b/libgo/go/runtime/lockrank_test.go @@ -0,0 +1,41 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime_test + +import ( + . "runtime" + "testing" +) + +// Check that the partial order in lockPartialOrder fits within the total order +// determined by the order of the lockRank constants. +func TestLockRankPartialOrder(t *testing.T) { + for r, list := range LockPartialOrder { + rank := LockRank(r) + for _, e := range list { + entry := LockRank(e) + if entry > rank { + t.Errorf("lockPartialOrder row %v entry %v is inconsistent with total lock ranking order", rank, entry) + } + } + } +} + +// Verify that partial order lists are kept sorted. This is a purely cosemetic +// check to make manual reviews simpler. It does not affect correctness, unlike +// the above test. +func TestLockRankPartialOrderSortedEntries(t *testing.T) { + for r, list := range LockPartialOrder { + rank := LockRank(r) + var prev LockRank + for _, e := range list { + entry := LockRank(e) + if entry <= prev { + t.Errorf("Partial order for rank %v out of order: %v <= %v in %v", rank, entry, prev, list) + } + prev = entry + } + } +} diff --git a/libgo/go/runtime/malloc.go b/libgo/go/runtime/malloc.go index d3d88a2..7005e53 100644 --- a/libgo/go/runtime/malloc.go +++ b/libgo/go/runtime/malloc.go @@ -237,6 +237,7 @@ const ( // -------------- --------- ---------- ---------- ----------- // */64-bit 48 64MB 1 4M (32MB) // windows/64-bit 48 4MB 64 1M (8MB) + // ios/arm64 33 4MB 1 2048 (8KB) // */32-bit 32 4MB 1 1024 (4KB) // */mips(le) 31 4MB 1 512 (2KB) @@ -257,7 +258,7 @@ const ( // logHeapArenaBytes is log_2 of heapArenaBytes. For clarity, // prefer using heapArenaBytes where possible (we need the // constant to compute some other constants). - logHeapArenaBytes = (6+20)*(_64bit*(1-sys.GoosWindows)*(1-sys.GoarchWasm)) + (2+20)*(_64bit*sys.GoosWindows) + (2+20)*(1-_64bit) + (2+20)*sys.GoarchWasm + logHeapArenaBytes = (6+20)*(_64bit*(1-sys.GoosWindows)*(1-sys.GoarchWasm)*(1-sys.GoosIos*sys.GoarchArm64)) + (2+20)*(_64bit*sys.GoosWindows) + (2+20)*(1-_64bit) + (2+20)*sys.GoarchWasm + (2+20)*sys.GoosIos*sys.GoarchArm64 // heapArenaBitmapBytes is the size of each heap arena's bitmap. heapArenaBitmapBytes = heapArenaBytes / (sys.PtrSize * 8 / 2) @@ -305,7 +306,7 @@ const ( // high addresses if viewed as unsigned). // // On aix/ppc64, this offset allows to keep the heapAddrBits to - // 48. Otherwize, it would be 60 in order to handle mmap addresses + // 48. Otherwise, it would be 60 in order to handle mmap addresses // (in range 0x0a00000000000000 - 0x0afffffffffffff). But in this // case, the memory reserved in (s *pageAlloc).init for chunks // is causing important slowdowns. @@ -579,7 +580,7 @@ func mallocinit() { const arenaMetaSize = (1 << arenaBits) * unsafe.Sizeof(heapArena{}) meta := uintptr(sysReserve(nil, arenaMetaSize)) if meta != 0 { - mheap_.heapArenaAlloc.init(meta, arenaMetaSize) + mheap_.heapArenaAlloc.init(meta, arenaMetaSize, true) } // We want to start the arena low, but if we're linked @@ -616,7 +617,7 @@ func mallocinit() { for _, arenaSize := range &arenaSizes { a, size := sysReserveAligned(unsafe.Pointer(p), arenaSize, heapArenaBytes) if a != nil { - mheap_.arena.init(uintptr(a), size) + mheap_.arena.init(uintptr(a), size, false) p = mheap_.arena.end // For hint below break } @@ -633,8 +634,8 @@ func mallocinit() { // heapArenaBytes. sysAlloc returns nil on failure. // There is no corresponding free function. // -// sysAlloc returns a memory region in the Prepared state. This region must -// be transitioned to Ready before use. +// sysAlloc returns a memory region in the Reserved state. This region must +// be transitioned to Prepared and then Ready before use. // // h must be locked. func (h *mheap) sysAlloc(n uintptr) (v unsafe.Pointer, size uintptr) { @@ -736,9 +737,6 @@ func (h *mheap) sysAlloc(n uintptr) (v unsafe.Pointer, size uintptr) { throw("misrounded allocation in sysAlloc") } - // Transition from Reserved to Prepared. - sysMap(v, size, &memstats.heap_sys) - mapped: // Create arena metadata. for ri := arenaIndex(uintptr(v)); ri <= arenaIndex(uintptr(v)+size-1); ri++ { @@ -947,7 +945,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { } if inittrace.active && inittrace.id == getg().goid { - // Init functions are executed sequentially in a single Go routine. + // Init functions are executed sequentially in a single goroutine. inittrace.allocs += 1 } } @@ -1003,6 +1001,9 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { var span *mspan var x unsafe.Pointer noscan := typ == nil || typ.ptrdata == 0 + // In some cases block zeroing can profitably (for latency reduction purposes) + // be delayed till preemption is possible; isZeroed tracks that state. + isZeroed := true if size <= maxSmallSize { if noscan && size < maxTinySize { // Tiny allocator. @@ -1074,7 +1075,8 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { (*[2]uint64)(x)[1] = 0 // See if we need to replace the existing tiny block with the new one // based on amount of remaining free space. - if size < c.tinyoffset || c.tiny == 0 { + if !raceenabled && (size < c.tinyoffset || c.tiny == 0) { + // Note: disabled when race detector is on, see comment near end of this function. c.tiny = uintptr(x) c.tinyoffset = size } @@ -1100,7 +1102,9 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { } } else { shouldhelpgc = true - span = c.allocLarge(size, needzero, noscan) + // For large allocations, keep track of zeroed state so that + // bulk zeroing can be happen later in a preemptible context. + span, isZeroed = c.allocLarge(size, needzero && !noscan, noscan) span.freeindex = 1 span.allocCount = 1 x = unsafe.Pointer(span.base()) @@ -1147,30 +1151,34 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { msanmalloc(x, size) } + if rate := MemProfileRate; rate > 0 { + // Note cache c only valid while m acquired; see #47302 + if rate != 1 && size < c.nextSample { + c.nextSample -= size + } else { + profilealloc(mp, x, size) + } + } mp.mallocing = 0 releasem(mp) + // Pointerfree data can be zeroed late in a context where preemption can occur. + // x will keep the memory alive. + if !isZeroed && needzero { + memclrNoHeapPointersChunked(size, x) // This is a possible preemption point: see #47302 + } + if debug.malloc { if debug.allocfreetrace != 0 { tracealloc(x, size, typ) } if inittrace.active && inittrace.id == getg().goid { - // Init functions are executed sequentially in a single Go routine. + // Init functions are executed sequentially in a single goroutine. inittrace.bytes += uint64(size) } } - if rate := MemProfileRate; rate > 0 { - if rate != 1 && size < c.nextSample { - c.nextSample -= size - } else { - mp := acquirem() - profilealloc(mp, x, size) - releasem(mp) - } - } - if assistG != nil { // Account for internal fragmentation in the assist // debt now that we know it. @@ -1183,6 +1191,22 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { } } + if raceenabled && noscan && dataSize < maxTinySize { + // Pad tinysize allocations so they are aligned with the end + // of the tinyalloc region. This ensures that any arithmetic + // that goes off the top end of the object will be detectable + // by checkptr (issue 38872). + // Note that we disable tinyalloc when raceenabled for this to work. + // TODO: This padding is only performed when the race detector + // is enabled. It would be nice to enable it if any package + // was compiled with checkptr, but there's no easy way to + // detect that (especially at compile time). + // TODO: enable this padding for all allocations, not just + // tinyalloc ones. It's tricky because of pointer maps. + // Maybe just all noscan objects? + x = add(x, size-dataSize) + } + // Check preemption, since unlike gc we don't check on every call. if getg().preempt { checkPreempt() @@ -1195,6 +1219,33 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { return x } +// memclrNoHeapPointersChunked repeatedly calls memclrNoHeapPointers +// on chunks of the buffer to be zeroed, with opportunities for preemption +// along the way. memclrNoHeapPointers contains no safepoints and also +// cannot be preemptively scheduled, so this provides a still-efficient +// block copy that can also be preempted on a reasonable granularity. +// +// Use this with care; if the data being cleared is tagged to contain +// pointers, this allows the GC to run before it is all cleared. +func memclrNoHeapPointersChunked(size uintptr, x unsafe.Pointer) { + v := uintptr(x) + // got this from benchmarking. 128k is too small, 512k is too large. + const chunkBytes = 256 * 1024 + vsize := v + size + for voff := v; voff < vsize; voff = voff + chunkBytes { + if getg().preempt { + // may hold locks, e.g., profiling + goschedguarded() + } + // clear min(avail, lump) bytes + n := vsize - voff + if n > chunkBytes { + n = chunkBytes + } + memclrNoHeapPointers(unsafe.Pointer(voff), n) + } +} + // implementation of new builtin // compiler (both frontend and SSA backend) knows the signature // of this function @@ -1425,15 +1476,19 @@ func inPersistentAlloc(p uintptr) bool { } // linearAlloc is a simple linear allocator that pre-reserves a region -// of memory and then maps that region into the Ready state as needed. The -// caller is responsible for locking. +// of memory and then optionally maps that region into the Ready state +// as needed. +// +// The caller is responsible for locking. type linearAlloc struct { next uintptr // next free byte mapped uintptr // one byte past end of mapped space end uintptr // end of reserved space + + mapMemory bool // transition memory from Reserved to Ready if true } -func (l *linearAlloc) init(base, size uintptr) { +func (l *linearAlloc) init(base, size uintptr, mapMemory bool) { if base+size < base { // Chop off the last byte. The runtime isn't prepared // to deal with situations where the bounds could overflow. @@ -1443,6 +1498,7 @@ func (l *linearAlloc) init(base, size uintptr) { } l.next, l.mapped = base, base l.end = base + size + l.mapMemory = mapMemory } func (l *linearAlloc) alloc(size, align uintptr, sysStat *sysMemStat) unsafe.Pointer { @@ -1452,9 +1508,11 @@ func (l *linearAlloc) alloc(size, align uintptr, sysStat *sysMemStat) unsafe.Poi } l.next = p + size if pEnd := alignUp(l.next-1, physPageSize); pEnd > l.mapped { - // Transition from Reserved to Prepared to Ready. - sysMap(unsafe.Pointer(l.mapped), pEnd-l.mapped, sysStat) - sysUsed(unsafe.Pointer(l.mapped), pEnd-l.mapped) + if l.mapMemory { + // Transition from Reserved to Prepared to Ready. + sysMap(unsafe.Pointer(l.mapped), pEnd-l.mapped, sysStat) + sysUsed(unsafe.Pointer(l.mapped), pEnd-l.mapped) + } l.mapped = pEnd } return unsafe.Pointer(p) diff --git a/libgo/go/runtime/malloc_test.go b/libgo/go/runtime/malloc_test.go index 24b8740..7e83255 100644 --- a/libgo/go/runtime/malloc_test.go +++ b/libgo/go/runtime/malloc_test.go @@ -156,6 +156,9 @@ func TestStringConcatenationAllocs(t *testing.T) { } func TestTinyAlloc(t *testing.T) { + if runtime.Raceenabled { + t.Skip("tinyalloc suppressed when running in race mode") + } const N = 16 var v [N]unsafe.Pointer for i := range v { @@ -184,6 +187,9 @@ type obj12 struct { } func TestTinyAllocIssue37262(t *testing.T) { + if runtime.Raceenabled { + t.Skip("tinyalloc suppressed when running in race mode") + } // Try to cause an alignment access fault // by atomically accessing the first 64-bit // value of a tiny-allocated object. diff --git a/libgo/go/runtime/map.go b/libgo/go/runtime/map.go index 5b9d7102..c96d2c7 100644 --- a/libgo/go/runtime/map.go +++ b/libgo/go/runtime/map.go @@ -128,7 +128,7 @@ func isEmpty(x uint8) bool { // A header for a Go map. type hmap struct { - // Note: the format of the hmap is also encoded in cmd/compile/internal/gc/reflect.go. + // Note: the format of the hmap is also encoded in cmd/compile/internal/reflectdata/reflect.go. // Make sure this stays in sync with the compiler's definition. count int // # live cells == size of map. Must be first (used by len() builtin) flags uint8 @@ -174,11 +174,11 @@ type bmap struct { } // A hash iteration structure. -// If you modify hiter, also change cmd/compile/internal/gc/reflect.go to indicate +// If you modify hiter, also change cmd/compile/internal/reflectdata/reflect.go to indicate // the layout of this structure. type hiter struct { - key unsafe.Pointer // Must be in first position. Write nil to indicate iteration end (see cmd/compile/internal/gc/range.go). - elem unsafe.Pointer // Must be in second position (see cmd/compile/internal/gc/range.go). + key unsafe.Pointer // Must be in first position. Write nil to indicate iteration end (see cmd/compile/internal/walk/range.go). + elem unsafe.Pointer // Must be in second position (see cmd/compile/internal/walk/range.go). t *maptype h *hmap buckets unsafe.Pointer // bucket ptr at hash_iter initialization time @@ -495,13 +495,13 @@ func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool) } hash := t.hasher(key, uintptr(h.hash0)) m := bucketMask(h.B) - b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + (hash&m)*uintptr(t.bucketsize))) + b := (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize))) if c := h.oldbuckets; c != nil { if !h.sameSizeGrow() { // There used to be half as many buckets; mask down one more power of two. m >>= 1 } - oldb := (*bmap)(unsafe.Pointer(uintptr(c) + (hash&m)*uintptr(t.bucketsize))) + oldb := (*bmap)(add(c, (hash&m)*uintptr(t.bucketsize))) if !evacuated(oldb) { b = oldb } @@ -544,13 +544,13 @@ func mapaccessK(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, unsafe } hash := t.hasher(key, uintptr(h.hash0)) m := bucketMask(h.B) - b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + (hash&m)*uintptr(t.bucketsize))) + b := (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize))) if c := h.oldbuckets; c != nil { if !h.sameSizeGrow() { // There used to be half as many buckets; mask down one more power of two. m >>= 1 } - oldb := (*bmap)(unsafe.Pointer(uintptr(c) + (hash&m)*uintptr(t.bucketsize))) + oldb := (*bmap)(add(c, (hash&m)*uintptr(t.bucketsize))) if !evacuated(oldb) { b = oldb } @@ -863,7 +863,7 @@ func mapiterinit(t *maptype, h *hmap, it *hiter) { } if unsafe.Sizeof(hiter{})/sys.PtrSize != 12 { - throw("hash_iter size incorrect") // see cmd/compile/internal/gc/reflect.go + throw("hash_iter size incorrect") // see cmd/compile/internal/reflectdata/reflect.go } it.t = t it.h = h diff --git a/libgo/go/runtime/map_faststr.go b/libgo/go/runtime/map_faststr.go index 2205947..647978b 100644 --- a/libgo/go/runtime/map_faststr.go +++ b/libgo/go/runtime/map_faststr.go @@ -262,6 +262,9 @@ bucketloop: // already have a mapping for key. Update it. inserti = i insertb = b + // Overwrite existing key, so it can be garbage collected. + // The size is already guaranteed to be set correctly. + k.str = key.str goto done } ovf := b.overflow(t) diff --git a/libgo/go/runtime/mbitmap.go b/libgo/go/runtime/mbitmap.go index 0eb19d6..72cd9f3 100644 --- a/libgo/go/runtime/mbitmap.go +++ b/libgo/go/runtime/mbitmap.go @@ -226,16 +226,25 @@ func (s *mspan) isFree(index uintptr) bool { return *bytep&mask == 0 } -func (s *mspan) objIndex(p uintptr) uintptr { - byteOffset := p - s.base() - if byteOffset == 0 { - return 0 - } - if s.baseMask != 0 { - // s.baseMask is non-0, elemsize is a power of two, so shift by s.divShift - return byteOffset >> s.divShift +// divideByElemSize returns n/s.elemsize. +// n must be within [0, s.npages*_PageSize), +// or may be exactly s.npages*_PageSize +// if s.elemsize is from sizeclasses.go. +func (s *mspan) divideByElemSize(n uintptr) uintptr { + const doubleCheck = false + + // See explanation in mksizeclasses.go's computeDivMagic. + q := uintptr((uint64(n) * uint64(s.divMul)) >> 32) + + if doubleCheck && q != n/s.elemsize { + println(n, "/", s.elemsize, "should be", n/s.elemsize, "but got", q) + throw("bad magic division") } - return uintptr(((uint64(byteOffset) >> s.divShift) * uint64(s.divMul)) >> s.divShift2) + return q +} + +func (s *mspan) objIndex(p uintptr) uintptr { + return s.divideByElemSize(p - s.base()) } func markBitsForAddr(p uintptr) markBits { @@ -324,6 +333,10 @@ func heapBitsForAddr(addr uintptr) (h heapBits) { return } +// clobberdeadPtr is a special value that is used by the compiler to +// clobber dead stack slots, when -clobberdead flag is set. +const clobberdeadPtr = uintptr(0xdeaddead | 0xdeaddead<<((^uintptr(0)>>63)*32)) + // badPointer throws bad pointer in heap panic. func badPointer(s *mspan, p, refBase, refOff uintptr) { // Typically this indicates an incorrect use @@ -336,13 +349,16 @@ func badPointer(s *mspan, p, refBase, refOff uintptr) { // in allocated spans. printlock() print("runtime: pointer ", hex(p)) - state := s.state.get() - if state != mSpanInUse { - print(" to unallocated span") - } else { - print(" to unused region of span") + if s != nil { + state := s.state.get() + if state != mSpanInUse { + print(" to unallocated span") + } else { + print(" to unused region of span") + } + print(" span.base()=", hex(s.base()), " span.limit=", hex(s.limit), " span.state=", state) } - print(" span.base()=", hex(s.base()), " span.limit=", hex(s.limit), " span.state=", state, "\n") + print("\n") if refBase != 0 { print("runtime: found in object at *(", hex(refBase), "+", hex(refOff), ")\n") gcDumpObject("object", refBase, refOff) @@ -373,6 +389,12 @@ func findObject(p, refBase, refOff uintptr, forStack bool) (base uintptr, s *msp // If s is nil, the virtual address has never been part of the heap. // This pointer may be to some mmap'd region, so we allow it. if s == nil { + if GOARCH == "amd64" && p == clobberdeadPtr && debug.invalidptr != 0 { + // Crash if clobberdeadPtr is seen. Only on AMD64 for now, as + // it is the only platform where compiler's clobberdead mode is + // implemented. On AMD64 clobberdeadPtr cannot be a valid address. + badPointer(s, p, refBase, refOff) + } return } // If p is a bad pointer, it may not be in s's bounds. @@ -402,24 +424,8 @@ func findObject(p, refBase, refOff uintptr, forStack bool) (base uintptr, s *msp } } - // If this span holds object of a power of 2 size, just mask off the bits to - // the interior of the object. Otherwise use the size to get the base. - if s.baseMask != 0 { - // optimize for power of 2 sized objects. - base = s.base() - base = base + (p-base)&uintptr(s.baseMask) - objIndex = (base - s.base()) >> s.divShift - // base = p & s.baseMask is faster for small spans, - // but doesn't work for large spans. - // Overall, it's faster to use the more general computation above. - } else { - base = s.base() - if p-base >= s.elemsize { - // n := (p - base) / s.elemsize, using division by multiplication - objIndex = uintptr(p-base) >> s.divShift * uintptr(s.divMul) >> s.divShift2 - base += objIndex * s.elemsize - } - } + objIndex = s.objIndex(p) + base = s.base() + objIndex*s.elemsize return } diff --git a/libgo/go/runtime/mcache.go b/libgo/go/runtime/mcache.go index 32622e6..531f3be 100644 --- a/libgo/go/runtime/mcache.go +++ b/libgo/go/runtime/mcache.go @@ -168,29 +168,29 @@ func (c *mcache) refill(spc spanClass) { // mcache. If it gets uncached, we'll adjust this. stats := memstats.heapStats.acquire() atomic.Xadduintptr(&stats.smallAllocCount[spc.sizeclass()], uintptr(s.nelems)-uintptr(s.allocCount)) - memstats.heapStats.release() - - // Update heap_live with the same assumption. - usedBytes := uintptr(s.allocCount) * s.elemsize - atomic.Xadd64(&memstats.heap_live, int64(s.npages*pageSize)-int64(usedBytes)) // Flush tinyAllocs. if spc == tinySpanClass { - atomic.Xadd64(&memstats.tinyallocs, int64(c.tinyAllocs)) + atomic.Xadduintptr(&stats.tinyAllocCount, c.tinyAllocs) c.tinyAllocs = 0 } + memstats.heapStats.release() + + // Update gcController.heapLive with the same assumption. + usedBytes := uintptr(s.allocCount) * s.elemsize + atomic.Xadd64(&gcController.heapLive, int64(s.npages*pageSize)-int64(usedBytes)) // While we're here, flush scanAlloc, since we have to call // revise anyway. - atomic.Xadd64(&memstats.heap_scan, int64(c.scanAlloc)) + atomic.Xadd64(&gcController.heapScan, int64(c.scanAlloc)) c.scanAlloc = 0 if trace.enabled { - // heap_live changed. + // gcController.heapLive changed. traceHeapAlloc() } if gcBlackenEnabled != 0 { - // heap_live and heap_scan changed. + // gcController.heapLive and heapScan changed. gcController.revise() } @@ -198,7 +198,10 @@ func (c *mcache) refill(spc spanClass) { } // allocLarge allocates a span for a large object. -func (c *mcache) allocLarge(size uintptr, needzero bool, noscan bool) *mspan { +// The boolean result indicates whether the span is known-zeroed. +// If it did not need to be zeroed, it may not have been zeroed; +// but if it came directly from the OS, it is already zeroed. +func (c *mcache) allocLarge(size uintptr, needzero bool, noscan bool) (*mspan, bool) { if size+_PageSize < size { throw("out of memory") } @@ -213,7 +216,7 @@ func (c *mcache) allocLarge(size uintptr, needzero bool, noscan bool) *mspan { deductSweepCredit(npages*_PageSize, npages) spc := makeSpanClass(0, noscan) - s := mheap_.alloc(npages, spc, needzero) + s, isZeroed := mheap_.alloc(npages, spc, needzero) if s == nil { throw("out of memory") } @@ -222,10 +225,10 @@ func (c *mcache) allocLarge(size uintptr, needzero bool, noscan bool) *mspan { atomic.Xadduintptr(&stats.largeAllocCount, 1) memstats.heapStats.release() - // Update heap_live and revise pacing if needed. - atomic.Xadd64(&memstats.heap_live, int64(npages*pageSize)) + // Update gcController.heapLive and revise pacing if needed. + atomic.Xadd64(&gcController.heapLive, int64(npages*pageSize)) if trace.enabled { - // Trace that a heap alloc occurred because heap_live changed. + // Trace that a heap alloc occurred because gcController.heapLive changed. traceHeapAlloc() } if gcBlackenEnabled != 0 { @@ -237,12 +240,12 @@ func (c *mcache) allocLarge(size uintptr, needzero bool, noscan bool) *mspan { mheap_.central[spc].mcentral.fullSwept(mheap_.sweepgen).push(s) s.limit = s.base() + size heapBitsForAddr(s.base()).initSpan(s) - return s + return s, isZeroed } func (c *mcache) releaseAll() { // Take this opportunity to flush scanAlloc. - atomic.Xadd64(&memstats.heap_scan, int64(c.scanAlloc)) + atomic.Xadd64(&gcController.heapScan, int64(c.scanAlloc)) c.scanAlloc = 0 sg := mheap_.sweepgen @@ -255,14 +258,14 @@ func (c *mcache) releaseAll() { atomic.Xadduintptr(&stats.smallAllocCount[spanClass(i).sizeclass()], -n) memstats.heapStats.release() if s.sweepgen != sg+1 { - // refill conservatively counted unallocated slots in heap_live. + // refill conservatively counted unallocated slots in gcController.heapLive. // Undo this. // // If this span was cached before sweep, then - // heap_live was totally recomputed since + // gcController.heapLive was totally recomputed since // caching this span, so we don't do this for // stale spans. - atomic.Xadd64(&memstats.heap_live, -int64(n)*int64(s.elemsize)) + atomic.Xadd64(&gcController.heapLive, -int64(n)*int64(s.elemsize)) } // Release the span to the mcentral. mheap_.central[i].mcentral.uncacheSpan(s) @@ -272,10 +275,14 @@ func (c *mcache) releaseAll() { // Clear tinyalloc pool. c.tiny = 0 c.tinyoffset = 0 - atomic.Xadd64(&memstats.tinyallocs, int64(c.tinyAllocs)) + + // Flush tinyAllocs. + stats := memstats.heapStats.acquire() + atomic.Xadduintptr(&stats.tinyAllocCount, c.tinyAllocs) c.tinyAllocs = 0 + memstats.heapStats.release() - // Updated heap_scan and possible heap_live. + // Updated heapScan and possible gcController.heapLive. if gcBlackenEnabled != 0 { gcController.revise() } diff --git a/libgo/go/runtime/mcentral.go b/libgo/go/runtime/mcentral.go index cd20dec..6013c94 100644 --- a/libgo/go/runtime/mcentral.go +++ b/libgo/go/runtime/mcentral.go @@ -81,8 +81,6 @@ func (c *mcentral) cacheSpan() *mspan { spanBytes := uintptr(class_to_allocnpages[c.spanclass.sizeclass()]) * _PageSize deductSweepCredit(spanBytes, 0) - sg := mheap_.sweepgen - traceDone := false if trace.enabled { traceGCSweepStart() @@ -104,6 +102,8 @@ func (c *mcentral) cacheSpan() *mspan { spanBudget := 100 var s *mspan + sl := newSweepLocker() + sg := sl.sweepGen // Try partial swept spans first. if s = c.partialSwept(sg).pop(); s != nil { @@ -116,9 +116,10 @@ func (c *mcentral) cacheSpan() *mspan { if s == nil { break } - if atomic.Load(&s.sweepgen) == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) { + if s, ok := sl.tryAcquire(s); ok { // We got ownership of the span, so let's sweep it and use it. s.sweep(true) + sl.dispose() goto havespan } // We failed to get ownership of the span, which means it's being or @@ -135,20 +136,22 @@ func (c *mcentral) cacheSpan() *mspan { if s == nil { break } - if atomic.Load(&s.sweepgen) == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) { + if s, ok := sl.tryAcquire(s); ok { // We got ownership of the span, so let's sweep it. s.sweep(true) // Check if there's any free space. freeIndex := s.nextFreeIndex() if freeIndex != s.nelems { s.freeindex = freeIndex + sl.dispose() goto havespan } // Add it to the swept list, because sweeping didn't give us any free space. - c.fullSwept(sg).push(s) + c.fullSwept(sg).push(s.mspan) } // See comment for partial unswept spans. } + sl.dispose() if trace.enabled { traceGCSweepDone() traceDone = true @@ -211,7 +214,13 @@ func (c *mcentral) uncacheSpan(s *mspan) { if stale { // It's stale, so just sweep it. Sweeping will put it on // the right list. - s.sweep(false) + // + // We don't use a sweepLocker here. Stale cached spans + // aren't in the global sweep lists, so mark termination + // itself holds up sweep completion until all mcaches + // have been swept. + ss := sweepLocked{s} + ss.sweep(false) } else { if int(s.nelems)-int(s.allocCount) > 0 { // Put it back on the partial swept list. @@ -229,14 +238,14 @@ func (c *mcentral) grow() *mspan { npages := uintptr(class_to_allocnpages[c.spanclass.sizeclass()]) size := uintptr(class_to_size[c.spanclass.sizeclass()]) - s := mheap_.alloc(npages, c.spanclass, true) + s, _ := mheap_.alloc(npages, c.spanclass, true) if s == nil { return nil } // Use division by multiplication and shifts to quickly compute: // n := (npages << _PageShift) / size - n := (npages << _PageShift) >> s.divShift * uintptr(s.divMul) >> s.divShift2 + n := s.divideByElemSize(npages << _PageShift) s.limit = s.base() + size*n heapBitsForAddr(s.base()).initSpan(s) return s diff --git a/libgo/go/runtime/metrics.go b/libgo/go/runtime/metrics.go index e1f1db2..45a68e4 100644 --- a/libgo/go/runtime/metrics.go +++ b/libgo/go/runtime/metrics.go @@ -98,6 +98,20 @@ func initMetrics() { } }, }, + "/gc/heap/allocs:bytes": { + deps: makeStatDepSet(heapStatsDep), + compute: func(in *statAggregate, out *metricValue) { + out.kind = metricKindUint64 + out.scalar = in.heapStats.totalAllocated + }, + }, + "/gc/heap/allocs:objects": { + deps: makeStatDepSet(heapStatsDep), + compute: func(in *statAggregate, out *metricValue) { + out.kind = metricKindUint64 + out.scalar = in.heapStats.totalAllocs + }, + }, "/gc/heap/frees-by-size:bytes": { deps: makeStatDepSet(heapStatsDep), compute: func(in *statAggregate, out *metricValue) { @@ -110,6 +124,20 @@ func initMetrics() { } }, }, + "/gc/heap/frees:bytes": { + deps: makeStatDepSet(heapStatsDep), + compute: func(in *statAggregate, out *metricValue) { + out.kind = metricKindUint64 + out.scalar = in.heapStats.totalFreed + }, + }, + "/gc/heap/frees:objects": { + deps: makeStatDepSet(heapStatsDep), + compute: func(in *statAggregate, out *metricValue) { + out.kind = metricKindUint64 + out.scalar = in.heapStats.totalFrees + }, + }, "/gc/heap/goal:bytes": { deps: makeStatDepSet(sysStatsDep), compute: func(in *statAggregate, out *metricValue) { @@ -124,6 +152,13 @@ func initMetrics() { out.scalar = in.heapStats.numObjects }, }, + "/gc/heap/tiny/allocs:objects": { + deps: makeStatDepSet(heapStatsDep), + compute: func(in *statAggregate, out *metricValue) { + out.kind = metricKindUint64 + out.scalar = uint64(in.heapStats.tinyAllocCount) + }, + }, "/gc/pauses:seconds": { compute: func(_ *statAggregate, out *metricValue) { hist := out.float64HistOrInit(timeHistBuckets) @@ -245,6 +280,15 @@ func initMetrics() { out.scalar = uint64(gcount()) }, }, + "/sched/latencies:seconds": { + compute: func(_ *statAggregate, out *metricValue) { + hist := out.float64HistOrInit(timeHistBuckets) + hist.counts[0] = atomic.Load64(&sched.timeToRun.underflow) + for i := range sched.timeToRun.counts { + hist.counts[i+1] = atomic.Load64(&sched.timeToRun.counts[i]) + } + }, + }, } metricsInit = true } @@ -321,6 +365,22 @@ type heapStatsAggregate struct { // numObjects is the number of live objects in the heap. numObjects uint64 + + // totalAllocated is the total bytes of heap objects allocated + // over the lifetime of the program. + totalAllocated uint64 + + // totalFreed is the total bytes of heap objects freed + // over the lifetime of the program. + totalFreed uint64 + + // totalAllocs is the number of heap objects allocated over + // the lifetime of the program. + totalAllocs uint64 + + // totalFrees is the number of heap objects freed over + // the lifetime of the program. + totalFrees uint64 } // compute populates the heapStatsAggregate with values from the runtime. @@ -328,13 +388,20 @@ func (a *heapStatsAggregate) compute() { memstats.heapStats.read(&a.heapStatsDelta) // Calculate derived stats. - a.inObjects = uint64(a.largeAlloc - a.largeFree) - a.numObjects = uint64(a.largeAllocCount - a.largeFreeCount) + a.totalAllocs = uint64(a.largeAllocCount) + a.totalFrees = uint64(a.largeFreeCount) + a.totalAllocated = uint64(a.largeAlloc) + a.totalFreed = uint64(a.largeFree) for i := range a.smallAllocCount { - n := uint64(a.smallAllocCount[i] - a.smallFreeCount[i]) - a.inObjects += n * uint64(class_to_size[i]) - a.numObjects += n + na := uint64(a.smallAllocCount[i]) + nf := uint64(a.smallFreeCount[i]) + a.totalAllocs += na + a.totalFrees += nf + a.totalAllocated += na * uint64(class_to_size[i]) + a.totalFreed += nf * uint64(class_to_size[i]) } + a.inObjects = a.totalAllocated - a.totalFreed + a.numObjects = a.totalAllocs - a.totalFrees } // sysStatsAggregate represents system memory stats obtained @@ -364,7 +431,7 @@ func (a *sysStatsAggregate) compute() { a.buckHashSys = memstats.buckhash_sys.load() a.gcMiscSys = memstats.gcMiscSys.load() a.otherSys = memstats.other_sys.load() - a.heapGoal = atomic.Load64(&memstats.next_gc) + a.heapGoal = atomic.Load64(&gcController.heapGoal) a.gcCyclesDone = uint64(memstats.numgc) a.gcCyclesForced = uint64(memstats.numforcedgc) @@ -481,7 +548,7 @@ func readMetrics(samplesp unsafe.Pointer, len int, cap int) { // Acquire the metricsSema but with handoff. This operation // is expensive enough that queueing up goroutines and handing - // off between them will be noticably better-behaved. + // off between them will be noticeably better-behaved. semacquire1(&metricsSema, true, 0, 0) // Ensure the map is initialized. diff --git a/libgo/go/runtime/metrics/description.go b/libgo/go/runtime/metrics/description.go index 1175156..c147cad 100644 --- a/libgo/go/runtime/metrics/description.go +++ b/libgo/go/runtime/metrics/description.go @@ -70,18 +70,51 @@ var allDesc = []Description{ Cumulative: true, }, { - Name: "/gc/heap/allocs-by-size:bytes", - Description: "Distribution of all objects allocated by approximate size.", - Kind: KindFloat64Histogram, + Name: "/gc/heap/allocs-by-size:bytes", + Description: "Distribution of heap allocations by approximate size. " + + "Note that this does not include tiny objects as defined by " + + "/gc/heap/tiny/allocs:objects, only tiny blocks.", + Kind: KindFloat64Histogram, + Cumulative: true, + }, + { + Name: "/gc/heap/allocs:bytes", + Description: "Cumulative sum of memory allocated to the heap by the application.", + Kind: KindUint64, Cumulative: true, }, { - Name: "/gc/heap/frees-by-size:bytes", - Description: "Distribution of all objects freed by approximate size.", - Kind: KindFloat64Histogram, + Name: "/gc/heap/allocs:objects", + Description: "Cumulative count of heap allocations triggered by the application. " + + "Note that this does not include tiny objects as defined by " + + "/gc/heap/tiny/allocs:objects, only tiny blocks.", + Kind: KindUint64, + Cumulative: true, + }, + { + Name: "/gc/heap/frees-by-size:bytes", + Description: "Distribution of freed heap allocations by approximate size. " + + "Note that this does not include tiny objects as defined by " + + "/gc/heap/tiny/allocs:objects, only tiny blocks.", + Kind: KindFloat64Histogram, + Cumulative: true, + }, + { + Name: "/gc/heap/frees:bytes", + Description: "Cumulative sum of heap memory freed by the garbage collector.", + Kind: KindUint64, Cumulative: true, }, { + Name: "/gc/heap/frees:objects", + Description: "Cumulative count of heap allocations whose storage was freed " + + "by the garbage collector. " + + "Note that this does not include tiny objects as defined by " + + "/gc/heap/tiny/allocs:objects, only tiny blocks.", + Kind: KindUint64, + Cumulative: true, + }, + { Name: "/gc/heap/goal:bytes", Description: "Heap size target for the end of the GC cycle.", Kind: KindUint64, @@ -92,6 +125,16 @@ var allDesc = []Description{ Kind: KindUint64, }, { + Name: "/gc/heap/tiny/allocs:objects", + Description: "Count of small allocations that are packed together into blocks. " + + "These allocations are counted separately from other allocations " + + "because each individual allocation is not tracked by the runtime, " + + "only their block. Each block is already accounted for in " + + "allocs-by-size and frees-by-size.", + Kind: KindUint64, + Cumulative: true, + }, + { Name: "/gc/pauses:seconds", Description: "Distribution individual GC-related stop-the-world pause latencies.", Kind: KindFloat64Histogram, @@ -176,6 +219,11 @@ var allDesc = []Description{ Description: "Count of live goroutines.", Kind: KindUint64, }, + { + Name: "/sched/latencies:seconds", + Description: "Distribution of the time goroutines have spent in the scheduler in a runnable state before actually running.", + Kind: KindFloat64Histogram, + }, } // All returns a slice of containing metric descriptions for all supported metrics. diff --git a/libgo/go/runtime/metrics/doc.go b/libgo/go/runtime/metrics/doc.go index 7f790af..91ef030 100644 --- a/libgo/go/runtime/metrics/doc.go +++ b/libgo/go/runtime/metrics/doc.go @@ -61,10 +61,30 @@ Below is the full list of supported metrics, ordered lexicographically. Count of all completed GC cycles. /gc/heap/allocs-by-size:bytes - Distribution of all objects allocated by approximate size. + Distribution of heap allocations by approximate size. + Note that this does not include tiny objects as defined by /gc/heap/tiny/allocs:objects, + only tiny blocks. + + /gc/heap/allocs:bytes + Cumulative sum of memory allocated to the heap by the application. + + /gc/heap/allocs:objects + Cumulative count of heap allocations triggered by the application. + Note that this does not include tiny objects as defined by /gc/heap/tiny/allocs:objects, + only tiny blocks. /gc/heap/frees-by-size:bytes - Distribution of all objects freed by approximate size. + Distribution of freed heap allocations by approximate size. + Note that this does not include tiny objects as defined by /gc/heap/tiny/allocs:objects, + only tiny blocks. + + /gc/heap/frees:bytes + Cumulative sum of heap memory freed by the garbage collector. + + /gc/heap/frees:objects + Cumulative count of heap allocations whose storage was freed by the garbage collector. + Note that this does not include tiny objects as defined by /gc/heap/tiny/allocs:objects, + only tiny blocks. /gc/heap/goal:bytes Heap size target for the end of the GC cycle. @@ -72,6 +92,13 @@ Below is the full list of supported metrics, ordered lexicographically. /gc/heap/objects:objects Number of objects, live or unswept, occupying heap memory. + /gc/heap/tiny/allocs:objects + Count of small allocations that are packed together into blocks. + These allocations are counted separately from other allocations + because each individual allocation is not tracked by the runtime, + only their block. Each block is already accounted for in + allocs-by-size and frees-by-size. + /gc/pauses:seconds Distribution individual GC-related stop-the-world pause latencies. @@ -139,5 +166,9 @@ Below is the full list of supported metrics, ordered lexicographically. /sched/goroutines:goroutines Count of live goroutines. + + /sched/latencies:seconds + Distribution of the time goroutines have spent in the scheduler + in a runnable state before actually running. */ package metrics diff --git a/libgo/go/runtime/metrics_test.go b/libgo/go/runtime/metrics_test.go index 8a3cf01..5d32ef4 100644 --- a/libgo/go/runtime/metrics_test.go +++ b/libgo/go/runtime/metrics_test.go @@ -40,6 +40,9 @@ func TestReadMetrics(t *testing.T) { } // Check to make sure the values we read line up with other values we read. + var allocsBySize *metrics.Float64Histogram + var tinyAllocs uint64 + var mallocs, frees uint64 for i := range samples { switch name := samples[i].Name; name { case "/memory/classes/heap/free:bytes": @@ -84,6 +87,9 @@ func TestReadMetrics(t *testing.T) { t.Errorf("histogram counts do not much BySize for class %d: got %d, want %d", i, c, m) } } + allocsBySize = hist + case "/gc/heap/allocs:bytes": + checkUint64(t, name, samples[i].Value.Uint64(), mstats.TotalAlloc) case "/gc/heap/frees-by-size:bytes": hist := samples[i].Value.Float64Histogram() // Skip size class 0 in BySize, because it's always empty and not represented @@ -95,9 +101,29 @@ func TestReadMetrics(t *testing.T) { continue } if c, f := hist.Counts[i], sc.Frees; c != f { - t.Errorf("histogram counts do not much BySize for class %d: got %d, want %d", i, c, f) + t.Errorf("histogram counts do not match BySize for class %d: got %d, want %d", i, c, f) } } + case "/gc/heap/frees:bytes": + checkUint64(t, name, samples[i].Value.Uint64(), mstats.TotalAlloc-mstats.HeapAlloc) + case "/gc/heap/tiny/allocs:objects": + // Currently, MemStats adds tiny alloc count to both Mallocs AND Frees. + // The reason for this is because MemStats couldn't be extended at the time + // but there was a desire to have Mallocs at least be a little more representative, + // while having Mallocs - Frees still represent a live object count. + // Unfortunately, MemStats doesn't actually export a large allocation count, + // so it's impossible to pull this number out directly. + // + // Check tiny allocation count outside of this loop, by using the allocs-by-size + // histogram in order to figure out how many large objects there are. + tinyAllocs = samples[i].Value.Uint64() + // Because the next two metrics tests are checking against Mallocs and Frees, + // we can't check them directly for the same reason: we need to account for tiny + // allocations included in Mallocs and Frees. + case "/gc/heap/allocs:objects": + mallocs = samples[i].Value.Uint64() + case "/gc/heap/frees:objects": + frees = samples[i].Value.Uint64() case "/gc/heap/objects:objects": checkUint64(t, name, samples[i].Value.Uint64(), mstats.HeapObjects) case "/gc/heap/goal:bytes": @@ -110,6 +136,17 @@ func TestReadMetrics(t *testing.T) { checkUint64(t, name, samples[i].Value.Uint64(), uint64(mstats.NumGC)) } } + + // Check tinyAllocs. + nonTinyAllocs := uint64(0) + for _, c := range allocsBySize.Counts { + nonTinyAllocs += c + } + checkUint64(t, "/gc/heap/tiny/allocs:objects", tinyAllocs, mstats.Mallocs-nonTinyAllocs) + + // Check allocation and free counts. + checkUint64(t, "/gc/heap/allocs:objects", mallocs, mstats.Mallocs-tinyAllocs) + checkUint64(t, "/gc/heap/frees:objects", frees, mstats.Frees-tinyAllocs) } func TestReadMetricsConsistency(t *testing.T) { @@ -132,8 +169,10 @@ func TestReadMetricsConsistency(t *testing.T) { got, want uint64 } var objects struct { - alloc, free *metrics.Float64Histogram - total uint64 + alloc, free *metrics.Float64Histogram + allocs, frees uint64 + allocdBytes, freedBytes uint64 + total, totalBytes uint64 } var gc struct { numGC uint64 @@ -159,10 +198,20 @@ func TestReadMetricsConsistency(t *testing.T) { switch samples[i].Name { case "/memory/classes/total:bytes": totalVirtual.got = samples[i].Value.Uint64() + case "/memory/classes/heap/objects:bytes": + objects.totalBytes = samples[i].Value.Uint64() case "/gc/heap/objects:objects": objects.total = samples[i].Value.Uint64() + case "/gc/heap/allocs:bytes": + objects.allocdBytes = samples[i].Value.Uint64() + case "/gc/heap/allocs:objects": + objects.allocs = samples[i].Value.Uint64() case "/gc/heap/allocs-by-size:bytes": objects.alloc = samples[i].Value.Float64Histogram() + case "/gc/heap/frees:bytes": + objects.freedBytes = samples[i].Value.Uint64() + case "/gc/heap/frees:objects": + objects.frees = samples[i].Value.Uint64() case "/gc/heap/frees-by-size:bytes": objects.free = samples[i].Value.Float64Histogram() case "/gc/cycles:gc-cycles": @@ -182,6 +231,12 @@ func TestReadMetricsConsistency(t *testing.T) { if totalVirtual.got != totalVirtual.want { t.Errorf(`"/memory/classes/total:bytes" does not match sum of /memory/classes/**: got %d, want %d`, totalVirtual.got, totalVirtual.want) } + if got, want := objects.allocs-objects.frees, objects.total; got != want { + t.Errorf("mismatch between object alloc/free tallies and total: got %d, want %d", got, want) + } + if got, want := objects.allocdBytes-objects.freedBytes, objects.totalBytes; got != want { + t.Errorf("mismatch between object alloc/free tallies and total: got %d, want %d", got, want) + } if b, c := len(objects.alloc.Buckets), len(objects.alloc.Counts); b != c+1 { t.Errorf("allocs-by-size has wrong bucket or counts length: %d buckets, %d counts", b, c) } @@ -201,17 +256,25 @@ func TestReadMetricsConsistency(t *testing.T) { } } if !t.Failed() { - got, want := uint64(0), objects.total + var gotAlloc, gotFree uint64 + want := objects.total for i := range objects.alloc.Counts { if objects.alloc.Counts[i] < objects.free.Counts[i] { t.Errorf("found more allocs than frees in object dist bucket %d", i) continue } - got += objects.alloc.Counts[i] - objects.free.Counts[i] + gotAlloc += objects.alloc.Counts[i] + gotFree += objects.free.Counts[i] } - if got != want { + if got := gotAlloc - gotFree; got != want { t.Errorf("object distribution counts don't match count of live objects: got %d, want %d", got, want) } + if gotAlloc != objects.allocs { + t.Errorf("object distribution counts don't match total allocs: got %d, want %d", gotAlloc, objects.allocs) + } + if gotFree != objects.frees { + t.Errorf("object distribution counts don't match total allocs: got %d, want %d", gotFree, objects.frees) + } } } // The current GC has at least 2 pauses per GC. diff --git a/libgo/go/runtime/mgc.go b/libgo/go/runtime/mgc.go index a9f2c1a..efb8012 100644 --- a/libgo/go/runtime/mgc.go +++ b/libgo/go/runtime/mgc.go @@ -113,8 +113,8 @@ // Next GC is after we've allocated an extra amount of memory proportional to // the amount already in use. The proportion is controlled by GOGC environment variable // (100 by default). If GOGC=100 and we're using 4M, we'll GC again when we get to 8M -// (this mark is tracked in next_gc variable). This keeps the GC cost in linear -// proportion to the allocation cost. Adjusting GOGC just changes the linear constant +// (this mark is tracked in gcController.heapGoal variable). This keeps the GC cost in +// linear proportion to the allocation cost. Adjusting GOGC just changes the linear constant // (and also the amount of extra memory used). // Oblets @@ -149,45 +149,16 @@ const ( sweepMinHeapDistance = 1024 * 1024 ) -// heapminimum is the minimum heap size at which to trigger GC. -// For small heaps, this overrides the usual GOGC*live set rule. -// -// When there is a very small live set but a lot of allocation, simply -// collecting when the heap reaches GOGC*live results in many GC -// cycles and high total per-GC overhead. This minimum amortizes this -// per-GC overhead while keeping the heap reasonably small. -// -// During initialization this is set to 4MB*GOGC/100. In the case of -// GOGC==0, this will set heapminimum to 0, resulting in constant -// collection even when the heap size is small, which is useful for -// debugging. -var heapminimum uint64 = defaultHeapMinimum - -// defaultHeapMinimum is the value of heapminimum for GOGC==100. -const defaultHeapMinimum = 4 << 20 - -// Initialized from $GOGC. GOGC=off means no GC. -var gcpercent int32 - func gcinit() { if unsafe.Sizeof(workbuf{}) != _WorkbufSize { throw("size of Workbuf is suboptimal") } - // No sweep on the first cycle. - mheap_.sweepdone = 1 + mheap_.sweepDrained = 1 - // Set a reasonable initial GC trigger. - memstats.triggerRatio = 7 / 8.0 - - // Fake a heap_marked value so it looks like a trigger at - // heapminimum is the appropriate growth from heap_marked. - // This will go into computing the initial GC goal. - memstats.heap_marked = uint64(float64(heapminimum) / (1 + memstats.triggerRatio)) - - // Set gcpercent from the environment. This will also compute - // and set the GC trigger and goal. - _ = setGCPercent(readgogc()) + // Initialize GC pacer state. + // Use the environment variable GOGC for the initial gcPercent value. + gcController.init(readGOGC()) work.startSema = 1 work.markDoneSema = 1 @@ -196,16 +167,9 @@ func gcinit() { lockInit(&work.wbufSpans.lock, lockRankWbufSpans) } -func readgogc() int32 { - p := gogetenv("GOGC") - if p == "off" { - return -1 - } - if n, ok := atoi32(p); ok { - return n - } - return 100 -} +// Temporary in order to enable register ABI work. +// TODO(register args): convert back to local chan in gcenabled, passed to "go" stmts. +var gcenable_setup chan int // gcenable is called after the bulk of the runtime initialization, // just before we're about to start letting user code run. @@ -213,41 +177,17 @@ func readgogc() int32 { // scavenger goroutine, and enables GC. func gcenable() { // Kick off sweeping and scavenging. - c := make(chan int, 2) + gcenable_setup = make(chan int, 2) expectSystemGoroutine() - go bgsweep(c) + go bgsweep() expectSystemGoroutine() - go bgscavenge(c) - <-c - <-c + go bgscavenge() + <-gcenable_setup + <-gcenable_setup + gcenable_setup = nil memstats.enablegc = true // now that runtime is initialized, GC is okay } -//go:linkname setGCPercent runtime_1debug.setGCPercent -func setGCPercent(in int32) (out int32) { - // Run on the system stack since we grab the heap lock. - systemstack(func() { - lock(&mheap_.lock) - out = gcpercent - if in < 0 { - in = -1 - } - gcpercent = in - heapminimum = defaultHeapMinimum * uint64(gcpercent) / 100 - // Update pacing in response to gcpercent change. - gcSetTriggerRatio(memstats.triggerRatio) - unlock(&mheap_.lock) - }) - - // If we just disabled GC, wait for any concurrent GC mark to - // finish so we always return with no GC running. - if in < 0 { - gcWaitOnMark(atomic.Load(&work.cycles)) - } - - return out -} - // Garbage collector phase. // Indicates to write barrier and synchronization task to perform. var gcphase uint32 @@ -304,9 +244,11 @@ const ( // gcMarkWorkerFractionalMode indicates that a P is currently // running the "fractional" mark worker. The fractional worker // is necessary when GOMAXPROCS*gcBackgroundUtilization is not - // an integer. The fractional worker should run until it is - // preempted and will be scheduled to pick up the fractional - // part of GOMAXPROCS*gcBackgroundUtilization. + // an integer and using only dedicated workers would result in + // utilization too far from the target of gcBackgroundUtilization. + // The fractional worker should run until it is preempted and + // will be scheduled to pick up the fractional part of + // GOMAXPROCS*gcBackgroundUtilization. gcMarkWorkerFractionalMode // gcMarkWorkerIdleMode indicates that a P is running the mark @@ -325,474 +267,6 @@ var gcMarkWorkerModeStrings = [...]string{ "GC (idle)", } -// gcController implements the GC pacing controller that determines -// when to trigger concurrent garbage collection and how much marking -// work to do in mutator assists and background marking. -// -// It uses a feedback control algorithm to adjust the memstats.gc_trigger -// trigger based on the heap growth and GC CPU utilization each cycle. -// This algorithm optimizes for heap growth to match GOGC and for CPU -// utilization between assist and background marking to be 25% of -// GOMAXPROCS. The high-level design of this algorithm is documented -// at https://golang.org/s/go15gcpacing. -// -// All fields of gcController are used only during a single mark -// cycle. -var gcController gcControllerState - -type gcControllerState struct { - // scanWork is the total scan work performed this cycle. This - // is updated atomically during the cycle. Updates occur in - // bounded batches, since it is both written and read - // throughout the cycle. At the end of the cycle, this is how - // much of the retained heap is scannable. - // - // Currently this is the bytes of heap scanned. For most uses, - // this is an opaque unit of work, but for estimation the - // definition is important. - scanWork int64 - - // bgScanCredit is the scan work credit accumulated by the - // concurrent background scan. This credit is accumulated by - // the background scan and stolen by mutator assists. This is - // updated atomically. Updates occur in bounded batches, since - // it is both written and read throughout the cycle. - bgScanCredit int64 - - // assistTime is the nanoseconds spent in mutator assists - // during this cycle. This is updated atomically. Updates - // occur in bounded batches, since it is both written and read - // throughout the cycle. - assistTime int64 - - // dedicatedMarkTime is the nanoseconds spent in dedicated - // mark workers during this cycle. This is updated atomically - // at the end of the concurrent mark phase. - dedicatedMarkTime int64 - - // fractionalMarkTime is the nanoseconds spent in the - // fractional mark worker during this cycle. This is updated - // atomically throughout the cycle and will be up-to-date if - // the fractional mark worker is not currently running. - fractionalMarkTime int64 - - // idleMarkTime is the nanoseconds spent in idle marking - // during this cycle. This is updated atomically throughout - // the cycle. - idleMarkTime int64 - - // markStartTime is the absolute start time in nanoseconds - // that assists and background mark workers started. - markStartTime int64 - - // dedicatedMarkWorkersNeeded is the number of dedicated mark - // workers that need to be started. This is computed at the - // beginning of each cycle and decremented atomically as - // dedicated mark workers get started. - dedicatedMarkWorkersNeeded int64 - - // assistWorkPerByte is the ratio of scan work to allocated - // bytes that should be performed by mutator assists. This is - // computed at the beginning of each cycle and updated every - // time heap_scan is updated. - // - // Stored as a uint64, but it's actually a float64. Use - // float64frombits to get the value. - // - // Read and written atomically. - assistWorkPerByte uint64 - - // assistBytesPerWork is 1/assistWorkPerByte. - // - // Stored as a uint64, but it's actually a float64. Use - // float64frombits to get the value. - // - // Read and written atomically. - // - // Note that because this is read and written independently - // from assistWorkPerByte users may notice a skew between - // the two values, and such a state should be safe. - assistBytesPerWork uint64 - - // fractionalUtilizationGoal is the fraction of wall clock - // time that should be spent in the fractional mark worker on - // each P that isn't running a dedicated worker. - // - // For example, if the utilization goal is 25% and there are - // no dedicated workers, this will be 0.25. If the goal is - // 25%, there is one dedicated worker, and GOMAXPROCS is 5, - // this will be 0.05 to make up the missing 5%. - // - // If this is zero, no fractional workers are needed. - fractionalUtilizationGoal float64 - - _ cpu.CacheLinePad -} - -// startCycle resets the GC controller's state and computes estimates -// for a new GC cycle. The caller must hold worldsema and the world -// must be stopped. -func (c *gcControllerState) startCycle() { - c.scanWork = 0 - c.bgScanCredit = 0 - c.assistTime = 0 - c.dedicatedMarkTime = 0 - c.fractionalMarkTime = 0 - c.idleMarkTime = 0 - - // Ensure that the heap goal is at least a little larger than - // the current live heap size. This may not be the case if GC - // start is delayed or if the allocation that pushed heap_live - // over gc_trigger is large or if the trigger is really close to - // GOGC. Assist is proportional to this distance, so enforce a - // minimum distance, even if it means going over the GOGC goal - // by a tiny bit. - if memstats.next_gc < memstats.heap_live+1024*1024 { - memstats.next_gc = memstats.heap_live + 1024*1024 - } - - // Compute the background mark utilization goal. In general, - // this may not come out exactly. We round the number of - // dedicated workers so that the utilization is closest to - // 25%. For small GOMAXPROCS, this would introduce too much - // error, so we add fractional workers in that case. - totalUtilizationGoal := float64(gomaxprocs) * gcBackgroundUtilization - c.dedicatedMarkWorkersNeeded = int64(totalUtilizationGoal + 0.5) - utilError := float64(c.dedicatedMarkWorkersNeeded)/totalUtilizationGoal - 1 - const maxUtilError = 0.3 - if utilError < -maxUtilError || utilError > maxUtilError { - // Rounding put us more than 30% off our goal. With - // gcBackgroundUtilization of 25%, this happens for - // GOMAXPROCS<=3 or GOMAXPROCS=6. Enable fractional - // workers to compensate. - if float64(c.dedicatedMarkWorkersNeeded) > totalUtilizationGoal { - // Too many dedicated workers. - c.dedicatedMarkWorkersNeeded-- - } - c.fractionalUtilizationGoal = (totalUtilizationGoal - float64(c.dedicatedMarkWorkersNeeded)) / float64(gomaxprocs) - } else { - c.fractionalUtilizationGoal = 0 - } - - // In STW mode, we just want dedicated workers. - if debug.gcstoptheworld > 0 { - c.dedicatedMarkWorkersNeeded = int64(gomaxprocs) - c.fractionalUtilizationGoal = 0 - } - - // Clear per-P state - for _, p := range allp { - p.gcAssistTime = 0 - p.gcFractionalMarkTime = 0 - } - - // Compute initial values for controls that are updated - // throughout the cycle. - c.revise() - - if debug.gcpacertrace > 0 { - assistRatio := float64frombits(atomic.Load64(&c.assistWorkPerByte)) - print("pacer: assist ratio=", assistRatio, - " (scan ", memstats.heap_scan>>20, " MB in ", - work.initialHeapLive>>20, "->", - memstats.next_gc>>20, " MB)", - " workers=", c.dedicatedMarkWorkersNeeded, - "+", c.fractionalUtilizationGoal, "\n") - } -} - -// revise updates the assist ratio during the GC cycle to account for -// improved estimates. This should be called whenever memstats.heap_scan, -// memstats.heap_live, or memstats.next_gc is updated. It is safe to -// call concurrently, but it may race with other calls to revise. -// -// The result of this race is that the two assist ratio values may not line -// up or may be stale. In practice this is OK because the assist ratio -// moves slowly throughout a GC cycle, and the assist ratio is a best-effort -// heuristic anyway. Furthermore, no part of the heuristic depends on -// the two assist ratio values being exact reciprocals of one another, since -// the two values are used to convert values from different sources. -// -// The worst case result of this raciness is that we may miss a larger shift -// in the ratio (say, if we decide to pace more aggressively against the -// hard heap goal) but even this "hard goal" is best-effort (see #40460). -// The dedicated GC should ensure we don't exceed the hard goal by too much -// in the rare case we do exceed it. -// -// It should only be called when gcBlackenEnabled != 0 (because this -// is when assists are enabled and the necessary statistics are -// available). -func (c *gcControllerState) revise() { - gcpercent := gcpercent - if gcpercent < 0 { - // If GC is disabled but we're running a forced GC, - // act like GOGC is huge for the below calculations. - gcpercent = 100000 - } - live := atomic.Load64(&memstats.heap_live) - scan := atomic.Load64(&memstats.heap_scan) - work := atomic.Loadint64(&c.scanWork) - - // Assume we're under the soft goal. Pace GC to complete at - // next_gc assuming the heap is in steady-state. - heapGoal := int64(atomic.Load64(&memstats.next_gc)) - - // Compute the expected scan work remaining. - // - // This is estimated based on the expected - // steady-state scannable heap. For example, with - // GOGC=100, only half of the scannable heap is - // expected to be live, so that's what we target. - // - // (This is a float calculation to avoid overflowing on - // 100*heap_scan.) - scanWorkExpected := int64(float64(scan) * 100 / float64(100+gcpercent)) - - if int64(live) > heapGoal || work > scanWorkExpected { - // We're past the soft goal, or we've already done more scan - // work than we expected. Pace GC so that in the worst case it - // will complete by the hard goal. - const maxOvershoot = 1.1 - heapGoal = int64(float64(heapGoal) * maxOvershoot) - - // Compute the upper bound on the scan work remaining. - scanWorkExpected = int64(scan) - } - - // Compute the remaining scan work estimate. - // - // Note that we currently count allocations during GC as both - // scannable heap (heap_scan) and scan work completed - // (scanWork), so allocation will change this difference - // slowly in the soft regime and not at all in the hard - // regime. - scanWorkRemaining := scanWorkExpected - work - if scanWorkRemaining < 1000 { - // We set a somewhat arbitrary lower bound on - // remaining scan work since if we aim a little high, - // we can miss by a little. - // - // We *do* need to enforce that this is at least 1, - // since marking is racy and double-scanning objects - // may legitimately make the remaining scan work - // negative, even in the hard goal regime. - scanWorkRemaining = 1000 - } - - // Compute the heap distance remaining. - heapRemaining := heapGoal - int64(live) - if heapRemaining <= 0 { - // This shouldn't happen, but if it does, avoid - // dividing by zero or setting the assist negative. - heapRemaining = 1 - } - - // Compute the mutator assist ratio so by the time the mutator - // allocates the remaining heap bytes up to next_gc, it will - // have done (or stolen) the remaining amount of scan work. - // Note that the assist ratio values are updated atomically - // but not together. This means there may be some degree of - // skew between the two values. This is generally OK as the - // values shift relatively slowly over the course of a GC - // cycle. - assistWorkPerByte := float64(scanWorkRemaining) / float64(heapRemaining) - assistBytesPerWork := float64(heapRemaining) / float64(scanWorkRemaining) - atomic.Store64(&c.assistWorkPerByte, float64bits(assistWorkPerByte)) - atomic.Store64(&c.assistBytesPerWork, float64bits(assistBytesPerWork)) -} - -// endCycle computes the trigger ratio for the next cycle. -func (c *gcControllerState) endCycle() float64 { - if work.userForced { - // Forced GC means this cycle didn't start at the - // trigger, so where it finished isn't good - // information about how to adjust the trigger. - // Just leave it where it is. - return memstats.triggerRatio - } - - // Proportional response gain for the trigger controller. Must - // be in [0, 1]. Lower values smooth out transient effects but - // take longer to respond to phase changes. Higher values - // react to phase changes quickly, but are more affected by - // transient changes. Values near 1 may be unstable. - const triggerGain = 0.5 - - // Compute next cycle trigger ratio. First, this computes the - // "error" for this cycle; that is, how far off the trigger - // was from what it should have been, accounting for both heap - // growth and GC CPU utilization. We compute the actual heap - // growth during this cycle and scale that by how far off from - // the goal CPU utilization we were (to estimate the heap - // growth if we had the desired CPU utilization). The - // difference between this estimate and the GOGC-based goal - // heap growth is the error. - goalGrowthRatio := gcEffectiveGrowthRatio() - actualGrowthRatio := float64(memstats.heap_live)/float64(memstats.heap_marked) - 1 - assistDuration := nanotime() - c.markStartTime - - // Assume background mark hit its utilization goal. - utilization := gcBackgroundUtilization - // Add assist utilization; avoid divide by zero. - if assistDuration > 0 { - utilization += float64(c.assistTime) / float64(assistDuration*int64(gomaxprocs)) - } - - triggerError := goalGrowthRatio - memstats.triggerRatio - utilization/gcGoalUtilization*(actualGrowthRatio-memstats.triggerRatio) - - // Finally, we adjust the trigger for next time by this error, - // damped by the proportional gain. - triggerRatio := memstats.triggerRatio + triggerGain*triggerError - - if debug.gcpacertrace > 0 { - // Print controller state in terms of the design - // document. - H_m_prev := memstats.heap_marked - h_t := memstats.triggerRatio - H_T := memstats.gc_trigger - h_a := actualGrowthRatio - H_a := memstats.heap_live - h_g := goalGrowthRatio - H_g := int64(float64(H_m_prev) * (1 + h_g)) - u_a := utilization - u_g := gcGoalUtilization - W_a := c.scanWork - print("pacer: H_m_prev=", H_m_prev, - " h_t=", h_t, " H_T=", H_T, - " h_a=", h_a, " H_a=", H_a, - " h_g=", h_g, " H_g=", H_g, - " u_a=", u_a, " u_g=", u_g, - " W_a=", W_a, - " goalΔ=", goalGrowthRatio-h_t, - " actualΔ=", h_a-h_t, - " u_a/u_g=", u_a/u_g, - "\n") - } - - return triggerRatio -} - -// enlistWorker encourages another dedicated mark worker to start on -// another P if there are spare worker slots. It is used by putfull -// when more work is made available. -// -//go:nowritebarrier -func (c *gcControllerState) enlistWorker() { - // If there are idle Ps, wake one so it will run an idle worker. - // NOTE: This is suspected of causing deadlocks. See golang.org/issue/19112. - // - // if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 { - // wakep() - // return - // } - - // There are no idle Ps. If we need more dedicated workers, - // try to preempt a running P so it will switch to a worker. - if c.dedicatedMarkWorkersNeeded <= 0 { - return - } - // Pick a random other P to preempt. - if gomaxprocs <= 1 { - return - } - gp := getg() - if gp == nil || gp.m == nil || gp.m.p == 0 { - return - } - myID := gp.m.p.ptr().id - for tries := 0; tries < 5; tries++ { - id := int32(fastrandn(uint32(gomaxprocs - 1))) - if id >= myID { - id++ - } - p := allp[id] - if p.status != _Prunning { - continue - } - if preemptone(p) { - return - } - } -} - -// findRunnableGCWorker returns a background mark worker for _p_ if it -// should be run. This must only be called when gcBlackenEnabled != 0. -func (c *gcControllerState) findRunnableGCWorker(_p_ *p) *g { - if gcBlackenEnabled == 0 { - throw("gcControllerState.findRunnable: blackening not enabled") - } - - if !gcMarkWorkAvailable(_p_) { - // No work to be done right now. This can happen at - // the end of the mark phase when there are still - // assists tapering off. Don't bother running a worker - // now because it'll just return immediately. - return nil - } - - // Grab a worker before we commit to running below. - node := (*gcBgMarkWorkerNode)(gcBgMarkWorkerPool.pop()) - if node == nil { - // There is at least one worker per P, so normally there are - // enough workers to run on all Ps, if necessary. However, once - // a worker enters gcMarkDone it may park without rejoining the - // pool, thus freeing a P with no corresponding worker. - // gcMarkDone never depends on another worker doing work, so it - // is safe to simply do nothing here. - // - // If gcMarkDone bails out without completing the mark phase, - // it will always do so with queued global work. Thus, that P - // will be immediately eligible to re-run the worker G it was - // just using, ensuring work can complete. - return nil - } - - decIfPositive := func(ptr *int64) bool { - for { - v := atomic.Loadint64(ptr) - if v <= 0 { - return false - } - - // TODO: having atomic.Casint64 would be more pleasant. - if atomic.Cas64((*uint64)(unsafe.Pointer(ptr)), uint64(v), uint64(v-1)) { - return true - } - } - } - - if decIfPositive(&c.dedicatedMarkWorkersNeeded) { - // This P is now dedicated to marking until the end of - // the concurrent mark phase. - _p_.gcMarkWorkerMode = gcMarkWorkerDedicatedMode - } else if c.fractionalUtilizationGoal == 0 { - // No need for fractional workers. - gcBgMarkWorkerPool.push(&node.node) - return nil - } else { - // Is this P behind on the fractional utilization - // goal? - // - // This should be kept in sync with pollFractionalWorkerExit. - delta := nanotime() - gcController.markStartTime - if delta > 0 && float64(_p_.gcFractionalMarkTime)/float64(delta) > c.fractionalUtilizationGoal { - // Nope. No need to run a fractional worker. - gcBgMarkWorkerPool.push(&node.node) - return nil - } - // Run a fractional worker. - _p_.gcMarkWorkerMode = gcMarkWorkerFractionalMode - } - - // Run the background mark worker. - gp := node.gp.ptr() - casgstatus(gp, _Gwaiting, _Grunnable) - if trace.enabled { - traceGoUnpark(gp, 0) - } - return gp -} - // pollFractionalWorkerExit reports whether a fractional mark worker // should self-preempt. It assumes it is called from the fractional // worker. @@ -811,203 +285,6 @@ func pollFractionalWorkerExit() bool { return float64(selfTime)/float64(delta) > 1.2*gcController.fractionalUtilizationGoal } -// gcSetTriggerRatio sets the trigger ratio and updates everything -// derived from it: the absolute trigger, the heap goal, mark pacing, -// and sweep pacing. -// -// This can be called any time. If GC is the in the middle of a -// concurrent phase, it will adjust the pacing of that phase. -// -// This depends on gcpercent, memstats.heap_marked, and -// memstats.heap_live. These must be up to date. -// -// mheap_.lock must be held or the world must be stopped. -func gcSetTriggerRatio(triggerRatio float64) { - assertWorldStoppedOrLockHeld(&mheap_.lock) - - // Compute the next GC goal, which is when the allocated heap - // has grown by GOGC/100 over the heap marked by the last - // cycle. - goal := ^uint64(0) - if gcpercent >= 0 { - goal = memstats.heap_marked + memstats.heap_marked*uint64(gcpercent)/100 - } - - // Set the trigger ratio, capped to reasonable bounds. - if gcpercent >= 0 { - scalingFactor := float64(gcpercent) / 100 - // Ensure there's always a little margin so that the - // mutator assist ratio isn't infinity. - maxTriggerRatio := 0.95 * scalingFactor - if triggerRatio > maxTriggerRatio { - triggerRatio = maxTriggerRatio - } - - // If we let triggerRatio go too low, then if the application - // is allocating very rapidly we might end up in a situation - // where we're allocating black during a nearly always-on GC. - // The result of this is a growing heap and ultimately an - // increase in RSS. By capping us at a point >0, we're essentially - // saying that we're OK using more CPU during the GC to prevent - // this growth in RSS. - // - // The current constant was chosen empirically: given a sufficiently - // fast/scalable allocator with 48 Ps that could drive the trigger ratio - // to <0.05, this constant causes applications to retain the same peak - // RSS compared to not having this allocator. - minTriggerRatio := 0.6 * scalingFactor - if triggerRatio < minTriggerRatio { - triggerRatio = minTriggerRatio - } - } else if triggerRatio < 0 { - // gcpercent < 0, so just make sure we're not getting a negative - // triggerRatio. This case isn't expected to happen in practice, - // and doesn't really matter because if gcpercent < 0 then we won't - // ever consume triggerRatio further on in this function, but let's - // just be defensive here; the triggerRatio being negative is almost - // certainly undesirable. - triggerRatio = 0 - } - memstats.triggerRatio = triggerRatio - - // Compute the absolute GC trigger from the trigger ratio. - // - // We trigger the next GC cycle when the allocated heap has - // grown by the trigger ratio over the marked heap size. - trigger := ^uint64(0) - if gcpercent >= 0 { - trigger = uint64(float64(memstats.heap_marked) * (1 + triggerRatio)) - // Don't trigger below the minimum heap size. - minTrigger := heapminimum - if !isSweepDone() { - // Concurrent sweep happens in the heap growth - // from heap_live to gc_trigger, so ensure - // that concurrent sweep has some heap growth - // in which to perform sweeping before we - // start the next GC cycle. - sweepMin := atomic.Load64(&memstats.heap_live) + sweepMinHeapDistance - if sweepMin > minTrigger { - minTrigger = sweepMin - } - } - if trigger < minTrigger { - trigger = minTrigger - } - if int64(trigger) < 0 { - print("runtime: next_gc=", memstats.next_gc, " heap_marked=", memstats.heap_marked, " heap_live=", memstats.heap_live, " initialHeapLive=", work.initialHeapLive, "triggerRatio=", triggerRatio, " minTrigger=", minTrigger, "\n") - throw("gc_trigger underflow") - } - if trigger > goal { - // The trigger ratio is always less than GOGC/100, but - // other bounds on the trigger may have raised it. - // Push up the goal, too. - goal = trigger - } - } - - // Commit to the trigger and goal. - memstats.gc_trigger = trigger - atomic.Store64(&memstats.next_gc, goal) - if trace.enabled { - traceNextGC() - } - - // Update mark pacing. - if gcphase != _GCoff { - gcController.revise() - } - - // Update sweep pacing. - if isSweepDone() { - mheap_.sweepPagesPerByte = 0 - } else { - // Concurrent sweep needs to sweep all of the in-use - // pages by the time the allocated heap reaches the GC - // trigger. Compute the ratio of in-use pages to sweep - // per byte allocated, accounting for the fact that - // some might already be swept. - heapLiveBasis := atomic.Load64(&memstats.heap_live) - heapDistance := int64(trigger) - int64(heapLiveBasis) - // Add a little margin so rounding errors and - // concurrent sweep are less likely to leave pages - // unswept when GC starts. - heapDistance -= 1024 * 1024 - if heapDistance < _PageSize { - // Avoid setting the sweep ratio extremely high - heapDistance = _PageSize - } - pagesSwept := atomic.Load64(&mheap_.pagesSwept) - pagesInUse := atomic.Load64(&mheap_.pagesInUse) - sweepDistancePages := int64(pagesInUse) - int64(pagesSwept) - if sweepDistancePages <= 0 { - mheap_.sweepPagesPerByte = 0 - } else { - mheap_.sweepPagesPerByte = float64(sweepDistancePages) / float64(heapDistance) - mheap_.sweepHeapLiveBasis = heapLiveBasis - // Write pagesSweptBasis last, since this - // signals concurrent sweeps to recompute - // their debt. - atomic.Store64(&mheap_.pagesSweptBasis, pagesSwept) - } - } - - gcPaceScavenger() -} - -// gcEffectiveGrowthRatio returns the current effective heap growth -// ratio (GOGC/100) based on heap_marked from the previous GC and -// next_gc for the current GC. -// -// This may differ from gcpercent/100 because of various upper and -// lower bounds on gcpercent. For example, if the heap is smaller than -// heapminimum, this can be higher than gcpercent/100. -// -// mheap_.lock must be held or the world must be stopped. -func gcEffectiveGrowthRatio() float64 { - assertWorldStoppedOrLockHeld(&mheap_.lock) - - egogc := float64(atomic.Load64(&memstats.next_gc)-memstats.heap_marked) / float64(memstats.heap_marked) - if egogc < 0 { - // Shouldn't happen, but just in case. - egogc = 0 - } - return egogc -} - -// gcGoalUtilization is the goal CPU utilization for -// marking as a fraction of GOMAXPROCS. -const gcGoalUtilization = 0.30 - -// gcBackgroundUtilization is the fixed CPU utilization for background -// marking. It must be <= gcGoalUtilization. The difference between -// gcGoalUtilization and gcBackgroundUtilization will be made up by -// mark assists. The scheduler will aim to use within 50% of this -// goal. -// -// Setting this to < gcGoalUtilization avoids saturating the trigger -// feedback controller when there are no assists, which allows it to -// better control CPU and heap growth. However, the larger the gap, -// the more mutator assists are expected to happen, which impact -// mutator latency. -const gcBackgroundUtilization = 0.25 - -// gcCreditSlack is the amount of scan work credit that can -// accumulate locally before updating gcController.scanWork and, -// optionally, gcController.bgScanCredit. Lower values give a more -// accurate assist ratio and make it more likely that assists will -// successfully steal background credit. Higher values reduce memory -// contention. -const gcCreditSlack = 2000 - -// gcAssistTimeSlack is the nanoseconds of mutator assist time that -// can accumulate on a P before updating gcController.assistTime. -const gcAssistTimeSlack = 5000 - -// gcOverAssistWork determines how many extra units of scan work a GC -// assist does when an assist happens. This amortizes the cost of an -// assist by pre-paying for this many bytes of future allocations. -const gcOverAssistWork = 64 << 10 - var work struct { full lfstack // lock-free list of full blocks workbuf empty lfstack // lock-free list of empty blocks workbuf @@ -1050,9 +327,11 @@ var work struct { nwait uint32 // Number of roots of various root types. Set by gcMarkRootPrepare. - nFlushCacheRoots int nDataRoots, nSpanRoots, nStackRoots int + // Base indexes of each root type. Set by gcMarkRootPrepare. + baseData, baseSpans, baseStacks, baseEnd uint32 + // Each type of GC state transition is protected by a lock. // Since multiple threads can simultaneously detect the state // transition condition, any thread that detects a transition @@ -1086,7 +365,7 @@ var work struct { // program started if debug.gctrace > 0. totaltime int64 - // initialHeapLive is the value of memstats.heap_live at the + // initialHeapLive is the value of gcController.heapLive at the // beginning of this GC cycle. initialHeapLive uint64 @@ -1183,7 +462,7 @@ func GC() { // First, wait for sweeping to finish. (We know there are no // more spans on the sweep queue, but we may be concurrently // sweeping spans, so we have to wait.) - for atomic.Load(&work.cycles) == n+1 && atomic.Load(&mheap_.sweepers) != 0 { + for atomic.Load(&work.cycles) == n+1 && !isSweepDone() { Gosched() } @@ -1267,13 +546,13 @@ func (t gcTrigger) test() bool { } switch t.kind { case gcTriggerHeap: - // Non-atomic access to heap_live for performance. If + // Non-atomic access to gcController.heapLive for performance. If // we are going to trigger on this, this thread just - // atomically wrote heap_live anyway and we'll see our + // atomically wrote gcController.heapLive anyway and we'll see our // own write. - return memstats.heap_live >= memstats.gc_trigger + return gcController.heapLive >= gcController.trigger case gcTriggerTime: - if gcpercent < 0 { + if gcController.gcPercent < 0 { return false } lastgc := int64(atomic.Load64(&memstats.last_gc_nanotime)) @@ -1367,7 +646,7 @@ func gcStart(trigger gcTrigger) { // so it can't be more than ncpu, even if GOMAXPROCS is. work.stwprocs = ncpu } - work.heap0 = atomic.Load64(&memstats.heap_live) + work.heap0 = atomic.Load64(&gcController.heapLive) work.pauseNS = 0 work.mode = mode @@ -1390,7 +669,7 @@ func gcStart(trigger gcTrigger) { work.cycles++ gcController.startCycle() - work.heapGoal = memstats.next_gc + work.heapGoal = gcController.heapGoal // In STW mode, disable scheduling of user Gs. This may also // disable scheduling of this goroutine, so it may block as @@ -1619,7 +898,7 @@ top: // endCycle depends on all gcWork cache stats being flushed. // The termination algorithm above ensured that up to // allocations since the ragged barrier. - nextTriggerRatio := gcController.endCycle() + nextTriggerRatio := gcController.endCycle(work.userForced) // Perform mark termination. This will restart the world. gcMarkTermination(nextTriggerRatio) @@ -1631,7 +910,7 @@ func gcMarkTermination(nextTriggerRatio float64) { // Start marktermination (write barrier remains enabled for now). setGCPhase(_GCmarktermination) - work.heap1 = memstats.heap_live + work.heap1 = gcController.heapLive startTime := nanotime() mp := acquirem() @@ -1693,12 +972,12 @@ func gcMarkTermination(nextTriggerRatio float64) { throw("gc done but gcphase != _GCoff") } - // Record next_gc and heap_inuse for scavenger. - memstats.last_next_gc = memstats.next_gc + // Record heapGoal and heap_inuse for scavenger. + gcController.lastHeapGoal = gcController.heapGoal memstats.last_heap_inuse = memstats.heap_inuse // Update GC trigger and pacing for the next cycle. - gcSetTriggerRatio(nextTriggerRatio) + gcController.commit(nextTriggerRatio) // Update timing memstats now := nanotime() @@ -1745,6 +1024,13 @@ func gcMarkTermination(nextTriggerRatio float64) { // so events don't leak into the wrong cycle. mProf_NextCycle() + // There may be stale spans in mcaches that need to be swept. + // Those aren't tracked in any sweep lists, so we need to + // count them against sweep completion until we ensure all + // those spans have been forced out. + sl := newSweepLocker() + sl.blockCompletion() + systemstack(func() { startTheWorldWithSema(true) }) // Flush the heap profile so we can start a new cycle next GC. @@ -1765,6 +1051,9 @@ func gcMarkTermination(nextTriggerRatio float64) { _p_.mcache.prepareForSweep() }) }) + // Now that we've swept stale spans in mcaches, they don't + // count against unswept spans. + sl.dispose() // Print gctrace before dropping worldsema. As soon as we drop // worldsema another cycle could start and smash the stats @@ -1986,15 +1275,11 @@ func gcBgMarkWorker() { // everything out of the run // queue so it can run // somewhere else. - lock(&sched.lock) - for { - gp, _ := runqget(pp) - if gp == nil { - break - } - globrunqput(gp) + if drainQ, n := runqdrain(pp); n > 0 { + lock(&sched.lock) + globrunqputbatch(&drainQ, int32(n)) + unlock(&sched.lock) } - unlock(&sched.lock) } // Go back to draining, this time // without preemption. @@ -2068,7 +1353,7 @@ func gcMarkWorkAvailable(p *p) bool { // gcMark runs the mark (or, for concurrent GC, mark termination) // All gcWork caches must be empty. // STW is in effect at this point. -func gcMark(start_time int64) { +func gcMark(startTime int64) { if debug.allocfreetrace > 0 { tracegc() } @@ -2076,7 +1361,7 @@ func gcMark(start_time int64) { if gcphase != _GCmarktermination { throw("in gcMark expecting to see gcphase as _GCmarktermination") } - work.tstart = start_time + work.tstart = startTime // Check that there's no marking work remaining. if work.full != 0 || work.markrootNext < work.markrootJobs { @@ -2138,25 +1423,25 @@ func gcMark(start_time int64) { } // Update the marked heap stat. - memstats.heap_marked = work.bytesMarked + gcController.heapMarked = work.bytesMarked // Flush scanAlloc from each mcache since we're about to modify - // heap_scan directly. If we were to flush this later, then scanAlloc + // heapScan directly. If we were to flush this later, then scanAlloc // might have incorrect information. for _, p := range allp { c := p.mcache if c == nil { continue } - memstats.heap_scan += uint64(c.scanAlloc) + gcController.heapScan += uint64(c.scanAlloc) c.scanAlloc = 0 } // Update other GC heap size stats. This must happen after // cachestats (which flushes local statistics to these) and - // flushallmcaches (which modifies heap_live). - memstats.heap_live = work.bytesMarked - memstats.heap_scan = uint64(gcController.scanWork) + // flushallmcaches (which modifies gcController.heapLive). + gcController.heapLive = work.bytesMarked + gcController.heapScan = uint64(gcController.scanWork) if trace.enabled { traceHeapAlloc() @@ -2178,7 +1463,7 @@ func gcSweep(mode gcMode) { lock(&mheap_.lock) mheap_.sweepgen += 2 - mheap_.sweepdone = 0 + mheap_.sweepDrained = 0 mheap_.pagesSwept = 0 mheap_.sweepArenas = mheap_.allArenas mheap_.reclaimIndex = 0 @@ -2229,14 +1514,12 @@ func gcSweep(mode gcMode) { // //go:systemstack func gcResetMarkState() { - // This may be called during a concurrent phase, so make sure + // This may be called during a concurrent phase, so lock to make sure // allgs doesn't change. - lock(&allglock) - for _, gp := range allgs { + forEachG(func(gp *g) { gp.gcscandone = false // set to true in gcphasework gp.gcAssistBytes = 0 - } - unlock(&allglock) + }) // Clear page marks. This is just 1MB per 64GB of heap, so the // time here is pretty trivial. @@ -2251,7 +1534,7 @@ func gcResetMarkState() { } work.bytesMarked = 0 - work.initialHeapLive = atomic.Load64(&memstats.heap_live) + work.initialHeapLive = atomic.Load64(&gcController.heapLive) } // Hooks for other packages @@ -2334,3 +1617,95 @@ func fmtNSAsMS(buf []byte, ns uint64) []byte { } return itoaDiv(buf, x, dec) } + +// Helpers for testing GC. + +// gcTestIsReachable performs a GC and returns a bit set where bit i +// is set if ptrs[i] is reachable. +func gcTestIsReachable(ptrs ...unsafe.Pointer) (mask uint64) { + // This takes the pointers as unsafe.Pointers in order to keep + // them live long enough for us to attach specials. After + // that, we drop our references to them. + + if len(ptrs) > 64 { + panic("too many pointers for uint64 mask") + } + + // Block GC while we attach specials and drop our references + // to ptrs. Otherwise, if a GC is in progress, it could mark + // them reachable via this function before we have a chance to + // drop them. + semacquire(&gcsema) + + // Create reachability specials for ptrs. + specials := make([]*specialReachable, len(ptrs)) + for i, p := range ptrs { + lock(&mheap_.speciallock) + s := (*specialReachable)(mheap_.specialReachableAlloc.alloc()) + unlock(&mheap_.speciallock) + s.special.kind = _KindSpecialReachable + if !addspecial(p, &s.special) { + throw("already have a reachable special (duplicate pointer?)") + } + specials[i] = s + // Make sure we don't retain ptrs. + ptrs[i] = nil + } + + semrelease(&gcsema) + + // Force a full GC and sweep. + GC() + + // Process specials. + for i, s := range specials { + if !s.done { + printlock() + println("runtime: object", i, "was not swept") + throw("IsReachable failed") + } + if s.reachable { + mask |= 1 << i + } + lock(&mheap_.speciallock) + mheap_.specialReachableAlloc.free(unsafe.Pointer(s)) + unlock(&mheap_.speciallock) + } + + return mask +} + +// onCurrentStack reports whether the argument is on the current stack. +// It is implemented in C. +func onCurrentStack(uintptr) bool + +// getBSS returns the start of the BSS section. +// It is implemented in C. +func getBSS() uintptr + +// gcTestPointerClass returns the category of what p points to, one of: +// "heap", "stack", "data", "bss", "other". This is useful for checking +// that a test is doing what it's intended to do. +// +// This is nosplit simply to avoid extra pointer shuffling that may +// complicate a test. +// +//go:nosplit +func gcTestPointerClass(p unsafe.Pointer) string { + p2 := uintptr(noescape(p)) + if onCurrentStack(p2) { + return "stack" + } + if base, _, _ := findObject(p2, 0, 0, false); base != 0 { + return "heap" + } + bss := getBSS() + if p2 >= getText() && p2 < bss { + return "data" + } + if p2 >= bss && p2 < getEnd() { + return "bss" + } + KeepAlive(p) + return "other" +} diff --git a/libgo/go/runtime/mgcmark.go b/libgo/go/runtime/mgcmark.go index e558125..f6e1a14 100644 --- a/libgo/go/runtime/mgcmark.go +++ b/libgo/go/runtime/mgcmark.go @@ -56,8 +56,6 @@ const ( func gcMarkRootPrepare() { assertWorldStopped() - work.nFlushCacheRoots = 0 - work.nDataRoots = 0 // Only scan globals once per cycle; preferably concurrently. @@ -91,7 +89,13 @@ func gcMarkRootPrepare() { work.nStackRoots = int(atomic.Loaduintptr(&allglen)) work.markrootNext = 0 - work.markrootJobs = uint32(fixedRootCount + work.nFlushCacheRoots + work.nDataRoots + work.nSpanRoots + work.nStackRoots) + work.markrootJobs = uint32(fixedRootCount + work.nDataRoots + work.nSpanRoots + work.nStackRoots) + + // Calculate base indexes of each root type + work.baseData = uint32(fixedRootCount) + work.baseSpans = work.baseData + uint32(work.nDataRoots) + work.baseStacks = work.baseSpans + uint32(work.nSpanRoots) + work.baseEnd = work.baseStacks + uint32(work.nStackRoots) } // gcMarkRootCheck checks that all roots have been scanned. It is @@ -102,23 +106,26 @@ func gcMarkRootCheck() { throw("left over markroot jobs") } - lock(&allglock) // Check that stacks have been scanned. - var gp *g - for i := 0; i < work.nStackRoots; i++ { - gp = allgs[i] + // + // We only check the first nStackRoots Gs that we should have scanned. + // Since we don't care about newer Gs (see comment in + // gcMarkRootPrepare), no locking is required. + i := 0 + forEachGRace(func(gp *g) { + if i >= work.nStackRoots { + return + } + if !gp.gcscandone { - goto fail + println("gp", gp, "goid", gp.goid, + "status", readgstatus(gp), + "gcscandone", gp.gcscandone) + throw("scan missed a g") } - } - unlock(&allglock) - return - -fail: - println("gp", gp, "goid", gp.goid, - "status", readgstatus(gp), - "gcscandone", gp.gcscandone) - throw("scan missed a g") + + i++ + }) } // ptrmask for an allocation containing a single pointer. @@ -132,22 +139,11 @@ var oneptrmask = [...]uint8{1} // //go:nowritebarrier func markroot(gcw *gcWork, i uint32) { - // TODO(austin): This is a bit ridiculous. Compute and store - // the bases in gcMarkRootPrepare instead of the counts. - baseFlushCache := uint32(fixedRootCount) - baseData := baseFlushCache + uint32(work.nFlushCacheRoots) - baseSpans := baseData + uint32(work.nDataRoots) - baseStacks := baseSpans + uint32(work.nSpanRoots) - end := baseStacks + uint32(work.nStackRoots) - // Note: if you add a case here, please also update heapdump.go:dumproots. switch { - case baseFlushCache <= i && i < baseData: - flushmcache(int(i - baseFlushCache)) - - case baseData <= i && i < baseSpans: + case work.baseData <= i && i < work.baseSpans: roots := gcRoots - c := baseData + c := work.baseData for roots != nil { if i == c { markrootBlock(roots, gcw) @@ -166,15 +162,18 @@ func markroot(gcw *gcWork, i uint32) { case i == fixedRootFreeGStacks: // FIXME: We don't do this for gccgo. - case baseSpans <= i && i < baseStacks: + case work.baseSpans <= i && i < work.baseStacks: // mark mspan.specials - markrootSpans(gcw, int(i-baseSpans)) + markrootSpans(gcw, int(i-work.baseSpans)) default: // the rest is scanning goroutine stacks var gp *g - if baseStacks <= i && i < end { - gp = allgs[i-baseStacks] + if work.baseStacks <= i && i < work.baseEnd { + // N.B. Atomic read of allglen in gcMarkRootPrepare + // acts as a barrier to ensure that allgs must be large + // enough to contain all relevant Gs. + gp = allgs[i-work.baseStacks] } else { throw("markroot: bad index") } @@ -1051,12 +1050,7 @@ func scanobject(b uintptr, gcw *gcWork) { } var i uintptr - for i = 0; i < n; i += sys.PtrSize { - // Find bits for this word. - if i != 0 { - // Avoid needless hbits.next() on last iteration. - hbits = hbits.next() - } + for i = 0; i < n; i, hbits = i+sys.PtrSize, hbits.next() { // Load bits once. See CL 22712 and issue 16973 for discussion. bits := hbits.bits() if bits&bitScan == 0 { diff --git a/libgo/go/runtime/mgcpacer.go b/libgo/go/runtime/mgcpacer.go new file mode 100644 index 0000000..8a66920 --- /dev/null +++ b/libgo/go/runtime/mgcpacer.go @@ -0,0 +1,848 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +import ( + "internal/cpu" + "runtime/internal/atomic" + "unsafe" +) + +const ( + // gcGoalUtilization is the goal CPU utilization for + // marking as a fraction of GOMAXPROCS. + gcGoalUtilization = 0.30 + + // gcBackgroundUtilization is the fixed CPU utilization for background + // marking. It must be <= gcGoalUtilization. The difference between + // gcGoalUtilization and gcBackgroundUtilization will be made up by + // mark assists. The scheduler will aim to use within 50% of this + // goal. + // + // Setting this to < gcGoalUtilization avoids saturating the trigger + // feedback controller when there are no assists, which allows it to + // better control CPU and heap growth. However, the larger the gap, + // the more mutator assists are expected to happen, which impact + // mutator latency. + gcBackgroundUtilization = 0.25 + + // gcCreditSlack is the amount of scan work credit that can + // accumulate locally before updating gcController.scanWork and, + // optionally, gcController.bgScanCredit. Lower values give a more + // accurate assist ratio and make it more likely that assists will + // successfully steal background credit. Higher values reduce memory + // contention. + gcCreditSlack = 2000 + + // gcAssistTimeSlack is the nanoseconds of mutator assist time that + // can accumulate on a P before updating gcController.assistTime. + gcAssistTimeSlack = 5000 + + // gcOverAssistWork determines how many extra units of scan work a GC + // assist does when an assist happens. This amortizes the cost of an + // assist by pre-paying for this many bytes of future allocations. + gcOverAssistWork = 64 << 10 + + // defaultHeapMinimum is the value of heapMinimum for GOGC==100. + defaultHeapMinimum = 4 << 20 +) + +func init() { + if offset := unsafe.Offsetof(gcController.heapLive); offset%8 != 0 { + println(offset) + throw("gcController.heapLive not aligned to 8 bytes") + } +} + +// gcController implements the GC pacing controller that determines +// when to trigger concurrent garbage collection and how much marking +// work to do in mutator assists and background marking. +// +// It uses a feedback control algorithm to adjust the gcController.trigger +// trigger based on the heap growth and GC CPU utilization each cycle. +// This algorithm optimizes for heap growth to match GOGC and for CPU +// utilization between assist and background marking to be 25% of +// GOMAXPROCS. The high-level design of this algorithm is documented +// at https://golang.org/s/go15gcpacing. +// +// All fields of gcController are used only during a single mark +// cycle. +var gcController gcControllerState + +type gcControllerState struct { + // Initialized from $GOGC. GOGC=off means no GC. + gcPercent int32 + + _ uint32 // padding so following 64-bit values are 8-byte aligned + + // heapMinimum is the minimum heap size at which to trigger GC. + // For small heaps, this overrides the usual GOGC*live set rule. + // + // When there is a very small live set but a lot of allocation, simply + // collecting when the heap reaches GOGC*live results in many GC + // cycles and high total per-GC overhead. This minimum amortizes this + // per-GC overhead while keeping the heap reasonably small. + // + // During initialization this is set to 4MB*GOGC/100. In the case of + // GOGC==0, this will set heapMinimum to 0, resulting in constant + // collection even when the heap size is small, which is useful for + // debugging. + heapMinimum uint64 + + // triggerRatio is the heap growth ratio that triggers marking. + // + // E.g., if this is 0.6, then GC should start when the live + // heap has reached 1.6 times the heap size marked by the + // previous cycle. This should be ≤ GOGC/100 so the trigger + // heap size is less than the goal heap size. This is set + // during mark termination for the next cycle's trigger. + // + // Protected by mheap_.lock or a STW. + triggerRatio float64 + + // trigger is the heap size that triggers marking. + // + // When heapLive ≥ trigger, the mark phase will start. + // This is also the heap size by which proportional sweeping + // must be complete. + // + // This is computed from triggerRatio during mark termination + // for the next cycle's trigger. + // + // Protected by mheap_.lock or a STW. + trigger uint64 + + // heapGoal is the goal heapLive for when next GC ends. + // Set to ^uint64(0) if disabled. + // + // Read and written atomically, unless the world is stopped. + heapGoal uint64 + + // lastHeapGoal is the value of heapGoal for the previous GC. + // Note that this is distinct from the last value heapGoal had, + // because it could change if e.g. gcPercent changes. + // + // Read and written with the world stopped or with mheap_.lock held. + lastHeapGoal uint64 + + // heapLive is the number of bytes considered live by the GC. + // That is: retained by the most recent GC plus allocated + // since then. heapLive ≤ memstats.heapAlloc, since heapAlloc includes + // unmarked objects that have not yet been swept (and hence goes up as we + // allocate and down as we sweep) while heapLive excludes these + // objects (and hence only goes up between GCs). + // + // This is updated atomically without locking. To reduce + // contention, this is updated only when obtaining a span from + // an mcentral and at this point it counts all of the + // unallocated slots in that span (which will be allocated + // before that mcache obtains another span from that + // mcentral). Hence, it slightly overestimates the "true" live + // heap size. It's better to overestimate than to + // underestimate because 1) this triggers the GC earlier than + // necessary rather than potentially too late and 2) this + // leads to a conservative GC rate rather than a GC rate that + // is potentially too low. + // + // Reads should likewise be atomic (or during STW). + // + // Whenever this is updated, call traceHeapAlloc() and + // this gcControllerState's revise() method. + heapLive uint64 + + // heapScan is the number of bytes of "scannable" heap. This + // is the live heap (as counted by heapLive), but omitting + // no-scan objects and no-scan tails of objects. + // + // Whenever this is updated, call this gcControllerState's + // revise() method. + // + // Read and written atomically or with the world stopped. + heapScan uint64 + + // heapMarked is the number of bytes marked by the previous + // GC. After mark termination, heapLive == heapMarked, but + // unlike heapLive, heapMarked does not change until the + // next mark termination. + heapMarked uint64 + + // scanWork is the total scan work performed this cycle. This + // is updated atomically during the cycle. Updates occur in + // bounded batches, since it is both written and read + // throughout the cycle. At the end of the cycle, this is how + // much of the retained heap is scannable. + // + // Currently this is the bytes of heap scanned. For most uses, + // this is an opaque unit of work, but for estimation the + // definition is important. + scanWork int64 + + // bgScanCredit is the scan work credit accumulated by the + // concurrent background scan. This credit is accumulated by + // the background scan and stolen by mutator assists. This is + // updated atomically. Updates occur in bounded batches, since + // it is both written and read throughout the cycle. + bgScanCredit int64 + + // assistTime is the nanoseconds spent in mutator assists + // during this cycle. This is updated atomically. Updates + // occur in bounded batches, since it is both written and read + // throughout the cycle. + assistTime int64 + + // dedicatedMarkTime is the nanoseconds spent in dedicated + // mark workers during this cycle. This is updated atomically + // at the end of the concurrent mark phase. + dedicatedMarkTime int64 + + // fractionalMarkTime is the nanoseconds spent in the + // fractional mark worker during this cycle. This is updated + // atomically throughout the cycle and will be up-to-date if + // the fractional mark worker is not currently running. + fractionalMarkTime int64 + + // idleMarkTime is the nanoseconds spent in idle marking + // during this cycle. This is updated atomically throughout + // the cycle. + idleMarkTime int64 + + // markStartTime is the absolute start time in nanoseconds + // that assists and background mark workers started. + markStartTime int64 + + // dedicatedMarkWorkersNeeded is the number of dedicated mark + // workers that need to be started. This is computed at the + // beginning of each cycle and decremented atomically as + // dedicated mark workers get started. + dedicatedMarkWorkersNeeded int64 + + // assistWorkPerByte is the ratio of scan work to allocated + // bytes that should be performed by mutator assists. This is + // computed at the beginning of each cycle and updated every + // time heapScan is updated. + // + // Stored as a uint64, but it's actually a float64. Use + // float64frombits to get the value. + // + // Read and written atomically. + assistWorkPerByte uint64 + + // assistBytesPerWork is 1/assistWorkPerByte. + // + // Stored as a uint64, but it's actually a float64. Use + // float64frombits to get the value. + // + // Read and written atomically. + // + // Note that because this is read and written independently + // from assistWorkPerByte users may notice a skew between + // the two values, and such a state should be safe. + assistBytesPerWork uint64 + + // fractionalUtilizationGoal is the fraction of wall clock + // time that should be spent in the fractional mark worker on + // each P that isn't running a dedicated worker. + // + // For example, if the utilization goal is 25% and there are + // no dedicated workers, this will be 0.25. If the goal is + // 25%, there is one dedicated worker, and GOMAXPROCS is 5, + // this will be 0.05 to make up the missing 5%. + // + // If this is zero, no fractional workers are needed. + fractionalUtilizationGoal float64 + + _ cpu.CacheLinePad +} + +func (c *gcControllerState) init(gcPercent int32) { + c.heapMinimum = defaultHeapMinimum + + // Set a reasonable initial GC trigger. + c.triggerRatio = 7 / 8.0 + + // Fake a heapMarked value so it looks like a trigger at + // heapMinimum is the appropriate growth from heapMarked. + // This will go into computing the initial GC goal. + c.heapMarked = uint64(float64(c.heapMinimum) / (1 + c.triggerRatio)) + + // This will also compute and set the GC trigger and goal. + c.setGCPercent(gcPercent) +} + +// startCycle resets the GC controller's state and computes estimates +// for a new GC cycle. The caller must hold worldsema and the world +// must be stopped. +func (c *gcControllerState) startCycle() { + c.scanWork = 0 + c.bgScanCredit = 0 + c.assistTime = 0 + c.dedicatedMarkTime = 0 + c.fractionalMarkTime = 0 + c.idleMarkTime = 0 + + // Ensure that the heap goal is at least a little larger than + // the current live heap size. This may not be the case if GC + // start is delayed or if the allocation that pushed gcController.heapLive + // over trigger is large or if the trigger is really close to + // GOGC. Assist is proportional to this distance, so enforce a + // minimum distance, even if it means going over the GOGC goal + // by a tiny bit. + if c.heapGoal < c.heapLive+1024*1024 { + c.heapGoal = c.heapLive + 1024*1024 + } + + // Compute the background mark utilization goal. In general, + // this may not come out exactly. We round the number of + // dedicated workers so that the utilization is closest to + // 25%. For small GOMAXPROCS, this would introduce too much + // error, so we add fractional workers in that case. + totalUtilizationGoal := float64(gomaxprocs) * gcBackgroundUtilization + c.dedicatedMarkWorkersNeeded = int64(totalUtilizationGoal + 0.5) + utilError := float64(c.dedicatedMarkWorkersNeeded)/totalUtilizationGoal - 1 + const maxUtilError = 0.3 + if utilError < -maxUtilError || utilError > maxUtilError { + // Rounding put us more than 30% off our goal. With + // gcBackgroundUtilization of 25%, this happens for + // GOMAXPROCS<=3 or GOMAXPROCS=6. Enable fractional + // workers to compensate. + if float64(c.dedicatedMarkWorkersNeeded) > totalUtilizationGoal { + // Too many dedicated workers. + c.dedicatedMarkWorkersNeeded-- + } + c.fractionalUtilizationGoal = (totalUtilizationGoal - float64(c.dedicatedMarkWorkersNeeded)) / float64(gomaxprocs) + } else { + c.fractionalUtilizationGoal = 0 + } + + // In STW mode, we just want dedicated workers. + if debug.gcstoptheworld > 0 { + c.dedicatedMarkWorkersNeeded = int64(gomaxprocs) + c.fractionalUtilizationGoal = 0 + } + + // Clear per-P state + for _, p := range allp { + p.gcAssistTime = 0 + p.gcFractionalMarkTime = 0 + } + + // Compute initial values for controls that are updated + // throughout the cycle. + c.revise() + + if debug.gcpacertrace > 0 { + assistRatio := float64frombits(atomic.Load64(&c.assistWorkPerByte)) + print("pacer: assist ratio=", assistRatio, + " (scan ", gcController.heapScan>>20, " MB in ", + work.initialHeapLive>>20, "->", + c.heapGoal>>20, " MB)", + " workers=", c.dedicatedMarkWorkersNeeded, + "+", c.fractionalUtilizationGoal, "\n") + } +} + +// revise updates the assist ratio during the GC cycle to account for +// improved estimates. This should be called whenever gcController.heapScan, +// gcController.heapLive, or gcController.heapGoal is updated. It is safe to +// call concurrently, but it may race with other calls to revise. +// +// The result of this race is that the two assist ratio values may not line +// up or may be stale. In practice this is OK because the assist ratio +// moves slowly throughout a GC cycle, and the assist ratio is a best-effort +// heuristic anyway. Furthermore, no part of the heuristic depends on +// the two assist ratio values being exact reciprocals of one another, since +// the two values are used to convert values from different sources. +// +// The worst case result of this raciness is that we may miss a larger shift +// in the ratio (say, if we decide to pace more aggressively against the +// hard heap goal) but even this "hard goal" is best-effort (see #40460). +// The dedicated GC should ensure we don't exceed the hard goal by too much +// in the rare case we do exceed it. +// +// It should only be called when gcBlackenEnabled != 0 (because this +// is when assists are enabled and the necessary statistics are +// available). +func (c *gcControllerState) revise() { + gcPercent := c.gcPercent + if gcPercent < 0 { + // If GC is disabled but we're running a forced GC, + // act like GOGC is huge for the below calculations. + gcPercent = 100000 + } + live := atomic.Load64(&c.heapLive) + scan := atomic.Load64(&c.heapScan) + work := atomic.Loadint64(&c.scanWork) + + // Assume we're under the soft goal. Pace GC to complete at + // heapGoal assuming the heap is in steady-state. + heapGoal := int64(atomic.Load64(&c.heapGoal)) + + // Compute the expected scan work remaining. + // + // This is estimated based on the expected + // steady-state scannable heap. For example, with + // GOGC=100, only half of the scannable heap is + // expected to be live, so that's what we target. + // + // (This is a float calculation to avoid overflowing on + // 100*heapScan.) + scanWorkExpected := int64(float64(scan) * 100 / float64(100+gcPercent)) + + if int64(live) > heapGoal || work > scanWorkExpected { + // We're past the soft goal, or we've already done more scan + // work than we expected. Pace GC so that in the worst case it + // will complete by the hard goal. + const maxOvershoot = 1.1 + heapGoal = int64(float64(heapGoal) * maxOvershoot) + + // Compute the upper bound on the scan work remaining. + scanWorkExpected = int64(scan) + } + + // Compute the remaining scan work estimate. + // + // Note that we currently count allocations during GC as both + // scannable heap (heapScan) and scan work completed + // (scanWork), so allocation will change this difference + // slowly in the soft regime and not at all in the hard + // regime. + scanWorkRemaining := scanWorkExpected - work + if scanWorkRemaining < 1000 { + // We set a somewhat arbitrary lower bound on + // remaining scan work since if we aim a little high, + // we can miss by a little. + // + // We *do* need to enforce that this is at least 1, + // since marking is racy and double-scanning objects + // may legitimately make the remaining scan work + // negative, even in the hard goal regime. + scanWorkRemaining = 1000 + } + + // Compute the heap distance remaining. + heapRemaining := heapGoal - int64(live) + if heapRemaining <= 0 { + // This shouldn't happen, but if it does, avoid + // dividing by zero or setting the assist negative. + heapRemaining = 1 + } + + // Compute the mutator assist ratio so by the time the mutator + // allocates the remaining heap bytes up to heapGoal, it will + // have done (or stolen) the remaining amount of scan work. + // Note that the assist ratio values are updated atomically + // but not together. This means there may be some degree of + // skew between the two values. This is generally OK as the + // values shift relatively slowly over the course of a GC + // cycle. + assistWorkPerByte := float64(scanWorkRemaining) / float64(heapRemaining) + assistBytesPerWork := float64(heapRemaining) / float64(scanWorkRemaining) + atomic.Store64(&c.assistWorkPerByte, float64bits(assistWorkPerByte)) + atomic.Store64(&c.assistBytesPerWork, float64bits(assistBytesPerWork)) +} + +// endCycle computes the trigger ratio for the next cycle. +// userForced indicates whether the current GC cycle was forced +// by the application. +func (c *gcControllerState) endCycle(userForced bool) float64 { + if userForced { + // Forced GC means this cycle didn't start at the + // trigger, so where it finished isn't good + // information about how to adjust the trigger. + // Just leave it where it is. + return c.triggerRatio + } + + // Proportional response gain for the trigger controller. Must + // be in [0, 1]. Lower values smooth out transient effects but + // take longer to respond to phase changes. Higher values + // react to phase changes quickly, but are more affected by + // transient changes. Values near 1 may be unstable. + const triggerGain = 0.5 + + // Compute next cycle trigger ratio. First, this computes the + // "error" for this cycle; that is, how far off the trigger + // was from what it should have been, accounting for both heap + // growth and GC CPU utilization. We compute the actual heap + // growth during this cycle and scale that by how far off from + // the goal CPU utilization we were (to estimate the heap + // growth if we had the desired CPU utilization). The + // difference between this estimate and the GOGC-based goal + // heap growth is the error. + goalGrowthRatio := c.effectiveGrowthRatio() + actualGrowthRatio := float64(c.heapLive)/float64(c.heapMarked) - 1 + assistDuration := nanotime() - c.markStartTime + + // Assume background mark hit its utilization goal. + utilization := gcBackgroundUtilization + // Add assist utilization; avoid divide by zero. + if assistDuration > 0 { + utilization += float64(c.assistTime) / float64(assistDuration*int64(gomaxprocs)) + } + + triggerError := goalGrowthRatio - c.triggerRatio - utilization/gcGoalUtilization*(actualGrowthRatio-c.triggerRatio) + + // Finally, we adjust the trigger for next time by this error, + // damped by the proportional gain. + triggerRatio := c.triggerRatio + triggerGain*triggerError + + if debug.gcpacertrace > 0 { + // Print controller state in terms of the design + // document. + H_m_prev := c.heapMarked + h_t := c.triggerRatio + H_T := c.trigger + h_a := actualGrowthRatio + H_a := c.heapLive + h_g := goalGrowthRatio + H_g := int64(float64(H_m_prev) * (1 + h_g)) + u_a := utilization + u_g := gcGoalUtilization + W_a := c.scanWork + print("pacer: H_m_prev=", H_m_prev, + " h_t=", h_t, " H_T=", H_T, + " h_a=", h_a, " H_a=", H_a, + " h_g=", h_g, " H_g=", H_g, + " u_a=", u_a, " u_g=", u_g, + " W_a=", W_a, + " goalΔ=", goalGrowthRatio-h_t, + " actualΔ=", h_a-h_t, + " u_a/u_g=", u_a/u_g, + "\n") + } + + return triggerRatio +} + +// enlistWorker encourages another dedicated mark worker to start on +// another P if there are spare worker slots. It is used by putfull +// when more work is made available. +// +//go:nowritebarrier +func (c *gcControllerState) enlistWorker() { + // If there are idle Ps, wake one so it will run an idle worker. + // NOTE: This is suspected of causing deadlocks. See golang.org/issue/19112. + // + // if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 { + // wakep() + // return + // } + + // There are no idle Ps. If we need more dedicated workers, + // try to preempt a running P so it will switch to a worker. + if c.dedicatedMarkWorkersNeeded <= 0 { + return + } + // Pick a random other P to preempt. + if gomaxprocs <= 1 { + return + } + gp := getg() + if gp == nil || gp.m == nil || gp.m.p == 0 { + return + } + myID := gp.m.p.ptr().id + for tries := 0; tries < 5; tries++ { + id := int32(fastrandn(uint32(gomaxprocs - 1))) + if id >= myID { + id++ + } + p := allp[id] + if p.status != _Prunning { + continue + } + if preemptone(p) { + return + } + } +} + +// findRunnableGCWorker returns a background mark worker for _p_ if it +// should be run. This must only be called when gcBlackenEnabled != 0. +func (c *gcControllerState) findRunnableGCWorker(_p_ *p) *g { + if gcBlackenEnabled == 0 { + throw("gcControllerState.findRunnable: blackening not enabled") + } + + if !gcMarkWorkAvailable(_p_) { + // No work to be done right now. This can happen at + // the end of the mark phase when there are still + // assists tapering off. Don't bother running a worker + // now because it'll just return immediately. + return nil + } + + // Grab a worker before we commit to running below. + node := (*gcBgMarkWorkerNode)(gcBgMarkWorkerPool.pop()) + if node == nil { + // There is at least one worker per P, so normally there are + // enough workers to run on all Ps, if necessary. However, once + // a worker enters gcMarkDone it may park without rejoining the + // pool, thus freeing a P with no corresponding worker. + // gcMarkDone never depends on another worker doing work, so it + // is safe to simply do nothing here. + // + // If gcMarkDone bails out without completing the mark phase, + // it will always do so with queued global work. Thus, that P + // will be immediately eligible to re-run the worker G it was + // just using, ensuring work can complete. + return nil + } + + decIfPositive := func(ptr *int64) bool { + for { + v := atomic.Loadint64(ptr) + if v <= 0 { + return false + } + + if atomic.Casint64(ptr, v, v-1) { + return true + } + } + } + + if decIfPositive(&c.dedicatedMarkWorkersNeeded) { + // This P is now dedicated to marking until the end of + // the concurrent mark phase. + _p_.gcMarkWorkerMode = gcMarkWorkerDedicatedMode + } else if c.fractionalUtilizationGoal == 0 { + // No need for fractional workers. + gcBgMarkWorkerPool.push(&node.node) + return nil + } else { + // Is this P behind on the fractional utilization + // goal? + // + // This should be kept in sync with pollFractionalWorkerExit. + delta := nanotime() - c.markStartTime + if delta > 0 && float64(_p_.gcFractionalMarkTime)/float64(delta) > c.fractionalUtilizationGoal { + // Nope. No need to run a fractional worker. + gcBgMarkWorkerPool.push(&node.node) + return nil + } + // Run a fractional worker. + _p_.gcMarkWorkerMode = gcMarkWorkerFractionalMode + } + + // Run the background mark worker. + gp := node.gp.ptr() + casgstatus(gp, _Gwaiting, _Grunnable) + if trace.enabled { + traceGoUnpark(gp, 0) + } + return gp +} + +// commit sets the trigger ratio and updates everything +// derived from it: the absolute trigger, the heap goal, mark pacing, +// and sweep pacing. +// +// This can be called any time. If GC is the in the middle of a +// concurrent phase, it will adjust the pacing of that phase. +// +// This depends on gcPercent, gcController.heapMarked, and +// gcController.heapLive. These must be up to date. +// +// mheap_.lock must be held or the world must be stopped. +func (c *gcControllerState) commit(triggerRatio float64) { + assertWorldStoppedOrLockHeld(&mheap_.lock) + + // Compute the next GC goal, which is when the allocated heap + // has grown by GOGC/100 over the heap marked by the last + // cycle. + goal := ^uint64(0) + if c.gcPercent >= 0 { + goal = c.heapMarked + c.heapMarked*uint64(c.gcPercent)/100 + } + + // Set the trigger ratio, capped to reasonable bounds. + if c.gcPercent >= 0 { + scalingFactor := float64(c.gcPercent) / 100 + // Ensure there's always a little margin so that the + // mutator assist ratio isn't infinity. + maxTriggerRatio := 0.95 * scalingFactor + if triggerRatio > maxTriggerRatio { + triggerRatio = maxTriggerRatio + } + + // If we let triggerRatio go too low, then if the application + // is allocating very rapidly we might end up in a situation + // where we're allocating black during a nearly always-on GC. + // The result of this is a growing heap and ultimately an + // increase in RSS. By capping us at a point >0, we're essentially + // saying that we're OK using more CPU during the GC to prevent + // this growth in RSS. + // + // The current constant was chosen empirically: given a sufficiently + // fast/scalable allocator with 48 Ps that could drive the trigger ratio + // to <0.05, this constant causes applications to retain the same peak + // RSS compared to not having this allocator. + minTriggerRatio := 0.6 * scalingFactor + if triggerRatio < minTriggerRatio { + triggerRatio = minTriggerRatio + } + } else if triggerRatio < 0 { + // gcPercent < 0, so just make sure we're not getting a negative + // triggerRatio. This case isn't expected to happen in practice, + // and doesn't really matter because if gcPercent < 0 then we won't + // ever consume triggerRatio further on in this function, but let's + // just be defensive here; the triggerRatio being negative is almost + // certainly undesirable. + triggerRatio = 0 + } + c.triggerRatio = triggerRatio + + // Compute the absolute GC trigger from the trigger ratio. + // + // We trigger the next GC cycle when the allocated heap has + // grown by the trigger ratio over the marked heap size. + trigger := ^uint64(0) + if c.gcPercent >= 0 { + trigger = uint64(float64(c.heapMarked) * (1 + triggerRatio)) + // Don't trigger below the minimum heap size. + minTrigger := c.heapMinimum + if !isSweepDone() { + // Concurrent sweep happens in the heap growth + // from gcController.heapLive to trigger, so ensure + // that concurrent sweep has some heap growth + // in which to perform sweeping before we + // start the next GC cycle. + sweepMin := atomic.Load64(&c.heapLive) + sweepMinHeapDistance + if sweepMin > minTrigger { + minTrigger = sweepMin + } + } + if trigger < minTrigger { + trigger = minTrigger + } + if int64(trigger) < 0 { + print("runtime: heapGoal=", c.heapGoal, " heapMarked=", c.heapMarked, " gcController.heapLive=", c.heapLive, " initialHeapLive=", work.initialHeapLive, "triggerRatio=", triggerRatio, " minTrigger=", minTrigger, "\n") + throw("trigger underflow") + } + if trigger > goal { + // The trigger ratio is always less than GOGC/100, but + // other bounds on the trigger may have raised it. + // Push up the goal, too. + goal = trigger + } + } + + // Commit to the trigger and goal. + c.trigger = trigger + atomic.Store64(&c.heapGoal, goal) + if trace.enabled { + traceHeapGoal() + } + + // Update mark pacing. + if gcphase != _GCoff { + c.revise() + } + + // Update sweep pacing. + if isSweepDone() { + mheap_.sweepPagesPerByte = 0 + } else { + // Concurrent sweep needs to sweep all of the in-use + // pages by the time the allocated heap reaches the GC + // trigger. Compute the ratio of in-use pages to sweep + // per byte allocated, accounting for the fact that + // some might already be swept. + heapLiveBasis := atomic.Load64(&c.heapLive) + heapDistance := int64(trigger) - int64(heapLiveBasis) + // Add a little margin so rounding errors and + // concurrent sweep are less likely to leave pages + // unswept when GC starts. + heapDistance -= 1024 * 1024 + if heapDistance < _PageSize { + // Avoid setting the sweep ratio extremely high + heapDistance = _PageSize + } + pagesSwept := atomic.Load64(&mheap_.pagesSwept) + pagesInUse := atomic.Load64(&mheap_.pagesInUse) + sweepDistancePages := int64(pagesInUse) - int64(pagesSwept) + if sweepDistancePages <= 0 { + mheap_.sweepPagesPerByte = 0 + } else { + mheap_.sweepPagesPerByte = float64(sweepDistancePages) / float64(heapDistance) + mheap_.sweepHeapLiveBasis = heapLiveBasis + // Write pagesSweptBasis last, since this + // signals concurrent sweeps to recompute + // their debt. + atomic.Store64(&mheap_.pagesSweptBasis, pagesSwept) + } + } + + gcPaceScavenger() +} + +// effectiveGrowthRatio returns the current effective heap growth +// ratio (GOGC/100) based on heapMarked from the previous GC and +// heapGoal for the current GC. +// +// This may differ from gcPercent/100 because of various upper and +// lower bounds on gcPercent. For example, if the heap is smaller than +// heapMinimum, this can be higher than gcPercent/100. +// +// mheap_.lock must be held or the world must be stopped. +func (c *gcControllerState) effectiveGrowthRatio() float64 { + assertWorldStoppedOrLockHeld(&mheap_.lock) + + egogc := float64(atomic.Load64(&c.heapGoal)-c.heapMarked) / float64(c.heapMarked) + if egogc < 0 { + // Shouldn't happen, but just in case. + egogc = 0 + } + return egogc +} + +// setGCPercent updates gcPercent and all related pacer state. +// Returns the old value of gcPercent. +// +// The world must be stopped, or mheap_.lock must be held. +func (c *gcControllerState) setGCPercent(in int32) int32 { + assertWorldStoppedOrLockHeld(&mheap_.lock) + + out := c.gcPercent + if in < 0 { + in = -1 + } + c.gcPercent = in + c.heapMinimum = defaultHeapMinimum * uint64(c.gcPercent) / 100 + // Update pacing in response to gcPercent change. + c.commit(c.triggerRatio) + + return out +} + +//go:linkname setGCPercent runtime_1debug.setGCPercent +func setGCPercent(in int32) (out int32) { + // Run on the system stack since we grab the heap lock. + systemstack(func() { + lock(&mheap_.lock) + out = gcController.setGCPercent(in) + unlock(&mheap_.lock) + }) + + // If we just disabled GC, wait for any concurrent GC mark to + // finish so we always return with no GC running. + if in < 0 { + gcWaitOnMark(atomic.Load(&work.cycles)) + } + + return out +} + +func readGOGC() int32 { + p := gogetenv("GOGC") + if p == "off" { + return -1 + } + if n, ok := atoi32(p); ok { + return n + } + return 100 +} diff --git a/libgo/go/runtime/mgcscavenge.go b/libgo/go/runtime/mgcscavenge.go index da5be70..3fa1c46 100644 --- a/libgo/go/runtime/mgcscavenge.go +++ b/libgo/go/runtime/mgcscavenge.go @@ -18,12 +18,12 @@ // application down to a goal. // // That goal is defined as: -// (retainExtraPercent+100) / 100 * (next_gc / last_next_gc) * last_heap_inuse +// (retainExtraPercent+100) / 100 * (heapGoal / lastHeapGoal) * last_heap_inuse // // Essentially, we wish to have the application's RSS track the heap goal, but // the heap goal is defined in terms of bytes of objects, rather than pages like // RSS. As a result, we need to take into account for fragmentation internal to -// spans. next_gc / last_next_gc defines the ratio between the current heap goal +// spans. heapGoal / lastHeapGoal defines the ratio between the current heap goal // and the last heap goal, which tells us by how much the heap is growing and // shrinking. We estimate what the heap will grow to in terms of pages by taking // this ratio and multiplying it by heap_inuse at the end of the last GC, which @@ -118,12 +118,12 @@ func gcPaceScavenger() { // We never scavenge before the 2nd GC cycle anyway (we don't have enough // information about the heap yet) so this is fine, and avoids a fault // or garbage data later. - if memstats.last_next_gc == 0 { + if gcController.lastHeapGoal == 0 { mheap_.scavengeGoal = ^uint64(0) return } // Compute our scavenging goal. - goalRatio := float64(atomic.Load64(&memstats.next_gc)) / float64(memstats.last_next_gc) + goalRatio := float64(atomic.Load64(&gcController.heapGoal)) / float64(gcController.lastHeapGoal) retainedGoal := uint64(float64(memstats.last_heap_inuse) * goalRatio) // Add retainExtraPercent overhead to retainedGoal. This calculation // looks strange but the purpose is to arrive at an integer division @@ -207,7 +207,7 @@ func wakeScavenger() { // Ready the goroutine by injecting it. We use injectglist instead // of ready or goready in order to allow us to run this function // without a P. injectglist also avoids placing the goroutine in - // the current P's runnext slot, which is desireable to prevent + // the current P's runnext slot, which is desirable to prevent // the scavenger from interfering with user goroutine scheduling // too much. var list gList @@ -249,7 +249,7 @@ func scavengeSleep(ns int64) int64 { // The background scavenger maintains the RSS of the application below // the line described by the proportional scavenging statistics in // the mheap struct. -func bgscavenge(c chan int) { +func bgscavenge() { setSystemGoroutine() scavenge.g = getg() @@ -263,7 +263,7 @@ func bgscavenge(c chan int) { wakeScavenger() } - c <- 1 + gcenable_setup <- 1 goparkunlock(&scavenge.lock, waitReasonGCScavengeWait, traceEvGoBlock, 1) // Exponentially-weighted moving average of the fraction of time this @@ -374,7 +374,7 @@ func bgscavenge(c chan int) { // Due to OS-related anomalies we may "sleep" for an inordinate amount // of time. Let's avoid letting the ratio get out of hand by bounding // the sleep time we use in our EWMA. - const minFraction = 1 / 1000 + const minFraction = 1.0 / 1000.0 if fraction < minFraction { fraction = minFraction } diff --git a/libgo/go/runtime/mgcscavenge_test.go b/libgo/go/runtime/mgcscavenge_test.go index 2503430..3b12a2e 100644 --- a/libgo/go/runtime/mgcscavenge_test.go +++ b/libgo/go/runtime/mgcscavenge_test.go @@ -152,12 +152,6 @@ func TestPallocDataFindScavengeCandidate(t *testing.T) { max: PallocChunkPages, want: BitRange{0, uint(m)}, } - tests["StartFree"+suffix] = test{ - alloc: []BitRange{{uint(m), PallocChunkPages - uint(m)}}, - min: m, - max: PallocChunkPages, - want: BitRange{0, uint(m)}, - } tests["EndFree"+suffix] = test{ alloc: []BitRange{{0, PallocChunkPages - uint(m)}}, min: m, diff --git a/libgo/go/runtime/mgcsweep.go b/libgo/go/runtime/mgcsweep.go index b2a5a86..746e7f0 100644 --- a/libgo/go/runtime/mgcsweep.go +++ b/libgo/go/runtime/mgcsweep.go @@ -153,7 +153,7 @@ func finishsweep_m() { nextMarkBitArenaEpoch() } -func bgsweep(c chan int) { +func bgsweep() { setSystemGoroutine() sweep.g = getg() @@ -161,7 +161,7 @@ func bgsweep(c chan int) { lockInit(&sweep.lock, lockRankSweep) lock(&sweep.lock) sweep.parked = true - c <- 1 + gcenable_setup <- 1 goparkunlock(&sweep.lock, waitReasonGCSweepWait, traceEvGoBlock, 1) for { @@ -178,6 +178,10 @@ func bgsweep(c chan int) { // gosweepone returning ^0 above // and the lock being acquired. unlock(&sweep.lock) + + // We need a preemption point for gofrontend. + Gosched() + continue } sweep.parked = true @@ -185,66 +189,133 @@ func bgsweep(c chan int) { } } +// sweepLocker acquires sweep ownership of spans and blocks sweep +// completion. +type sweepLocker struct { + // sweepGen is the sweep generation of the heap. + sweepGen uint32 + // blocking indicates that this tracker is blocking sweep + // completion, usually as a result of acquiring sweep + // ownership of at least one span. + blocking bool +} + +// sweepLocked represents sweep ownership of a span. +type sweepLocked struct { + *mspan +} + +func newSweepLocker() sweepLocker { + return sweepLocker{ + sweepGen: mheap_.sweepgen, + } +} + +// tryAcquire attempts to acquire sweep ownership of span s. If it +// successfully acquires ownership, it blocks sweep completion. +func (l *sweepLocker) tryAcquire(s *mspan) (sweepLocked, bool) { + // Check before attempting to CAS. + if atomic.Load(&s.sweepgen) != l.sweepGen-2 { + return sweepLocked{}, false + } + // Add ourselves to sweepers before potentially taking + // ownership. + l.blockCompletion() + // Attempt to acquire sweep ownership of s. + if !atomic.Cas(&s.sweepgen, l.sweepGen-2, l.sweepGen-1) { + return sweepLocked{}, false + } + return sweepLocked{s}, true +} + +// blockCompletion blocks sweep completion without acquiring any +// specific spans. +func (l *sweepLocker) blockCompletion() { + if !l.blocking { + atomic.Xadd(&mheap_.sweepers, +1) + l.blocking = true + } +} + +func (l *sweepLocker) dispose() { + if !l.blocking { + return + } + // Decrement the number of active sweepers and if this is the + // last one, mark sweep as complete. + l.blocking = false + if atomic.Xadd(&mheap_.sweepers, -1) == 0 && atomic.Load(&mheap_.sweepDrained) != 0 { + l.sweepIsDone() + } +} + +func (l *sweepLocker) sweepIsDone() { + if debug.gcpacertrace > 0 { + print("pacer: sweep done at heap size ", gcController.heapLive>>20, "MB; allocated ", (gcController.heapLive-mheap_.sweepHeapLiveBasis)>>20, "MB during sweep; swept ", mheap_.pagesSwept, " pages at ", mheap_.sweepPagesPerByte, " pages/byte\n") + } +} + // sweepone sweeps some unswept heap span and returns the number of pages returned // to the heap, or ^uintptr(0) if there was nothing to sweep. func sweepone() uintptr { _g_ := getg() - sweepRatio := mheap_.sweepPagesPerByte // For debugging // increment locks to ensure that the goroutine is not preempted // in the middle of sweep thus leaving the span in an inconsistent state for next GC _g_.m.locks++ - if atomic.Load(&mheap_.sweepdone) != 0 { + if atomic.Load(&mheap_.sweepDrained) != 0 { _g_.m.locks-- return ^uintptr(0) } - atomic.Xadd(&mheap_.sweepers, +1) + // TODO(austin): sweepone is almost always called in a loop; + // lift the sweepLocker into its callers. + sl := newSweepLocker() // Find a span to sweep. - var s *mspan - sg := mheap_.sweepgen + npages := ^uintptr(0) + var noMoreWork bool for { - s = mheap_.nextSpanForSweep() + s := mheap_.nextSpanForSweep() if s == nil { - atomic.Store(&mheap_.sweepdone, 1) + noMoreWork = atomic.Cas(&mheap_.sweepDrained, 0, 1) break } if state := s.state.get(); state != mSpanInUse { // This can happen if direct sweeping already // swept this span, but in that case the sweep // generation should always be up-to-date. - if !(s.sweepgen == sg || s.sweepgen == sg+3) { - print("runtime: bad span s.state=", state, " s.sweepgen=", s.sweepgen, " sweepgen=", sg, "\n") + if !(s.sweepgen == sl.sweepGen || s.sweepgen == sl.sweepGen+3) { + print("runtime: bad span s.state=", state, " s.sweepgen=", s.sweepgen, " sweepgen=", sl.sweepGen, "\n") throw("non in-use span in unswept list") } continue } - if s.sweepgen == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) { + if s, ok := sl.tryAcquire(s); ok { + // Sweep the span we found. + npages = s.npages + if s.sweep(false) { + // Whole span was freed. Count it toward the + // page reclaimer credit since these pages can + // now be used for span allocation. + atomic.Xadduintptr(&mheap_.reclaimCredit, npages) + } else { + // Span is still in-use, so this returned no + // pages to the heap and the span needs to + // move to the swept in-use list. + npages = 0 + } break } } - // Sweep the span we found. - npages := ^uintptr(0) - if s != nil { - npages = s.npages - if s.sweep(false) { - // Whole span was freed. Count it toward the - // page reclaimer credit since these pages can - // now be used for span allocation. - atomic.Xadduintptr(&mheap_.reclaimCredit, npages) - } else { - // Span is still in-use, so this returned no - // pages to the heap and the span needs to - // move to the swept in-use list. - npages = 0 - } - } + sl.dispose() - // Decrement the number of active sweepers and if this is the - // last one print trace information. - if atomic.Xadd(&mheap_.sweepers, -1) == 0 && atomic.Load(&mheap_.sweepdone) != 0 { - // Since the sweeper is done, move the scavenge gen forward (signalling + if noMoreWork { + // The sweep list is empty. There may still be + // concurrent sweeps running, but we're at least very + // close to done sweeping. + + // Move the scavenge gen forward (signalling // that there's new work to do) and wake the scavenger. // // The scavenger is signaled by the last sweeper because once @@ -264,23 +335,23 @@ func sweepone() uintptr { // for us to wake the scavenger directly via wakeScavenger, since // it could allocate. Ask sysmon to do it for us instead. readyForScavenger() - - if debug.gcpacertrace > 0 { - print("pacer: sweep done at heap size ", memstats.heap_live>>20, "MB; allocated ", (memstats.heap_live-mheap_.sweepHeapLiveBasis)>>20, "MB during sweep; swept ", mheap_.pagesSwept, " pages at ", sweepRatio, " pages/byte\n") - } } + _g_.m.locks-- return npages } -// isSweepDone reports whether all spans are swept or currently being swept. +// isSweepDone reports whether all spans are swept. // // Note that this condition may transition from false to true at any // time as the sweeper runs. It may transition from true to false if a // GC runs; to prevent that the caller must be non-preemptible or must // somehow block GC progress. func isSweepDone() bool { - return mheap_.sweepdone != 0 + // Check that all spans have at least begun sweeping and there + // are no active sweepers. If both are true, then all spans + // have finished sweeping. + return atomic.Load(&mheap_.sweepDrained) != 0 && atomic.Load(&mheap_.sweepers) == 0 } // Returns only when span s has been swept. @@ -294,20 +365,19 @@ func (s *mspan) ensureSwept() { throw("mspan.ensureSwept: m is not locked") } - sg := mheap_.sweepgen - spangen := atomic.Load(&s.sweepgen) - if spangen == sg || spangen == sg+3 { - return - } + sl := newSweepLocker() // The caller must be sure that the span is a mSpanInUse span. - if atomic.Cas(&s.sweepgen, sg-2, sg-1) { + if s, ok := sl.tryAcquire(s); ok { s.sweep(false) + sl.dispose() return } + sl.dispose() + // unfortunate condition, and we don't have efficient means to wait for { spangen := atomic.Load(&s.sweepgen) - if spangen == sg || spangen == sg+3 { + if spangen == sl.sweepGen || spangen == sl.sweepGen+3 { break } osyield() @@ -319,13 +389,21 @@ func (s *mspan) ensureSwept() { // Returns true if the span was returned to heap. // If preserve=true, don't return it to heap nor relink in mcentral lists; // caller takes care of it. -func (s *mspan) sweep(preserve bool) bool { +func (sl *sweepLocked) sweep(preserve bool) bool { // It's critical that we enter this function with preemption disabled, // GC must not start while we are in the middle of this function. _g_ := getg() if _g_.m.locks == 0 && _g_.m.mallocing == 0 && _g_ != _g_.m.g0 { throw("mspan.sweep: m is not locked") } + + s := sl.mspan + if !preserve { + // We'll release ownership of this span. Nil it out to + // prevent the caller from accidentally using it. + sl.mspan = nil + } + sweepgen := mheap_.sweepgen if state := s.state.get(); state != mSpanInUse || s.sweepgen != sweepgen-1 { print("mspan.sweep: state=", state, " sweepgen=", s.sweepgen, " mheap.sweepgen=", sweepgen, "\n") @@ -358,11 +436,10 @@ func (s *mspan) sweep(preserve bool) bool { // If such object is not marked, we need to queue all finalizers at once. // Both 1 and 2 are possible at the same time. hadSpecials := s.specials != nil - specialp := &s.specials - special := *specialp - for special != nil { + siter := newSpecialsIter(s) + for siter.valid() { // A finalizer can be set for an inner byte of an object, find object beginning. - objIndex := uintptr(special.offset) / size + objIndex := uintptr(siter.s.offset) / size p := s.base() + objIndex*size mbits := s.markBitsForIndex(objIndex) if !mbits.isMarked() { @@ -370,7 +447,7 @@ func (s *mspan) sweep(preserve bool) bool { // Pass 1: see if it has at least one finalizer. hasFin := false endOffset := p - s.base() + size - for tmp := special; tmp != nil && uintptr(tmp.offset) < endOffset; tmp = tmp.next { + for tmp := siter.s; tmp != nil && uintptr(tmp.offset) < endOffset; tmp = tmp.next { if tmp.kind == _KindSpecialFinalizer { // Stop freeing of object if it has a finalizer. mbits.setMarkedNonAtomic() @@ -379,27 +456,31 @@ func (s *mspan) sweep(preserve bool) bool { } } // Pass 2: queue all finalizers _or_ handle profile record. - for special != nil && uintptr(special.offset) < endOffset { + for siter.valid() && uintptr(siter.s.offset) < endOffset { // Find the exact byte for which the special was setup // (as opposed to object beginning). + special := siter.s p := s.base() + uintptr(special.offset) if special.kind == _KindSpecialFinalizer || !hasFin { - // Splice out special record. - y := special - special = special.next - *specialp = special - freespecial(y, unsafe.Pointer(p), size) + siter.unlinkAndNext() + freeSpecial(special, unsafe.Pointer(p), size) } else { - // This is profile record, but the object has finalizers (so kept alive). - // Keep special record. - specialp = &special.next - special = *specialp + // The object has finalizers, so we're keeping it alive. + // All other specials only apply when an object is freed, + // so just keep the special record. + siter.next() } } } else { - // object is still live: keep special record - specialp = &special.next - special = *specialp + // object is still live + if siter.s.kind == _KindSpecialReachable { + special := siter.unlinkAndNext() + (*specialReachable)(unsafe.Pointer(special)).reachable = true + freeSpecial(special, unsafe.Pointer(p), size) + } else { + // keep special record + siter.next() + } } } if hadSpecials && s.specials == nil { @@ -647,7 +728,7 @@ retry: sweptBasis := atomic.Load64(&mheap_.pagesSweptBasis) // Fix debt if necessary. - newHeapLive := uintptr(atomic.Load64(&memstats.heap_live)-mheap_.sweepHeapLiveBasis) + spanBytes + newHeapLive := uintptr(atomic.Load64(&gcController.heapLive)-mheap_.sweepHeapLiveBasis) + spanBytes pagesTarget := int64(mheap_.sweepPagesPerByte*float64(newHeapLive)) - int64(callerSweepPages) for pagesTarget > int64(atomic.Load64(&mheap_.pagesSwept)-sweptBasis) { if sweepone() == ^uintptr(0) { diff --git a/libgo/go/runtime/mgcwork.go b/libgo/go/runtime/mgcwork.go index b3a0686..667c7af 100644 --- a/libgo/go/runtime/mgcwork.go +++ b/libgo/go/runtime/mgcwork.go @@ -398,7 +398,7 @@ func getempty() *workbuf { } // putempty puts a workbuf onto the work.empty list. -// Upon entry this go routine owns b. The lfstack.push relinquishes ownership. +// Upon entry this goroutine owns b. The lfstack.push relinquishes ownership. //go:nowritebarrier func putempty(b *workbuf) { b.checkempty() diff --git a/libgo/go/runtime/mheap.go b/libgo/go/runtime/mheap.go index 77f3987..8e346c8 100644 --- a/libgo/go/runtime/mheap.go +++ b/libgo/go/runtime/mheap.go @@ -62,11 +62,12 @@ const ( type mheap struct { // lock must only be acquired on the system stack, otherwise a g // could self-deadlock if its stack grows with the lock held. - lock mutex - pages pageAlloc // page allocation data structure - sweepgen uint32 // sweep generation, see comment in mspan; written during STW - sweepdone uint32 // all spans are swept - sweepers uint32 // number of active sweepone calls + lock mutex + pages pageAlloc // page allocation data structure + + sweepgen uint32 // sweep generation, see comment in mspan; written during STW + sweepDrained uint32 // all spans are swept or are being swept + sweepers uint32 // number of active sweepone calls // allspans is a slice of all mspans ever created. Each mspan // appears exactly once. @@ -85,14 +86,14 @@ type mheap struct { // Proportional sweep // - // These parameters represent a linear function from heap_live + // These parameters represent a linear function from gcController.heapLive // to page sweep count. The proportional sweep system works to // stay in the black by keeping the current page sweep count - // above this line at the current heap_live. + // above this line at the current gcController.heapLive. // // The line has slope sweepPagesPerByte and passes through a // basis point at (sweepHeapLiveBasis, pagesSweptBasis). At - // any given time, the system is at (memstats.heap_live, + // any given time, the system is at (gcController.heapLive, // pagesSwept) in this space. // // It's important that the line pass through a point we @@ -104,7 +105,7 @@ type mheap struct { pagesInUse uint64 // pages of spans in stats mSpanInUse; updated atomically pagesSwept uint64 // pages swept this cycle; updated atomically pagesSweptBasis uint64 // pagesSwept to use as the origin of the sweep ratio; updated atomically - sweepHeapLiveBasis uint64 // value of heap_live to use as the origin of sweep ratio; written with lock, read without + sweepHeapLiveBasis uint64 // value of gcController.heapLive to use as the origin of sweep ratio; written with lock, read without sweepPagesPerByte float64 // proportional sweep ratio; written with lock, read without // TODO(austin): pagesInUse should be a uintptr, but the 386 // compiler can't 8-byte align fields. @@ -212,6 +213,7 @@ type mheap struct { cachealloc fixalloc // allocator for mcache* specialfinalizeralloc fixalloc // allocator for specialfinalizer* specialprofilealloc fixalloc // allocator for specialprofile* + specialReachableAlloc fixalloc // allocator for specialReachable speciallock mutex // lock for special record allocators. arenaHintAlloc fixalloc // allocator for arenaHints @@ -451,14 +453,11 @@ type mspan struct { // h->sweepgen is incremented by 2 after every GC sweepgen uint32 - divMul uint16 // for divide by elemsize - divMagic.mul - baseMask uint16 // if non-0, elemsize is a power of 2, & this will get object allocation base + divMul uint32 // for divide by elemsize allocCount uint16 // number of allocated objects spanclass spanClass // size class and noscan (uint8) state mSpanStateBox // mSpanInUse etc; accessed atomically (get/set methods) needzero uint8 // needs to be zeroed before allocation - divShift uint8 // for divide by elemsize - divMagic.shift - divShift2 uint8 // for divide by elemsize - divMagic.shift2 elemsize uintptr // computed from sizeclass or from npages limit uintptr // end of data in span speciallock mutex // guards specials list @@ -706,6 +705,7 @@ func (h *mheap) init() { h.cachealloc.init(unsafe.Sizeof(mcache{}), nil, nil, &memstats.mcache_sys) h.specialfinalizeralloc.init(unsafe.Sizeof(specialfinalizer{}), nil, nil, &memstats.other_sys) h.specialprofilealloc.init(unsafe.Sizeof(specialprofile{}), nil, nil, &memstats.other_sys) + h.specialReachableAlloc.init(unsafe.Sizeof(specialReachable{}), nil, nil, &memstats.other_sys) h.arenaHintAlloc.init(unsafe.Sizeof(arenaHint{}), nil, nil, &memstats.other_sys) // Don't zero mspan allocations. Background sweeping can @@ -818,7 +818,7 @@ func (h *mheap) reclaimChunk(arenas []arenaIdx, pageIdx, n uintptr) uintptr { n0 := n var nFreed uintptr - sg := h.sweepgen + sl := newSweepLocker() for n > 0 { ai := arenas[pageIdx/pagesPerArena] ha := h.arenas[ai.l1()][ai.l2()] @@ -843,7 +843,7 @@ func (h *mheap) reclaimChunk(arenas []arenaIdx, pageIdx, n uintptr) uintptr { for j := uint(0); j < 8; j++ { if inUseUnmarked&(1<<j) != 0 { s := ha.spans[arenaPage+uint(i)*8+j] - if atomic.Load(&s.sweepgen) == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) { + if s, ok := sl.tryAcquire(s); ok { npages := s.npages unlock(&h.lock) if s.sweep(false) { @@ -864,6 +864,7 @@ func (h *mheap) reclaimChunk(arenas []arenaIdx, pageIdx, n uintptr) uintptr { pageIdx += uintptr(len(inUse) * 8) n -= uintptr(len(inUse) * 8) } + sl.dispose() if trace.enabled { unlock(&h.lock) // Account for pages scanned but not reclaimed. @@ -896,7 +897,9 @@ func (s spanAllocType) manual() bool { // spanclass indicates the span's size class and scannability. // // If needzero is true, the memory for the returned span will be zeroed. -func (h *mheap) alloc(npages uintptr, spanclass spanClass, needzero bool) *mspan { +// The boolean returned indicates whether the returned span contains zeroes, +// either because this was requested, or because it was already zeroed. +func (h *mheap) alloc(npages uintptr, spanclass spanClass, needzero bool) (*mspan, bool) { // Don't do any operations that lock the heap on the G stack. // It might trigger stack growth, and the stack growth code needs // to be able to allocate heap. @@ -904,19 +907,22 @@ func (h *mheap) alloc(npages uintptr, spanclass spanClass, needzero bool) *mspan systemstack(func() { // To prevent excessive heap growth, before allocating n pages // we need to sweep and reclaim at least n pages. - if h.sweepdone == 0 { + if !isSweepDone() { h.reclaim(npages) } s = h.allocSpan(npages, spanAllocHeap, spanclass) }) - if s != nil { - if needzero && s.needzero != 0 { - memclrNoHeapPointers(unsafe.Pointer(s.base()), s.npages<<_PageShift) - } - s.needzero = 0 + if s == nil { + return nil, false } - return s + isZeroed := s.needzero == 0 + if needzero && !isZeroed { + memclrNoHeapPointers(unsafe.Pointer(s.base()), s.npages<<_PageShift) + isZeroed = true + } + s.needzero = 0 + return s, isZeroed } // allocManual allocates a manually-managed span of npage pages. @@ -1224,20 +1230,11 @@ HaveSpan: if sizeclass := spanclass.sizeclass(); sizeclass == 0 { s.elemsize = nbytes s.nelems = 1 - - s.divShift = 0 s.divMul = 0 - s.divShift2 = 0 - s.baseMask = 0 } else { s.elemsize = uintptr(class_to_size[sizeclass]) s.nelems = nbytes / s.elemsize - - m := &class_to_divmagic[sizeclass] - s.divShift = m.shift - s.divMul = m.mul - s.divShift2 = m.shift2 - s.baseMask = m.baseMask + s.divMul = class_to_divmagic[sizeclass] } // Initialize mark and allocation structures. @@ -1332,6 +1329,10 @@ func (h *mheap) grow(npage uintptr) bool { assertLockHeld(&h.lock) // We must grow the heap in whole palloc chunks. + // We call sysMap below but note that because we + // round up to pallocChunkPages which is on the order + // of MiB (generally >= to the huge page size) we + // won't be calling it too much. ask := alignUp(npage, pallocChunkPages) * pageSize totalGrowth := uintptr(0) @@ -1358,6 +1359,17 @@ func (h *mheap) grow(npage uintptr) bool { // remains of the current space and switch to // the new space. This should be rare. if size := h.curArena.end - h.curArena.base; size != 0 { + // Transition this space from Reserved to Prepared and mark it + // as released since we'll be able to start using it after updating + // the page allocator and releasing the lock at any time. + sysMap(unsafe.Pointer(h.curArena.base), size, &memstats.heap_sys) + // Update stats. + atomic.Xadd64(&memstats.heap_released, int64(size)) + stats := memstats.heapStats.acquire() + atomic.Xaddint64(&stats.released, int64(size)) + memstats.heapStats.release() + // Update the page allocator's structures to make this + // space ready for allocation. h.pages.grow(h.curArena.base, size) totalGrowth += size } @@ -1366,17 +1378,6 @@ func (h *mheap) grow(npage uintptr) bool { h.curArena.end = uintptr(av) + asize } - // The memory just allocated counts as both released - // and idle, even though it's not yet backed by spans. - // - // The allocation is always aligned to the heap arena - // size which is always > physPageSize, so its safe to - // just add directly to heap_released. - atomic.Xadd64(&memstats.heap_released, int64(asize)) - stats := memstats.heapStats.acquire() - atomic.Xaddint64(&stats.released, int64(asize)) - memstats.heapStats.release() - // Recalculate nBase. // We know this won't overflow, because sysAlloc returned // a valid region starting at h.curArena.base which is at @@ -1387,6 +1388,23 @@ func (h *mheap) grow(npage uintptr) bool { // Grow into the current arena. v := h.curArena.base h.curArena.base = nBase + + // Transition the space we're going to use from Reserved to Prepared. + sysMap(unsafe.Pointer(v), nBase-v, &memstats.heap_sys) + + // The memory just allocated counts as both released + // and idle, even though it's not yet backed by spans. + // + // The allocation is always aligned to the heap arena + // size which is always > physPageSize, so its safe to + // just add directly to heap_released. + atomic.Xadd64(&memstats.heap_released, int64(nBase-v)) + stats := memstats.heapStats.acquire() + atomic.Xaddint64(&stats.released, int64(nBase-v)) + memstats.heapStats.release() + + // Update the page allocator's structures to make this + // space ready for allocation. h.pages.grow(v, nBase-v) totalGrowth += nBase - v @@ -1640,6 +1658,9 @@ func (list *mSpanList) takeAll(other *mSpanList) { const ( _KindSpecialFinalizer = 1 _KindSpecialProfile = 2 + // _KindSpecialReachable is a special used for tracking + // reachability during testing. + _KindSpecialReachable = 3 // Note: The finalizer special must be first because if we're freeing // an object, a finalizer special will cause the freeing operation // to abort, and we want to keep the other special records around @@ -1843,9 +1864,45 @@ func setprofilebucket(p unsafe.Pointer, b *bucket) { } } -// Do whatever cleanup needs to be done to deallocate s. It has -// already been unlinked from the mspan specials list. -func freespecial(s *special, p unsafe.Pointer, size uintptr) { +// specialReachable tracks whether an object is reachable on the next +// GC cycle. This is used by testing. +type specialReachable struct { + special special + done bool + reachable bool +} + +// specialsIter helps iterate over specials lists. +type specialsIter struct { + pprev **special + s *special +} + +func newSpecialsIter(span *mspan) specialsIter { + return specialsIter{&span.specials, span.specials} +} + +func (i *specialsIter) valid() bool { + return i.s != nil +} + +func (i *specialsIter) next() { + i.pprev = &i.s.next + i.s = *i.pprev +} + +// unlinkAndNext removes the current special from the list and moves +// the iterator to the next special. It returns the unlinked special. +func (i *specialsIter) unlinkAndNext() *special { + cur := i.s + i.s = cur.next + *i.pprev = i.s + return cur +} + +// freeSpecial performs any cleanup on special s and deallocates it. +// s must already be unlinked from the specials list. +func freeSpecial(s *special, p unsafe.Pointer, size uintptr) { switch s.kind { case _KindSpecialFinalizer: sf := (*specialfinalizer)(unsafe.Pointer(s)) @@ -1859,6 +1916,10 @@ func freespecial(s *special, p unsafe.Pointer, size uintptr) { lock(&mheap_.speciallock) mheap_.specialprofilealloc.free(unsafe.Pointer(sp)) unlock(&mheap_.speciallock) + case _KindSpecialReachable: + sp := (*specialReachable)(unsafe.Pointer(s)) + sp.done = true + // The creator frees these. default: throw("bad special kind") panic("not reached") diff --git a/libgo/go/runtime/mkfastlog2table.go b/libgo/go/runtime/mkfastlog2table.go index d650292..8d78a39 100644 --- a/libgo/go/runtime/mkfastlog2table.go +++ b/libgo/go/runtime/mkfastlog2table.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // fastlog2Table contains log2 approximations for 5 binary digits. diff --git a/libgo/go/runtime/mkpreempt.go b/libgo/go/runtime/mkpreempt.go index 8644973..f82df93 100644 --- a/libgo/go/runtime/mkpreempt.go +++ b/libgo/go/runtime/mkpreempt.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // mkpreempt generates the asyncPreempt functions for each @@ -123,6 +124,7 @@ func header(arch string) { fmt.Fprintf(out, "// Code generated by mkpreempt.go; DO NOT EDIT.\n\n") if beLe[arch] { base := arch[:len(arch)-1] + fmt.Fprintf(out, "//go:build %s || %sle\n", base, base) fmt.Fprintf(out, "// +build %s %sle\n\n", base, base) } fmt.Fprintf(out, "#include \"go_asm.h\"\n") @@ -230,12 +232,16 @@ func genAMD64() { if reg == "SP" || reg == "BP" { continue } - if strings.HasPrefix(reg, "X") { - l.add("MOVUPS", reg, 16) - } else { + if !strings.HasPrefix(reg, "X") { l.add("MOVQ", reg, 8) } } + lSSE := layout{stack: l.stack, sp: "SP"} + for _, reg := range regNamesAMD64 { + if strings.HasPrefix(reg, "X") { + lSSE.add("MOVUPS", reg, 16) + } + } // TODO: MXCSR register? @@ -244,10 +250,12 @@ func genAMD64() { p("// Save flags before clobbering them") p("PUSHFQ") p("// obj doesn't understand ADD/SUB on SP, but does understand ADJSP") - p("ADJSP $%d", l.stack) + p("ADJSP $%d", lSSE.stack) p("// But vet doesn't know ADJSP, so suppress vet stack checking") p("NOP SP") + l.save() + // Apparently, the signal handling code path in darwin kernel leaves // the upper bits of Y registers in a dirty state, which causes // many SSE operations (128-bit and narrower) become much slower. @@ -259,10 +267,11 @@ func genAMD64() { p("VZEROUPPER") p("#endif") - l.save() + lSSE.save() p("CALL ·asyncPreempt2(SB)") + lSSE.restore() l.restore() - p("ADJSP $%d", -l.stack) + p("ADJSP $%d", -lSSE.stack) p("POPFQ") p("POPQ BP") p("RET") diff --git a/libgo/go/runtime/mksizeclasses.go b/libgo/go/runtime/mksizeclasses.go index b92d1fe..b1b10e9 100644 --- a/libgo/go/runtime/mksizeclasses.go +++ b/libgo/go/runtime/mksizeclasses.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // Generate tables for small malloc size classes. @@ -36,6 +37,8 @@ import ( "go/format" "io" "log" + "math" + "math/bits" "os" ) @@ -86,11 +89,6 @@ const ( type class struct { size int // max size npages int // number of pages - - mul int - shift uint - shift2 uint - mask int } func powerOfTwo(x int) bool { @@ -167,9 +165,9 @@ func makeClasses() []class { return classes } -// computeDivMagic computes some magic constants to implement -// the division required to compute object number from span offset. -// n / c.size is implemented as n >> c.shift * c.mul >> c.shift2 +// computeDivMagic checks that the division required to compute object +// index from span offset can be computed using 32-bit multiplication. +// n / c.size is implemented as (n * (^uint32(0)/uint32(c.size) + 1)) >> 32 // for all 0 <= n <= c.npages * pageSize func computeDivMagic(c *class) { // divisor @@ -181,68 +179,67 @@ func computeDivMagic(c *class) { // maximum input value for which the formula needs to work. max := c.npages * pageSize + // As reported in [1], if n and d are unsigned N-bit integers, we + // can compute n / d as ⌊n * c / 2^F⌋, where c is ⌈2^F / d⌉ and F is + // computed with: + // + // Algorithm 2: Algorithm to select the number of fractional bits + // and the scaled approximate reciprocal in the case of unsigned + // integers. + // + // if d is a power of two then + // Let F ← log₂(d) and c = 1. + // else + // Let F ← N + L where L is the smallest integer + // such that d ≤ (2^(N+L) mod d) + 2^L. + // end if + // + // [1] "Faster Remainder by Direct Computation: Applications to + // Compilers and Software Libraries" Daniel Lemire, Owen Kaser, + // Nathan Kurz arXiv:1902.01961 + // + // To minimize the risk of introducing errors, we implement the + // algorithm exactly as stated, rather than trying to adapt it to + // fit typical Go idioms. + N := bits.Len(uint(max)) + var F int if powerOfTwo(d) { - // If the size is a power of two, heapBitsForObject can divide even faster by masking. - // Compute this mask. - if max >= 1<<16 { - panic("max too big for power of two size") + F = int(math.Log2(float64(d))) + if d != 1<<F { + panic("imprecise log2") } - c.mask = 1<<16 - d - } - - // Compute pre-shift by factoring power of 2 out of d. - for d%2 == 0 { - c.shift++ - d >>= 1 - max >>= 1 - } - - // Find the smallest k that works. - // A small k allows us to fit the math required into 32 bits - // so we can use 32-bit multiplies and shifts on 32-bit platforms. -nextk: - for k := uint(0); ; k++ { - mul := (int(1)<<k + d - 1) / d // ⌈2^k / d⌉ - - // Test to see if mul works. - for n := 0; n <= max; n++ { - if n*mul>>k != n/d { - continue nextk + } else { + for L := 0; ; L++ { + if d <= ((1<<(N+L))%d)+(1<<L) { + F = N + L + break } } - if mul >= 1<<16 { - panic("mul too big") - } - if uint64(mul)*uint64(max) >= 1<<32 { - panic("mul*max too big") - } - c.mul = mul - c.shift2 = k - break } - // double-check. + // Also, noted in the paper, F is the smallest number of fractional + // bits required. We use 32 bits, because it works for all size + // classes and is fast on all CPU architectures that we support. + if F > 32 { + fmt.Printf("d=%d max=%d N=%d F=%d\n", c.size, max, N, F) + panic("size class requires more than 32 bits of precision") + } + + // Brute force double-check with the exact computation that will be + // done by the runtime. + m := ^uint32(0)/uint32(c.size) + 1 for n := 0; n <= max; n++ { - if n*c.mul>>c.shift2 != n/d { - fmt.Printf("d=%d max=%d mul=%d shift2=%d n=%d\n", d, max, c.mul, c.shift2, n) - panic("bad multiply magic") - } - // Also check the exact computations that will be done by the runtime, - // for both 32 and 64 bit operations. - if uint32(n)*uint32(c.mul)>>uint8(c.shift2) != uint32(n/d) { - fmt.Printf("d=%d max=%d mul=%d shift2=%d n=%d\n", d, max, c.mul, c.shift2, n) + if uint32((uint64(n)*uint64(m))>>32) != uint32(n/c.size) { + fmt.Printf("d=%d max=%d m=%d n=%d\n", d, max, m, n) panic("bad 32-bit multiply magic") } - if uint64(n)*uint64(c.mul)>>uint8(c.shift2) != uint64(n/d) { - fmt.Printf("d=%d max=%d mul=%d shift2=%d n=%d\n", d, max, c.mul, c.shift2, n) - panic("bad 64-bit multiply magic") - } } } func printComment(w io.Writer, classes []class) { - fmt.Fprintf(w, "// %-5s %-9s %-10s %-7s %-10s %-9s\n", "class", "bytes/obj", "bytes/span", "objects", "tail waste", "max waste") + fmt.Fprintf(w, "// %-5s %-9s %-10s %-7s %-10s %-9s %-9s\n", "class", "bytes/obj", "bytes/span", "objects", "tail waste", "max waste", "min align") prevSize := 0 + var minAligns [pageShift + 1]int for i, c := range classes { if i == 0 { continue @@ -251,8 +248,32 @@ func printComment(w io.Writer, classes []class) { objects := spanSize / c.size tailWaste := spanSize - c.size*(spanSize/c.size) maxWaste := float64((c.size-prevSize-1)*objects+tailWaste) / float64(spanSize) + alignBits := bits.TrailingZeros(uint(c.size)) + if alignBits > pageShift { + // object alignment is capped at page alignment + alignBits = pageShift + } + for i := range minAligns { + if i > alignBits { + minAligns[i] = 0 + } else if minAligns[i] == 0 { + minAligns[i] = c.size + } + } prevSize = c.size - fmt.Fprintf(w, "// %5d %9d %10d %7d %10d %8.2f%%\n", i, c.size, spanSize, objects, tailWaste, 100*maxWaste) + fmt.Fprintf(w, "// %5d %9d %10d %7d %10d %8.2f%% %9d\n", i, c.size, spanSize, objects, tailWaste, 100*maxWaste, 1<<alignBits) + } + fmt.Fprintf(w, "\n") + + fmt.Fprintf(w, "// %-9s %-4s %-12s\n", "alignment", "bits", "min obj size") + for bits, size := range minAligns { + if size == 0 { + break + } + if bits+1 < len(minAligns) && size == minAligns[bits+1] { + continue + } + fmt.Fprintf(w, "// %9d %4d %12d\n", 1<<bits, bits, size) } fmt.Fprintf(w, "\n") } @@ -279,15 +300,13 @@ func printClasses(w io.Writer, classes []class) { } fmt.Fprintln(w, "}") - fmt.Fprintln(w, "type divMagic struct {") - fmt.Fprintln(w, " shift uint8") - fmt.Fprintln(w, " shift2 uint8") - fmt.Fprintln(w, " mul uint16") - fmt.Fprintln(w, " baseMask uint16") - fmt.Fprintln(w, "}") - fmt.Fprint(w, "var class_to_divmagic = [_NumSizeClasses]divMagic {") + fmt.Fprint(w, "var class_to_divmagic = [_NumSizeClasses]uint32 {") for _, c := range classes { - fmt.Fprintf(w, "{%d,%d,%d,%d},", c.shift, c.shift2, c.mul, c.mask) + if c.size == 0 { + fmt.Fprintf(w, "0,") + continue + } + fmt.Fprintf(w, "^uint32(0)/%d+1,", c.size) } fmt.Fprintln(w, "}") diff --git a/libgo/go/runtime/mpagealloc.go b/libgo/go/runtime/mpagealloc.go index dac1f39..071f1fc 100644 --- a/libgo/go/runtime/mpagealloc.go +++ b/libgo/go/runtime/mpagealloc.go @@ -395,6 +395,9 @@ func (p *pageAlloc) grow(base, size uintptr) { // Store it atomically to avoid races with readers which // don't acquire the heap lock. r := sysAlloc(unsafe.Sizeof(*p.chunks[0]), p.sysStat) + if r == nil { + throw("pageAlloc: out of memory") + } atomic.StorepNoWB(unsafe.Pointer(&p.chunks[c.l1()]), r) } p.chunkOf(c).scavenged.setRange(0, pallocChunkPages) diff --git a/libgo/go/runtime/mpagealloc_32bit.go b/libgo/go/runtime/mpagealloc_32bit.go index e721c38..0741546 100644 --- a/libgo/go/runtime/mpagealloc_32bit.go +++ b/libgo/go/runtime/mpagealloc_32bit.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build 386 || arm || mips || mipsle || wasm || (ios && arm64) || amd64p32 || armbe || m68k || mips64p32 || mips64p32le || nios2 || ppc || riscv || s390 || sh || shbe || sparc // +build 386 arm mips mipsle wasm ios,arm64 amd64p32 armbe m68k mips64p32 mips64p32le nios2 ppc riscv s390 sh shbe sparc // wasm is a treated as a 32-bit architecture for the purposes of the page diff --git a/libgo/go/runtime/mpagealloc_64bit.go b/libgo/go/runtime/mpagealloc_64bit.go index 4d4257a..729a4eb 100644 --- a/libgo/go/runtime/mpagealloc_64bit.go +++ b/libgo/go/runtime/mpagealloc_64bit.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build amd64 || (!ios && arm64) || mips64 || mips64le || ppc64 || ppc64le || riscv64 || s390x || arm64be || alpha || sparc64 || ia64 // +build amd64 !ios,arm64 mips64 mips64le ppc64 ppc64le riscv64 s390x arm64be alpha sparc64 ia64 // See mpagealloc_32bit.go for why ios/arm64 is excluded here. diff --git a/libgo/go/runtime/mprof.go b/libgo/go/runtime/mprof.go index afacf8f..9b11597 100644 --- a/libgo/go/runtime/mprof.go +++ b/libgo/go/runtime/mprof.go @@ -12,6 +12,10 @@ import ( "unsafe" ) +// For gofrontend, use go:linkname for blockevent so that +// runtime/pprof/pprof_test can call it. +//go:linkname blockevent + // NOTE(rsc): Everything here could use cas if contention became an issue. var proflock mutex @@ -138,7 +142,7 @@ func (a *memRecordCycle) add(b *memRecordCycle) { // A blockRecord is the bucket data for a bucket of type blockProfile, // which is used in blocking and mutex profiles. type blockRecord struct { - count int64 + count float64 cycles int64 } @@ -431,20 +435,23 @@ func blockevent(cycles int64, skip int) { if cycles <= 0 { cycles = 1 } - if blocksampled(cycles) { - saveblockevent(cycles, skip+1, blockProfile) + + rate := int64(atomic.Load64(&blockprofilerate)) + if blocksampled(cycles, rate) { + saveblockevent(cycles, rate, skip+1, blockProfile) } } -func blocksampled(cycles int64) bool { - rate := int64(atomic.Load64(&blockprofilerate)) +// blocksampled returns true for all events where cycles >= rate. Shorter +// events have a cycles/rate random chance of returning true. +func blocksampled(cycles, rate int64) bool { if rate <= 0 || (rate > cycles && int64(fastrand())%rate > cycles) { return false } return true } -func saveblockevent(cycles int64, skip int, which bucketType) { +func saveblockevent(cycles, rate int64, skip int, which bucketType) { gp := getg() var nstk int var stk [maxStack]uintptr @@ -457,8 +464,15 @@ func saveblockevent(cycles int64, skip int, which bucketType) { } lock(&proflock) b := stkbucket(which, 0, skip, stk[:nstk], true) - b.bp().count++ - b.bp().cycles += cycles + + if which == blockProfile && cycles < rate { + // Remove sampling bias, see discussion on http://golang.org/cl/299991. + b.bp().count += float64(rate) / float64(cycles) + b.bp().cycles += rate + } else { + b.bp().count++ + b.bp().cycles += cycles + } unlock(&proflock) } @@ -489,7 +503,7 @@ func mutexevent(cycles int64, skip int) { // TODO(pjw): measure impact of always calling fastrand vs using something // like malloc.go:nextSample() if rate > 0 && int64(fastrand())%rate == 0 { - saveblockevent(cycles, skip+1, mutexProfile) + saveblockevent(cycles, rate, skip+1, mutexProfile) } } @@ -525,7 +539,22 @@ func (r *StackRecord) Stack() []uintptr { // memory profiling rate should do so just once, as early as // possible in the execution of the program (for example, // at the beginning of main). -var MemProfileRate int = 512 * 1024 +var MemProfileRate int = defaultMemProfileRate(512 * 1024) + +// defaultMemProfileRate returns 0 if disableMemoryProfiling is set. +// It exists primarily for the godoc rendering of MemProfileRate +// above. +func defaultMemProfileRate(v int) int { + if disableMemoryProfiling { + return 0 + } + return v +} + +// disableMemoryProfiling is set by the linker if runtime.MemProfile +// is not used and the link type guarantees nobody else could use it +// elsewhere. +var disableMemoryProfiling bool // A MemProfileRecord describes the live objects allocated // by a particular call sequence (stack trace). @@ -722,9 +751,8 @@ func fixupBucket(b *bucket) { rawrecord := b.mp() cb.mp().active.add(&rawrecord.active) case blockProfile, mutexProfile: - bpcount := b.bp().count - cb.bp().count += bpcount - cb.bp().cycles += bpcount + cb.bp().count += b.bp().count + cb.bp().cycles += b.bp().cycles } } @@ -866,7 +894,12 @@ func harvestBlockMutexProfile(buckets *bucket, p []BlockProfileRecord) (n int, o for b := sbuckets; b != nil; b = b.allnext { bp := b.bp() r := &p[0] - r.Count = bp.count + r.Count = int64(bp.count) + // Prevent callers from having to worry about division by zero errors. + // See discussion on http://golang.org/cl/299991. + if r.Count == 0 { + r.Count = 1 + } r.Cycles = bp.cycles i := 0 var pc uintptr @@ -962,12 +995,13 @@ func goroutineProfileWithLabels(p []StackRecord, labels []unsafe.Pointer) (n int stopTheWorld("profile") + // World is stopped, no locking required. n = 1 - for _, gp1 := range allgs { + forEachGRace(func(gp1 *g) { if isOK(gp1) { n++ } - } + }) if n <= len(p) { ok = true @@ -984,21 +1018,23 @@ func goroutineProfileWithLabels(p []StackRecord, labels []unsafe.Pointer) (n int } // Save other goroutines. - for _, gp1 := range allgs { + forEachGRace(func(gp1 *g) { if isOK(gp1) { - if len(r) == 0 { - // Should be impossible, but better to return a - // truncated profile than to crash the entire process. - break - } - saveg(gp1, &r[0]) - if labels != nil { - lbl[0] = gp1.labels - lbl = lbl[1:] - } - r = r[1:] + return } - } + + if len(r) == 0 { + // Should be impossible, but better to return a + // truncated profile than to crash the entire process. + return + } + saveg(gp1, &r[0]) + if labels != nil { + lbl[0] = gp1.labels + lbl = lbl[1:] + } + r = r[1:] + }) } startTheWorld() diff --git a/libgo/go/runtime/msan0.go b/libgo/go/runtime/msan0.go index 374d13f..b1096a6 100644 --- a/libgo/go/runtime/msan0.go +++ b/libgo/go/runtime/msan0.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !msan // +build !msan // Dummy MSan support API, used when not built with -msan. diff --git a/libgo/go/runtime/mstats.go b/libgo/go/runtime/mstats.go index 488e5d1..535b78a1 100644 --- a/libgo/go/runtime/mstats.go +++ b/libgo/go/runtime/mstats.go @@ -8,6 +8,7 @@ package runtime import ( "runtime/internal/atomic" + "runtime/internal/sys" "unsafe" ) @@ -62,12 +63,6 @@ type mstats struct { // Statistics about the garbage collector. - // next_gc is the goal heap_live for when next GC ends. - // Set to ^uint64(0) if disabled. - // - // Read and written atomically, unless the world is stopped. - next_gc uint64 - // Protected by mheap or stopping the world during GC. last_gc_unix uint64 // last gc (in unix time) pause_total_ns uint64 @@ -92,69 +87,8 @@ type mstats struct { _ [1 - _NumSizeClasses%2]uint32 last_gc_nanotime uint64 // last gc (monotonic time) - tinyallocs uint64 // number of tiny allocations that didn't cause actual allocation; not exported to go directly - last_next_gc uint64 // next_gc for the previous GC last_heap_inuse uint64 // heap_inuse at mark termination of the previous GC - // triggerRatio is the heap growth ratio that triggers marking. - // - // E.g., if this is 0.6, then GC should start when the live - // heap has reached 1.6 times the heap size marked by the - // previous cycle. This should be ≤ GOGC/100 so the trigger - // heap size is less than the goal heap size. This is set - // during mark termination for the next cycle's trigger. - triggerRatio float64 - - // gc_trigger is the heap size that triggers marking. - // - // When heap_live ≥ gc_trigger, the mark phase will start. - // This is also the heap size by which proportional sweeping - // must be complete. - // - // This is computed from triggerRatio during mark termination - // for the next cycle's trigger. - gc_trigger uint64 - - // heap_live is the number of bytes considered live by the GC. - // That is: retained by the most recent GC plus allocated - // since then. heap_live <= alloc, since alloc includes unmarked - // objects that have not yet been swept (and hence goes up as we - // allocate and down as we sweep) while heap_live excludes these - // objects (and hence only goes up between GCs). - // - // This is updated atomically without locking. To reduce - // contention, this is updated only when obtaining a span from - // an mcentral and at this point it counts all of the - // unallocated slots in that span (which will be allocated - // before that mcache obtains another span from that - // mcentral). Hence, it slightly overestimates the "true" live - // heap size. It's better to overestimate than to - // underestimate because 1) this triggers the GC earlier than - // necessary rather than potentially too late and 2) this - // leads to a conservative GC rate rather than a GC rate that - // is potentially too low. - // - // Reads should likewise be atomic (or during STW). - // - // Whenever this is updated, call traceHeapAlloc() and - // gcController.revise(). - heap_live uint64 - - // heap_scan is the number of bytes of "scannable" heap. This - // is the live heap (as counted by heap_live), but omitting - // no-scan objects and no-scan tails of objects. - // - // Whenever this is updated, call gcController.revise(). - // - // Read and written atomically or with the world stopped. - heap_scan uint64 - - // heap_marked is the number of bytes marked by the previous - // GC. After mark termination, heap_live == heap_marked, but - // unlike heap_live, heap_marked does not change until the - // next mark termination. - heap_marked uint64 - // heapStats is a set of statistics heapStats consistentHeapStats @@ -443,10 +377,6 @@ type MemStats struct { } func init() { - if offset := unsafe.Offsetof(memstats.heap_live); offset%8 != 0 { - println(offset) - throw("memstats.heap_live not aligned to 8 bytes") - } if offset := unsafe.Offsetof(memstats.heapStats); offset%8 != 0 { println(offset) throw("memstats.heapStats not aligned to 8 bytes") @@ -523,7 +453,7 @@ func readmemstats_m(stats *MemStats) { // at a more granular level in the runtime. stats.GCSys = memstats.gcMiscSys.load() + memstats.gcWorkBufInUse + memstats.gcProgPtrScalarBitsInUse stats.OtherSys = memstats.other_sys.load() - stats.NextGC = memstats.next_gc + stats.NextGC = gcController.heapGoal stats.LastGC = memstats.last_gc_unix stats.PauseTotalNs = memstats.pause_total_ns stats.PauseNs = memstats.pause_ns @@ -656,8 +586,8 @@ func updatememstats() { } // Account for tiny allocations. - memstats.nfree += memstats.tinyallocs - memstats.nmalloc += memstats.tinyallocs + memstats.nfree += uint64(consStats.tinyAllocCount) + memstats.nmalloc += uint64(consStats.tinyAllocCount) // Calculate derived stats. memstats.total_alloc = totalAlloc @@ -772,6 +702,7 @@ type heapStatsDelta struct { inPtrScalarBits int64 // byte delta of memory reserved for unrolled GC prog bits // Allocator stats. + tinyAllocCount uintptr // number of tiny allocations largeAlloc uintptr // bytes allocated for large objects largeAllocCount uintptr // number of large object allocations smallAllocCount [_NumSizeClasses]uintptr // number of allocs for small objects @@ -781,7 +712,7 @@ type heapStatsDelta struct { // Add a uint32 to ensure this struct is a multiple of 8 bytes in size. // Only necessary on 32-bit platforms. - // _ [(sys.PtrSize / 4) % 2]uint32 + _ [(sys.PtrSize / 4) % 2]uint32 } // merge adds in the deltas from b into a. @@ -793,6 +724,7 @@ func (a *heapStatsDelta) merge(b *heapStatsDelta) { a.inWorkBufs += b.inWorkBufs a.inPtrScalarBits += b.inPtrScalarBits + a.tinyAllocCount += b.tinyAllocCount a.largeAlloc += b.largeAlloc a.largeAllocCount += b.largeAllocCount for i := range b.smallAllocCount { diff --git a/libgo/go/runtime/nbpipe_pipe.go b/libgo/go/runtime/nbpipe_pipe.go index 822b294..b17257e 100644 --- a/libgo/go/runtime/nbpipe_pipe.go +++ b/libgo/go/runtime/nbpipe_pipe.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly +//go:build aix || darwin +// +build aix darwin package runtime diff --git a/libgo/go/runtime/nbpipe_pipe2.go b/libgo/go/runtime/nbpipe_pipe2.go index 76fb40c..34ead01 100644 --- a/libgo/go/runtime/nbpipe_pipe2.go +++ b/libgo/go/runtime/nbpipe_pipe2.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build freebsd || hurd || linux || netbsd || openbsd || solaris // +build freebsd hurd linux netbsd openbsd solaris package runtime diff --git a/libgo/go/runtime/nbpipe_test.go b/libgo/go/runtime/nbpipe_test.go index d7c5d45..22d41cd 100644 --- a/libgo/go/runtime/nbpipe_test.go +++ b/libgo/go/runtime/nbpipe_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package runtime_test diff --git a/libgo/go/runtime/netpoll.go b/libgo/go/runtime/netpoll.go index 879112a..82380f6 100644 --- a/libgo/go/runtime/netpoll.go +++ b/libgo/go/runtime/netpoll.go @@ -26,6 +26,9 @@ import ( // Arm edge-triggered notifications for fd. The pd argument is to pass // back to netpollready when fd is ready. Return an errno value. // +// func netpollclose(fd uintptr) int32 +// Disable notifications for fd. Return an errno value. +// // func netpoll(delta int64) gList // Poll the network. If delta < 0, block indefinitely. If delta == 0, // poll without blocking. If delta > 0, block for up to delta nanoseconds. @@ -165,9 +168,12 @@ func poll_runtime_pollOpen(fd uintptr) (uintptr, int) { pd.self = pd unlock(&pd.lock) - var errno int32 - errno = netpollopen(fd, pd) - return uintptr(unsafe.Pointer(pd)), int(errno) + errno := netpollopen(fd, pd) + if errno != 0 { + pollcache.free(pd) + return 0, int(errno) + } + return uintptr(unsafe.Pointer(pd)), 0 } //go:linkname poll_runtime_pollClose internal_1poll.runtime__pollClose diff --git a/libgo/go/runtime/netpoll_epoll.go b/libgo/go/runtime/netpoll_epoll.go index 9c5d338..60a1dc0 100644 --- a/libgo/go/runtime/netpoll_epoll.go +++ b/libgo/go/runtime/netpoll_epoll.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux // +build linux package runtime diff --git a/libgo/go/runtime/netpoll_fake.go b/libgo/go/runtime/netpoll_fake.go index b2af3b8..8366f28 100644 --- a/libgo/go/runtime/netpoll_fake.go +++ b/libgo/go/runtime/netpoll_fake.go @@ -5,6 +5,7 @@ // Fake network poller for wasm/js. // Should never be used, because wasm/js network connections do not honor "SetNonblock". +//go:build js && wasm // +build js,wasm package runtime diff --git a/libgo/go/runtime/netpoll_kqueue.go b/libgo/go/runtime/netpoll_kqueue.go index 1724f37..1e1b110 100644 --- a/libgo/go/runtime/netpoll_kqueue.go +++ b/libgo/go/runtime/netpoll_kqueue.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || netbsd || openbsd // +build darwin dragonfly freebsd netbsd openbsd package runtime diff --git a/libgo/go/runtime/netpoll_stub.go b/libgo/go/runtime/netpoll_stub.go index 3599f2d..33ab8eb 100644 --- a/libgo/go/runtime/netpoll_stub.go +++ b/libgo/go/runtime/netpoll_stub.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build plan9 // +build plan9 package runtime diff --git a/libgo/go/runtime/norace_test.go b/libgo/go/runtime/norace_test.go index e90128b..9ad5dde 100644 --- a/libgo/go/runtime/norace_test.go +++ b/libgo/go/runtime/norace_test.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. // The file contains tests that cannot run under race detector for some reason. +//go:build !race // +build !race package runtime_test diff --git a/libgo/go/runtime/os_aix.go b/libgo/go/runtime/os_aix.go index d902ae0..390fefa 100644 --- a/libgo/go/runtime/os_aix.go +++ b/libgo/go/runtime/os_aix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix // +build aix package runtime diff --git a/libgo/go/runtime/os_darwin.go b/libgo/go/runtime/os_darwin.go index 58e0412..0ae716c 100644 --- a/libgo/go/runtime/os_darwin.go +++ b/libgo/go/runtime/os_darwin.go @@ -4,7 +4,9 @@ package runtime -import "unsafe" +import ( + "unsafe" +) type mOS struct { initialized bool @@ -115,10 +117,15 @@ func sigNoteWakeup(*note) { // sigNoteSleep waits for a note created by sigNoteSetup to be woken. func sigNoteSleep(*note) { - entersyscallblock() - var b byte - read(sigNoteRead, unsafe.Pointer(&b), 1) - exitsyscall() + for { + var b byte + entersyscallblock() + n := read(sigNoteRead, unsafe.Pointer(&b), 1) + exitsyscall() + if n != -_EINTR { + return + } + } } // BSD interface for threading. diff --git a/libgo/go/runtime/os_gccgo.go b/libgo/go/runtime/os_gccgo.go index 65d7aef..da12c35 100644 --- a/libgo/go/runtime/os_gccgo.go +++ b/libgo/go/runtime/os_gccgo.go @@ -97,3 +97,11 @@ func setNonblock(fd int32) { fcntlUintptr(uintptr(fd), _F_SETFL, flags|_O_NONBLOCK) } } + +// For gccgo this is in the C code. +func osyield() + +//go:nosplit +func osyield_no_g() { + osyield() +} diff --git a/libgo/go/runtime/os_js.go b/libgo/go/runtime/os_js.go index 24261e8..52b64e76 100644 --- a/libgo/go/runtime/os_js.go +++ b/libgo/go/runtime/os_js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package runtime @@ -30,12 +31,22 @@ func wasmWrite(fd uintptr, p unsafe.Pointer, n int32) func usleep(usec uint32) +//go:nosplit +func usleep_no_g(usec uint32) { + usleep(usec) +} + func exitThread(wait *uint32) type mOS struct{} func osyield() +//go:nosplit +func osyield_no_g() { + osyield() +} + const _SIGSEGV = 0xb func sigpanic() { diff --git a/libgo/go/runtime/os_linux_arm64.go b/libgo/go/runtime/os_linux_arm64.go index 3844620..2b51a2a 100644 --- a/libgo/go/runtime/os_linux_arm64.go +++ b/libgo/go/runtime/os_linux_arm64.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build arm64 // +build arm64 package runtime diff --git a/libgo/go/runtime/os_linux_mips64x.go b/libgo/go/runtime/os_linux_mips64x.go index f905938..bc85ab3 100644 --- a/libgo/go/runtime/os_linux_mips64x.go +++ b/libgo/go/runtime/os_linux_mips64x.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux && (mips64 || mips64le) // +build linux // +build mips64 mips64le diff --git a/libgo/go/runtime/os_linux_mipsx.go b/libgo/go/runtime/os_linux_mipsx.go index 2bfd6f40..be31f19 100644 --- a/libgo/go/runtime/os_linux_mipsx.go +++ b/libgo/go/runtime/os_linux_mipsx.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux && (mips || mipsle) // +build linux // +build mips mipsle diff --git a/libgo/go/runtime/os_linux_noauxv.go b/libgo/go/runtime/os_linux_noauxv.go index 895b4cd..59b5aac 100644 --- a/libgo/go/runtime/os_linux_noauxv.go +++ b/libgo/go/runtime/os_linux_noauxv.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux -// +build !arm,!arm64,!mips,!mipsle,!mips64,!mips64le,!s390x,!ppc64,!ppc64le +//go:build linux && !arm && !arm64 && !mips && !mipsle && !mips64 && !mips64le && !s390x && !ppc64 && !ppc64le +// +build linux,!arm,!arm64,!mips,!mipsle,!mips64,!mips64le,!s390x,!ppc64,!ppc64le package runtime diff --git a/libgo/go/runtime/os_linux_ppc64x.go b/libgo/go/runtime/os_linux_ppc64x.go index cc79cc4..43a75c7 100644 --- a/libgo/go/runtime/os_linux_ppc64x.go +++ b/libgo/go/runtime/os_linux_ppc64x.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux && (ppc64 || ppc64le) // +build linux // +build ppc64 ppc64le diff --git a/libgo/go/runtime/os_only_solaris.go b/libgo/go/runtime/os_only_solaris.go index e2f5409..3829683c 100644 --- a/libgo/go/runtime/os_only_solaris.go +++ b/libgo/go/runtime/os_only_solaris.go @@ -4,6 +4,7 @@ // Solaris code that doesn't also apply to illumos. +//go:build !illumos // +build !illumos package runtime diff --git a/libgo/go/runtime/os_windows_arm64.go b/libgo/go/runtime/os_windows_arm64.go new file mode 100644 index 0000000..7e41344 --- /dev/null +++ b/libgo/go/runtime/os_windows_arm64.go @@ -0,0 +1,14 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +import "unsafe" + +//go:nosplit +func cputicks() int64 { + var counter int64 + stdcall1(_QueryPerformanceCounter, uintptr(unsafe.Pointer(&counter))) + return counter +} diff --git a/libgo/go/runtime/panic32.go b/libgo/go/runtime/panic32.go index fa314af..a2bf7e8 100644 --- a/libgo/go/runtime/panic32.go +++ b/libgo/go/runtime/panic32.go @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build 386 || arm || mips || mipsle || armbe || m68k || nios2 || ppc || riscv || s390 || sh || shbe || sparc +// +build 386 arm mips mipsle armbe m68k nios2 ppc riscv s390 sh shbe sparc + package runtime import _ "unsafe" // for go:linkname diff --git a/libgo/go/runtime/pprof/mprof_test.go b/libgo/go/runtime/pprof/mprof_test.go index 9551ea7..6a448a7 100644 --- a/libgo/go/runtime/pprof/mprof_test.go +++ b/libgo/go/runtime/pprof/mprof_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package pprof @@ -85,6 +86,17 @@ func TestMemoryProfiler(t *testing.T) { runtime.GC() // materialize stats + // TODO(mknyszek): Fix #45315 and remove this extra call. + // + // Unfortunately, it's possible for the sweep termination condition + // to flap, so with just one runtime.GC call, a freed object could be + // missed, leading this test to fail. A second call reduces the chance + // of this happening to zero, because sweeping actually has to finish + // to move on to the next GC, during which nothing will happen. + // + // See #46500 for more details. + runtime.GC() + memoryProfilerRun++ tests := []struct { @@ -93,33 +105,33 @@ func TestMemoryProfiler(t *testing.T) { }{{ stk: []string{"runtime/pprof.allocatePersistent1K", "runtime/pprof.TestMemoryProfiler"}, legacy: fmt.Sprintf(`%v: %v \[%v: %v\] @ 0x[0-9,a-f x]+ -# 0x[0-9,a-f]+ runtime/pprof\.allocatePersistent1K\+0x[0-9,a-f]+ .*/mprof_test\.go:47 -# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test\.go:82 +# 0x[0-9,a-f]+ runtime/pprof\.allocatePersistent1K\+0x[0-9,a-f]+ .*/mprof_test\.go:48 +# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test\.go:83 `, 32*memoryProfilerRun, 1024*memoryProfilerRun, 32*memoryProfilerRun, 1024*memoryProfilerRun), }, { stk: []string{"runtime/pprof.allocateTransient1M", "runtime/pprof.TestMemoryProfiler"}, legacy: fmt.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @ 0x[0-9,a-f x]+ -# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient1M\+0x[0-9,a-f]+ .*/mprof_test.go:24 -# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:79 +# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient1M\+0x[0-9,a-f]+ .*/mprof_test.go:25 +# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:80 `, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun), }, { stk: []string{"runtime/pprof.allocateTransient2M", "runtime/pprof.TestMemoryProfiler"}, // This should start with "0: 0" but gccgo's imprecise // GC means that sometimes the value is not collected. legacy: fmt.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @ 0x[0-9,a-f x]+ -# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient2M\+0x[0-9,a-f]+ .*/mprof_test.go:30 -# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:80 +# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient2M\+0x[0-9,a-f]+ .*/mprof_test.go:31 +# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:81 `, memoryProfilerRun, (2<<20)*memoryProfilerRun, memoryProfilerRun, (2<<20)*memoryProfilerRun), }, { stk: []string{"runtime/pprof.allocateTransient2MInline", "runtime/pprof.TestMemoryProfiler"}, legacy: fmt.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @ 0x[0-9,a-f x]+ -# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient2MInline\+0x[0-9,a-f]+ .*/mprof_test.go:34 -# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:81 +# 0x[0-9,a-f]+ runtime/pprof\.allocateTransient2MInline\+0x[0-9,a-f]+ .*/mprof_test.go:35 +# 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:82 `, memoryProfilerRun, (4<<20)*memoryProfilerRun, memoryProfilerRun, (4<<20)*memoryProfilerRun), }, { stk: []string{"runtime/pprof.allocateReflectTransient"}, legacy: fmt.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @( 0x[0-9,a-f]+)+ -# 0x[0-9,a-f]+ runtime/pprof\.allocateReflectTransient\+0x[0-9,a-f]+ .*/mprof_test.go:55 +# 0x[0-9,a-f]+ runtime/pprof\.allocateReflectTransient\+0x[0-9,a-f]+ .*/mprof_test.go:56 `, memoryProfilerRun, (3<<20)*memoryProfilerRun, memoryProfilerRun, (3<<20)*memoryProfilerRun), }} diff --git a/libgo/go/runtime/pprof/pprof.go b/libgo/go/runtime/pprof/pprof.go index 52df44a..54838fc 100644 --- a/libgo/go/runtime/pprof/pprof.go +++ b/libgo/go/runtime/pprof/pprof.go @@ -857,45 +857,7 @@ func countMutex() int { // writeBlock writes the current blocking profile to w. func writeBlock(w io.Writer, debug int) error { - var p []runtime.BlockProfileRecord - n, ok := runtime.BlockProfile(nil) - for { - p = make([]runtime.BlockProfileRecord, n+50) - n, ok = runtime.BlockProfile(p) - if ok { - p = p[:n] - break - } - } - - sort.Slice(p, func(i, j int) bool { return p[i].Cycles > p[j].Cycles }) - - if debug <= 0 { - return printCountCycleProfile(w, "contentions", "delay", scaleBlockProfile, p) - } - - b := bufio.NewWriter(w) - tw := tabwriter.NewWriter(w, 1, 8, 1, '\t', 0) - w = tw - - fmt.Fprintf(w, "--- contention:\n") - fmt.Fprintf(w, "cycles/second=%v\n", runtime_cyclesPerSecond()) - for i := range p { - r := &p[i] - fmt.Fprintf(w, "%v %v @", r.Cycles, r.Count) - for _, pc := range r.Stack() { - fmt.Fprintf(w, " %#x", pc) - } - fmt.Fprint(w, "\n") - if debug > 0 { - printStackRecord(w, r.Stack(), true) - } - } - - if tw != nil { - tw.Flush() - } - return b.Flush() + return writeProfileInternal(w, debug, "contention", runtime.BlockProfile, scaleBlockProfile) } func scaleBlockProfile(cnt int64, ns float64) (int64, float64) { @@ -908,12 +870,16 @@ func scaleBlockProfile(cnt int64, ns float64) (int64, float64) { // writeMutex writes the current mutex profile to w. func writeMutex(w io.Writer, debug int) error { - // TODO(pjw): too much common code with writeBlock. FIX! + return writeProfileInternal(w, debug, "mutex", runtime.MutexProfile, scaleMutexProfile) +} + +// writeProfileInternal writes the current blocking or mutex profile depending on the passed parameters +func writeProfileInternal(w io.Writer, debug int, name string, runtimeProfile func([]runtime.BlockProfileRecord) (int, bool), scaleProfile func(int64, float64) (int64, float64)) error { var p []runtime.BlockProfileRecord - n, ok := runtime.MutexProfile(nil) + n, ok := runtimeProfile(nil) for { p = make([]runtime.BlockProfileRecord, n+50) - n, ok = runtime.MutexProfile(p) + n, ok = runtimeProfile(p) if ok { p = p[:n] break @@ -923,16 +889,18 @@ func writeMutex(w io.Writer, debug int) error { sort.Slice(p, func(i, j int) bool { return p[i].Cycles > p[j].Cycles }) if debug <= 0 { - return printCountCycleProfile(w, "contentions", "delay", scaleMutexProfile, p) + return printCountCycleProfile(w, "contentions", "delay", scaleProfile, p) } b := bufio.NewWriter(w) tw := tabwriter.NewWriter(w, 1, 8, 1, '\t', 0) w = tw - fmt.Fprintf(w, "--- mutex:\n") + fmt.Fprintf(w, "--- %v:\n", name) fmt.Fprintf(w, "cycles/second=%v\n", runtime_cyclesPerSecond()) - fmt.Fprintf(w, "sampling period=%d\n", runtime.SetMutexProfileFraction(-1)) + if name == "mutex" { + fmt.Fprintf(w, "sampling period=%d\n", runtime.SetMutexProfileFraction(-1)) + } for i := range p { r := &p[i] fmt.Fprintf(w, "%v %v @", r.Cycles, r.Count) diff --git a/libgo/go/runtime/pprof/pprof_norusage.go b/libgo/go/runtime/pprof/pprof_norusage.go index 6fdcc6c..e175dd3 100644 --- a/libgo/go/runtime/pprof/pprof_norusage.go +++ b/libgo/go/runtime/pprof/pprof_norusage.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !darwin && !linux // +build !darwin,!linux package pprof diff --git a/libgo/go/runtime/pprof/pprof_rusage.go b/libgo/go/runtime/pprof/pprof_rusage.go index 7954673..269f21b 100644 --- a/libgo/go/runtime/pprof/pprof_rusage.go +++ b/libgo/go/runtime/pprof/pprof_rusage.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || linux // +build darwin linux package pprof diff --git a/libgo/go/runtime/pprof/pprof_test.go b/libgo/go/runtime/pprof/pprof_test.go index 73d7aaa..ab96b0c 100644 --- a/libgo/go/runtime/pprof/pprof_test.go +++ b/libgo/go/runtime/pprof/pprof_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package pprof @@ -13,6 +14,7 @@ import ( "internal/profile" "internal/testenv" "io" + "math" "math/big" "os" "os/exec" @@ -23,6 +25,7 @@ import ( "sync/atomic" "testing" "time" + _ "unsafe" ) func cpuHogger(f func(x int) int, y *int, dur time.Duration) { @@ -257,40 +260,43 @@ func parseProfile(t *testing.T, valBytes []byte, f func(uintptr, []*profile.Loca return p } +func cpuProfilingBroken() bool { + switch runtime.GOOS { + case "plan9": + // Profiling unimplemented. + return true + case "aix": + // See https://golang.org/issue/45170. + return true + case "ios", "dragonfly", "netbsd", "illumos", "solaris": + // See https://golang.org/issue/13841. + return true + case "openbsd": + if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" { + // See https://golang.org/issue/13841. + return true + } + } + + return false +} + // testCPUProfile runs f under the CPU profiler, checking for some conditions specified by need, // as interpreted by matches, and returns the parsed profile. func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []string, f func(dur time.Duration)) *profile.Profile { switch runtime.GOOS { - case "darwin", "ios": - switch runtime.GOARCH { - case "arm64": - // nothing - default: - out, err := exec.Command("uname", "-a").CombinedOutput() - if err != nil { - t.Fatal(err) - } - vers := string(out) - t.Logf("uname -a: %v", vers) + case "darwin": + out, err := exec.Command("uname", "-a").CombinedOutput() + if err != nil { + t.Fatal(err) } + vers := string(out) + t.Logf("uname -a: %v", vers) case "plan9": t.Skip("skipping on plan9") } - broken := false - switch runtime.GOOS { - // 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" { - broken = true - } - case "windows": - if runtime.GOARCH == "arm" { - broken = true // See https://golang.org/issues/42862 - } - } + broken := cpuProfilingBroken() maxDuration := 5 * time.Second if testing.Short() && broken { @@ -524,8 +530,10 @@ func TestGoroutineSwitch(t *testing.T) { } StopCPUProfile() - // Read profile to look for entries for runtime.gogo with an attempt at a traceback. - // The special entry + // Read profile to look for entries for gogo with an attempt at a traceback. + // "runtime.gogo" is OK, because that's the part of the context switch + // before the actual switch begins. But we should not see "gogo", + // aka "gogo<>(SB)", which does the actual switch and is marked SPWRITE. parseProfile(t, prof.Bytes(), func(count uintptr, stk []*profile.Location, _ map[string][]string) { // An entry with two frames with 'System' in its top frame // exists to record a PC without a traceback. Those are okay. @@ -536,13 +544,19 @@ func TestGoroutineSwitch(t *testing.T) { } } - // Otherwise, should not see runtime.gogo. + // An entry with just one frame is OK too: + // it knew to stop at gogo. + if len(stk) == 1 { + return + } + + // Otherwise, should not see gogo. // The place we'd see it would be the inner most frame. name := stk[0].Line[0].Function.Name - if name == "runtime.gogo" { + if name == "gogo" { var buf bytes.Buffer fprintStack(&buf, stk) - t.Fatalf("found profile entry for runtime.gogo:\n%s", buf.String()) + t.Fatalf("found profile entry for gogo:\n%s", buf.String()) } }) } @@ -616,17 +630,20 @@ func TestMorestack(t *testing.T) { //go:noinline func growstack1() { - growstack() + growstack(10) } //go:noinline -func growstack() { - var buf [8 << 10]byte +func growstack(n int) { + var buf [8 << 18]byte use(buf) + if n > 0 { + growstack(n - 1) + } } //go:noinline -func use(x [8 << 10]byte) {} +func use(x [8 << 18]byte) {} func TestBlockProfile(t *testing.T) { t.Skip("lots of details are different for gccgo; FIXME") @@ -905,6 +922,74 @@ func blockCond() { mu.Unlock() } +// See http://golang.org/cl/299991. +func TestBlockProfileBias(t *testing.T) { + rate := int(1000) // arbitrary value + runtime.SetBlockProfileRate(rate) + defer runtime.SetBlockProfileRate(0) + + // simulate blocking events + blockFrequentShort(rate) + blockInfrequentLong(rate) + + var w bytes.Buffer + Lookup("block").WriteTo(&w, 0) + p, err := profile.Parse(&w) + if err != nil { + t.Fatalf("failed to parse profile: %v", err) + } + t.Logf("parsed proto: %s", p) + + il := float64(-1) // blockInfrequentLong duration + fs := float64(-1) // blockFrequentShort duration + for _, s := range p.Sample { + for _, l := range s.Location { + for _, line := range l.Line { + if len(s.Value) < 2 { + t.Fatal("block profile has less than 2 sample types") + } + + if line.Function.Name == "runtime/pprof.blockInfrequentLong" { + il = float64(s.Value[1]) + } else if line.Function.Name == "runtime/pprof.blockFrequentShort" { + fs = float64(s.Value[1]) + } + } + } + } + if il == -1 || fs == -1 { + t.Fatal("block profile is missing expected functions") + } + + // stddev of bias from 100 runs on local machine multiplied by 10x + const threshold = 0.2 + if bias := (il - fs) / il; math.Abs(bias) > threshold { + t.Fatalf("bias: abs(%f) > %f", bias, threshold) + } else { + t.Logf("bias: abs(%f) < %f", bias, threshold) + } +} + +// blockFrequentShort produces 100000 block events with an average duration of +// rate / 10. +func blockFrequentShort(rate int) { + for i := 0; i < 100000; i++ { + blockevent(int64(rate/10), 1) + } +} + +// blockFrequentShort produces 10000 block events with an average duration of +// rate. +func blockInfrequentLong(rate int) { + for i := 0; i < 10000; i++ { + blockevent(int64(rate), 1) + } +} + +// Used by TestBlockProfileBias. +//go:linkname blockevent runtime.blockevent +func blockevent(cycles int64, skip int) + func TestMutexProfile(t *testing.T) { // Generate mutex profile diff --git a/libgo/go/runtime/preempt_nonwindows.go b/libgo/go/runtime/preempt_nonwindows.go index 3066a152..365e86a 100644 --- a/libgo/go/runtime/preempt_nonwindows.go +++ b/libgo/go/runtime/preempt_nonwindows.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows // +build !windows package runtime diff --git a/libgo/go/runtime/print.go b/libgo/go/runtime/print.go index be51ac0..d141061 100644 --- a/libgo/go/runtime/print.go +++ b/libgo/go/runtime/print.go @@ -238,13 +238,15 @@ func printint(v int64) { printuint(uint64(v)) } +var minhexdigits = 0 // protected by printlock + func printhex(v uint64) { const dig = "0123456789abcdef" var buf [100]byte i := len(buf) for i--; i > 0; i-- { buf[i] = dig[v%16] - if v < 16 { + if v < 16 && len(buf)-i >= minhexdigits { break } v /= 16 @@ -287,29 +289,16 @@ func printiface(i iface) { // and should return a character mark to appear just before that // word's value. It can return 0 to indicate no mark. func hexdumpWords(p, end uintptr, mark func(uintptr) byte) { - p1 := func(x uintptr) { - var buf [2 * sys.PtrSize]byte - for i := len(buf) - 1; i >= 0; i-- { - if x&0xF < 10 { - buf[i] = byte(x&0xF) + '0' - } else { - buf[i] = byte(x&0xF) - 10 + 'a' - } - x >>= 4 - } - gwrite(buf[:]) - } - printlock() var markbuf [1]byte markbuf[0] = ' ' + minhexdigits = int(unsafe.Sizeof(uintptr(0)) * 2) for i := uintptr(0); p+i < end; i += sys.PtrSize { if i%16 == 0 { if i != 0 { println() } - p1(p + i) - print(": ") + print(hex(p+i), ": ") } if mark != nil { @@ -320,16 +309,17 @@ func hexdumpWords(p, end uintptr, mark func(uintptr) byte) { } gwrite(markbuf[:]) val := *(*uintptr)(unsafe.Pointer(p + i)) - p1(val) + print(hex(val)) print(" ") // Can we symbolize val? name, _, _, _ := funcfileline(val, -1, false) if name != "" { entry := funcentry(val) - print("<", name, "+", val-entry, "> ") + print("<", name, "+", hex(val-entry), "> ") } } + minhexdigits = 0 println() printunlock() } diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go index 037e779..0534290 100644 --- a/libgo/go/runtime/proc.go +++ b/libgo/go/runtime/proc.go @@ -68,8 +68,6 @@ func main_init() //extern main.main func main_main() -var buildVersion = sys.TheVersion - // set using cmd/go/internal/modload.ModInfoProg var modinfo string @@ -108,33 +106,64 @@ var modinfo string // any work to do. // // The current approach: -// We unpark an additional thread when we ready a goroutine if (1) there is an -// idle P and there are no "spinning" worker threads. A worker thread is considered -// spinning if it is out of local work and did not find work in global run queue/ -// netpoller; the spinning state is denoted in m.spinning and in sched.nmspinning. -// Threads unparked this way are also considered spinning; we don't do goroutine -// handoff so such threads are out of work initially. Spinning threads do some -// spinning looking for work in per-P run queues before parking. If a spinning +// +// This approach applies to three primary sources of potential work: readying a +// goroutine, new/modified-earlier timers, and idle-priority GC. See below for +// additional details. +// +// We unpark an additional thread when we submit work if (this is wakep()): +// 1. There is an idle P, and +// 2. There are no "spinning" worker threads. +// +// A worker thread is considered spinning if it is out of local work and did +// not find work in the global run queue or netpoller; the spinning state is +// denoted in m.spinning and in sched.nmspinning. Threads unparked this way are +// also considered spinning; we don't do goroutine handoff so such threads are +// out of work initially. Spinning threads spin on looking for work in per-P +// run queues and timer heaps or from the GC before parking. If a spinning // thread finds work it takes itself out of the spinning state and proceeds to -// execution. If it does not find work it takes itself out of the spinning state -// and then parks. -// If there is at least one spinning thread (sched.nmspinning>1), we don't unpark -// new threads when readying goroutines. To compensate for that, if the last spinning -// thread finds work and stops spinning, it must unpark a new spinning thread. -// This approach smooths out unjustified spikes of thread unparking, -// but at the same time guarantees eventual maximal CPU parallelism utilization. +// execution. If it does not find work it takes itself out of the spinning +// state and then parks. +// +// If there is at least one spinning thread (sched.nmspinning>1), we don't +// unpark new threads when submitting work. To compensate for that, if the last +// spinning thread finds work and stops spinning, it must unpark a new spinning +// thread. This approach smooths out unjustified spikes of thread unparking, +// but at the same time guarantees eventual maximal CPU parallelism +// utilization. +// +// The main implementation complication is that we need to be very careful +// during spinning->non-spinning thread transition. This transition can race +// with submission of new work, and either one part or another needs to unpark +// another worker thread. If they both fail to do that, we can end up with +// semi-persistent CPU underutilization. // -// The main implementation complication is that we need to be very careful during -// spinning->non-spinning thread transition. This transition can race with submission -// of a new goroutine, and either one part or another needs to unpark another worker -// thread. If they both fail to do that, we can end up with semi-persistent CPU -// underutilization. The general pattern for goroutine readying is: submit a goroutine -// to local work queue, #StoreLoad-style memory barrier, check sched.nmspinning. -// The general pattern for spinning->non-spinning transition is: decrement nmspinning, -// #StoreLoad-style memory barrier, check all per-P work queues for new work. -// Note that all this complexity does not apply to global run queue as we are not -// sloppy about thread unparking when submitting to global queue. Also see comments -// for nmspinning manipulation. +// The general pattern for submission is: +// 1. Submit work to the local run queue, timer heap, or GC state. +// 2. #StoreLoad-style memory barrier. +// 3. Check sched.nmspinning. +// +// The general pattern for spinning->non-spinning transition is: +// 1. Decrement nmspinning. +// 2. #StoreLoad-style memory barrier. +// 3. Check all per-P work queues and GC for new work. +// +// Note that all this complexity does not apply to global run queue as we are +// not sloppy about thread unparking when submitting to global queue. Also see +// comments for nmspinning manipulation. +// +// How these different sources of work behave varies, though it doesn't affect +// the synchronization approach: +// * Ready goroutine: this is an obvious source of work; the goroutine is +// immediately ready and must run on some thread eventually. +// * New/modified-earlier timer: The current timer implementation (see time.go) +// uses netpoll in a thread with no work available to wait for the soonest +// timer. If there is no thread waiting, we want a new spinning thread to go +// wait. +// * Idle-priority GC: The GC wakes a stopped idle thread to contribute to +// background GC work (note: currently disabled per golang.org/issue/19112). +// Also see golang.org/issue/44313, as this should be extended to all GC +// workers. var ( m0 m @@ -514,8 +543,8 @@ var ( allglock mutex allgs []*g - // allglen and allgptr are atomic variables that contain len(allg) and - // &allg[0] respectively. Proper ordering depends on totally-ordered + // allglen and allgptr are atomic variables that contain len(allgs) and + // &allgs[0] respectively. Proper ordering depends on totally-ordered // loads and stores. Writes are protected by allglock. // // allgptr is updated before allglen. Readers should read allglen @@ -556,6 +585,30 @@ func atomicAllGIndex(ptr **g, i uintptr) *g { return *(**g)(add(unsafe.Pointer(ptr), i*sys.PtrSize)) } +// forEachG calls fn on every G from allgs. +// +// forEachG takes a lock to exclude concurrent addition of new Gs. +func forEachG(fn func(gp *g)) { + lock(&allglock) + for _, gp := range allgs { + fn(gp) + } + unlock(&allglock) +} + +// forEachGRace calls fn on every G from allgs. +// +// forEachGRace avoids locking, but does not exclude addition of new Gs during +// execution, which may be missed. +func forEachGRace(fn func(gp *g)) { + ptr, length := atomicAllG() + for i := uintptr(0); i < length; i++ { + gp := atomicAllGIndex(ptr, i) + fn(gp) + } + return +} + const ( // Number of goroutine ids to grab from sched.goidgen to local per-P cache at once. // 16 seems to provide enough amortization, but other than that it's mostly arbitrary number. @@ -649,6 +702,11 @@ func schedinit() { sigsave(&_g_.m.sigmask) initSigmask = _g_.m.sigmask + if offset := unsafe.Offsetof(sched.timeToRun); offset%8 != 0 { + println(offset) + throw("sched.timeToRun not aligned to 8 bytes") + } + goargs() goenvs() parsedebugvars() @@ -925,6 +983,37 @@ func casgstatus(gp *g, oldval, newval uint32) { nextYield = nanotime() + yieldDelay/2 } } + + // Handle tracking for scheduling latencies. + if oldval == _Grunning { + // Track every 8th time a goroutine transitions out of running. + if gp.trackingSeq%gTrackingPeriod == 0 { + gp.tracking = true + } + gp.trackingSeq++ + } + if gp.tracking { + now := nanotime() + if oldval == _Grunnable { + // We transitioned out of runnable, so measure how much + // time we spent in this state and add it to + // runnableTime. + gp.runnableTime += now - gp.runnableStamp + gp.runnableStamp = 0 + } + if newval == _Grunnable { + // We just transitioned into runnable, so record what + // time that happened. + gp.runnableStamp = now + } else if newval == _Grunning { + // We're transitioning into running, so turn off + // tracking and record how much time we spent in + // runnable. + gp.tracking = false + sched.timeToRun.record(gp.runnableTime) + gp.runnableTime = 0 + } + } } // casGToPreemptScan transitions gp from _Grunning to _Gscan|_Gpreempted. @@ -1235,6 +1324,9 @@ func kickoff() { goexit1() } +// The go:noinline is to guarantee the getcallerpc/getcallersp below are safe, +// so that we can set up g0.sched to return to the call of mstart1 above. +//go:noinline func mstart1() { _g_ := getg() @@ -1370,6 +1462,8 @@ found: } unlock(&sched.lock) + atomic.Xadd64(&ncgocall, int64(m.ncgocall)) + // Release the P. handoffp(releasep()) // After this point we must not have write barriers. @@ -1661,6 +1755,10 @@ func needm() { // Store the original signal mask for use by minit. mp.sigmask = sigmask + // Install TLS on some platforms (previously setg + // would do this if necessary). + osSetupTLS(mp) + // Install g (= m->curg). setg(mp.curg) @@ -1822,7 +1920,7 @@ func lockextra(nilokay bool) *m { for { old := atomic.Loaduintptr(&extram) if old == locked { - osyield() + osyield_no_g() continue } if old == 0 && !nilokay { @@ -1833,13 +1931,13 @@ func lockextra(nilokay bool) *m { atomic.Xadd(&extraMWaiters, 1) incr = true } - usleep(1) + usleep_no_g(1) continue } if atomic.Casuintptr(&extram, old, locked) { return (*m)(unsafe.Pointer(old)) } - osyield() + osyield_no_g() continue } } @@ -2417,85 +2515,40 @@ top: } } - // Steal work from other P's. + // Spinning Ms: steal work from other Ps. + // + // Limit the number of spinning Ms to half the number of busy Ps. + // This is necessary to prevent excessive CPU consumption when + // GOMAXPROCS>>1 but the program parallelism is low. procs := uint32(gomaxprocs) - ranTimer := false - // If number of spinning M's >= number of busy P's, block. - // This is necessary to prevent excessive CPU consumption - // when GOMAXPROCS>>1 but the program parallelism is low. - if !_g_.m.spinning && 2*atomic.Load(&sched.nmspinning) >= procs-atomic.Load(&sched.npidle) { - goto stop - } - if !_g_.m.spinning { - _g_.m.spinning = true - atomic.Xadd(&sched.nmspinning, 1) - } - const stealTries = 4 - for i := 0; i < stealTries; i++ { - stealTimersOrRunNextG := i == stealTries-1 - - for enum := stealOrder.start(fastrand()); !enum.done(); enum.next() { - if sched.gcwaiting != 0 { - goto top - } - p2 := allp[enum.position()] - if _p_ == p2 { - continue - } - - // Steal timers from p2. This call to checkTimers is the only place - // where we might hold a lock on a different P's timers. We do this - // once on the last pass before checking runnext because stealing - // from the other P's runnext should be the last resort, so if there - // are timers to steal do that first. - // - // We only check timers on one of the stealing iterations because - // the time stored in now doesn't change in this loop and checking - // the timers for each P more than once with the same value of now - // is probably a waste of time. - // - // timerpMask tells us whether the P may have timers at all. If it - // can't, no need to check at all. - if stealTimersOrRunNextG && timerpMask.read(enum.position()) { - tnow, w, ran := checkTimers(p2, now) - now = tnow - if w != 0 && (pollUntil == 0 || w < pollUntil) { - pollUntil = w - } - if ran { - // Running the timers may have - // made an arbitrary number of G's - // ready and added them to this P's - // local run queue. That invalidates - // the assumption of runqsteal - // that is always has room to add - // stolen G's. So check now if there - // is a local G to run. - if gp, inheritTime := runqget(_p_); gp != nil { - return gp, inheritTime - } - ranTimer = true - } - } + if _g_.m.spinning || 2*atomic.Load(&sched.nmspinning) < procs-atomic.Load(&sched.npidle) { + if !_g_.m.spinning { + _g_.m.spinning = true + atomic.Xadd(&sched.nmspinning, 1) + } - // Don't bother to attempt to steal if p2 is idle. - if !idlepMask.read(enum.position()) { - if gp := runqsteal(_p_, p2, stealTimersOrRunNextG); gp != nil { - return gp, false - } - } + gp, inheritTime, tnow, w, newWork := stealWork(now) + now = tnow + if gp != nil { + // Successfully stole. + return gp, inheritTime + } + if newWork { + // There may be new timer or GC work; restart to + // discover. + goto top + } + if w != 0 && (pollUntil == 0 || w < pollUntil) { + // Earlier timer to wait for. + pollUntil = w } - } - if ranTimer { - // Running a timer may have made some goroutine ready. - goto top } -stop: - - // We have nothing to do. If we're in the GC mark phase, can - // safely scan and blacken objects, and have work to do, run - // idle-time marking rather than give up the P. + // We have nothing to do. + // + // If we're in the GC mark phase, can safely scan and blacken objects, + // and have work to do, run idle-time marking rather than give up the + // P. if gcBlackenEnabled != 0 && gcMarkWorkAvailable(_p_) { node := (*gcBgMarkWorkerNode)(gcBgMarkWorkerPool.pop()) if node != nil { @@ -2509,17 +2562,11 @@ stop: } } - delta := int64(-1) - if pollUntil != 0 { - // checkTimers ensures that polluntil > now. - delta = pollUntil - now - } - // wasm only: // If a callback returned and no other goroutine is awake, // then wake event handler goroutine which pauses execution // until a callback was triggered. - gp, otherReady := beforeIdle(delta) + gp, otherReady := beforeIdle(now, pollUntil) if gp != nil { casgstatus(gp, _Gwaiting, _Grunnable) if trace.enabled { @@ -2558,18 +2605,25 @@ stop: pidleput(_p_) unlock(&sched.lock) - // Delicate dance: thread transitions from spinning to non-spinning state, - // potentially concurrently with submission of new goroutines. We must - // drop nmspinning first and then check all per-P queues again (with - // #StoreLoad memory barrier in between). If we do it the other way around, - // another thread can submit a goroutine after we've checked all run queues - // but before we drop nmspinning; as a result nobody will unpark a thread - // to run the goroutine. + // Delicate dance: thread transitions from spinning to non-spinning + // state, potentially concurrently with submission of new work. We must + // drop nmspinning first and then check all sources again (with + // #StoreLoad memory barrier in between). If we do it the other way + // around, another thread can submit work after we've checked all + // sources but before we drop nmspinning; as a result nobody will + // unpark a thread to run the work. + // + // This applies to the following sources of work: + // + // * Goroutines added to a per-P run queue. + // * New/modified-earlier timers on a per-P timer heap. + // * Idle-priority GC work (barring golang.org/issue/19112). + // // If we discover new work below, we need to restore m.spinning as a signal // for resetspinning to unpark a new worker thread (because there can be more // than one starving goroutine). However, if after discovering new work - // we also observe no idle Ps, it is OK to just park the current thread: - // the system is fully loaded so no spinning threads are required. + // we also observe no idle Ps it is OK to skip unparking a new worker + // thread: the system is fully loaded so no spinning threads are required. // Also see "Worker thread parking/unparking" comment at the top of the file. wasSpinning := _g_.m.spinning if _g_.m.spinning { @@ -2577,97 +2631,48 @@ stop: if int32(atomic.Xadd(&sched.nmspinning, -1)) < 0 { throw("findrunnable: negative nmspinning") } - } - // check all runqueues once again - for id, _p_ := range allpSnapshot { - if !idlepMaskSnapshot.read(uint32(id)) && !runqempty(_p_) { - lock(&sched.lock) - _p_ = pidleget() - unlock(&sched.lock) - if _p_ != nil { - acquirep(_p_) - if wasSpinning { - _g_.m.spinning = true - atomic.Xadd(&sched.nmspinning, 1) - } - goto top - } - break - } - } - - // Similar to above, check for timer creation or expiry concurrently with - // transitioning from spinning to non-spinning. Note that we cannot use - // checkTimers here because it calls adjusttimers which may need to allocate - // memory, and that isn't allowed when we don't have an active P. - for id, _p_ := range allpSnapshot { - if timerpMaskSnapshot.read(uint32(id)) { - w := nobarrierWakeTime(_p_) - if w != 0 && (pollUntil == 0 || w < pollUntil) { - pollUntil = w - } - } - } - if pollUntil != 0 { - if now == 0 { - now = nanotime() - } - delta = pollUntil - now - if delta < 0 { - delta = 0 - } - } + // Note the for correctness, only the last M transitioning from + // spinning to non-spinning must perform these rechecks to + // ensure no missed work. We are performing it on every M that + // transitions as a conservative change to monitor effects on + // latency. See golang.org/issue/43997. - // Check for idle-priority GC work again. - // - // N.B. Since we have no P, gcBlackenEnabled may change at any time; we - // must check again after acquiring a P. - if atomic.Load(&gcBlackenEnabled) != 0 && gcMarkWorkAvailable(nil) { - // Work is available; we can start an idle GC worker only if - // there is an available P and available worker G. - // - // We can attempt to acquire these in either order. Workers are - // almost always available (see comment in findRunnableGCWorker - // for the one case there may be none). Since we're slightly - // less likely to find a P, check for that first. - lock(&sched.lock) - var node *gcBgMarkWorkerNode - _p_ = pidleget() + // Check all runqueues once again. + _p_ = checkRunqsNoP(allpSnapshot, idlepMaskSnapshot) if _p_ != nil { - // Now that we own a P, gcBlackenEnabled can't change - // (as it requires STW). - if gcBlackenEnabled != 0 { - node = (*gcBgMarkWorkerNode)(gcBgMarkWorkerPool.pop()) - if node == nil { - pidleput(_p_) - _p_ = nil - } - } else { - pidleput(_p_) - _p_ = nil - } + acquirep(_p_) + _g_.m.spinning = true + atomic.Xadd(&sched.nmspinning, 1) + goto top } - unlock(&sched.lock) + + // Check for idle-priority GC work again. + _p_, gp = checkIdleGCNoP() if _p_ != nil { acquirep(_p_) - if wasSpinning { - _g_.m.spinning = true - atomic.Xadd(&sched.nmspinning, 1) - } + _g_.m.spinning = true + atomic.Xadd(&sched.nmspinning, 1) // Run the idle worker. _p_.gcMarkWorkerMode = gcMarkWorkerIdleMode - gp := node.gp.ptr() casgstatus(gp, _Gwaiting, _Grunnable) if trace.enabled { traceGoUnpark(gp, 0) } return gp, false } + + // Finally, check for timer creation or expiry concurrently with + // transitioning from spinning to non-spinning. + // + // Note that we cannot use checkTimers here because it calls + // adjusttimers which may need to allocate memory, and that isn't + // allowed when we don't have an active P. + pollUntil = checkTimersNoP(allpSnapshot, timerpMaskSnapshot, pollUntil) } - // poll network + // Poll network until next timer. if netpollinited() && (atomic.Load(&netpollWaiters) > 0 || pollUntil != 0) && atomic.Xchg64(&sched.lastpoll, 0) != 0 { atomic.Store64(&sched.pollUntil, uint64(pollUntil)) if _g_.m.p != 0 { @@ -2676,11 +2681,21 @@ stop: if _g_.m.spinning { throw("findrunnable: netpoll with spinning") } + delay := int64(-1) + if pollUntil != 0 { + if now == 0 { + now = nanotime() + } + delay = pollUntil - now + if delay < 0 { + delay = 0 + } + } if faketime != 0 { // When using fake time, just poll. - delta = 0 + delay = 0 } - list := netpoll(delta) // block until new work is available + list := netpoll(delay) // block until new work is available atomic.Store64(&sched.pollUntil, 0) atomic.Store64(&sched.lastpoll, uint64(nanotime())) if faketime != 0 && list.empty() { @@ -2742,6 +2757,178 @@ func pollWork() bool { return false } +// stealWork attempts to steal a runnable goroutine or timer from any P. +// +// If newWork is true, new work may have been readied. +// +// If now is not 0 it is the current time. stealWork returns the passed time or +// the current time if now was passed as 0. +func stealWork(now int64) (gp *g, inheritTime bool, rnow, pollUntil int64, newWork bool) { + pp := getg().m.p.ptr() + + ranTimer := false + + const stealTries = 4 + for i := 0; i < stealTries; i++ { + stealTimersOrRunNextG := i == stealTries-1 + + for enum := stealOrder.start(fastrand()); !enum.done(); enum.next() { + if sched.gcwaiting != 0 { + // GC work may be available. + return nil, false, now, pollUntil, true + } + p2 := allp[enum.position()] + if pp == p2 { + continue + } + + // Steal timers from p2. This call to checkTimers is the only place + // where we might hold a lock on a different P's timers. We do this + // once on the last pass before checking runnext because stealing + // from the other P's runnext should be the last resort, so if there + // are timers to steal do that first. + // + // We only check timers on one of the stealing iterations because + // the time stored in now doesn't change in this loop and checking + // the timers for each P more than once with the same value of now + // is probably a waste of time. + // + // timerpMask tells us whether the P may have timers at all. If it + // can't, no need to check at all. + if stealTimersOrRunNextG && timerpMask.read(enum.position()) { + tnow, w, ran := checkTimers(p2, now) + now = tnow + if w != 0 && (pollUntil == 0 || w < pollUntil) { + pollUntil = w + } + if ran { + // Running the timers may have + // made an arbitrary number of G's + // ready and added them to this P's + // local run queue. That invalidates + // the assumption of runqsteal + // that it always has room to add + // stolen G's. So check now if there + // is a local G to run. + if gp, inheritTime := runqget(pp); gp != nil { + return gp, inheritTime, now, pollUntil, ranTimer + } + ranTimer = true + } + } + + // Don't bother to attempt to steal if p2 is idle. + if !idlepMask.read(enum.position()) { + if gp := runqsteal(pp, p2, stealTimersOrRunNextG); gp != nil { + return gp, false, now, pollUntil, ranTimer + } + } + } + } + + // No goroutines found to steal. Regardless, running a timer may have + // made some goroutine ready that we missed. Indicate the next timer to + // wait for. + return nil, false, now, pollUntil, ranTimer +} + +// Check all Ps for a runnable G to steal. +// +// On entry we have no P. If a G is available to steal and a P is available, +// the P is returned which the caller should acquire and attempt to steal the +// work to. +func checkRunqsNoP(allpSnapshot []*p, idlepMaskSnapshot pMask) *p { + for id, p2 := range allpSnapshot { + if !idlepMaskSnapshot.read(uint32(id)) && !runqempty(p2) { + lock(&sched.lock) + pp := pidleget() + unlock(&sched.lock) + if pp != nil { + return pp + } + + // Can't get a P, don't bother checking remaining Ps. + break + } + } + + return nil +} + +// Check all Ps for a timer expiring sooner than pollUntil. +// +// Returns updated pollUntil value. +func checkTimersNoP(allpSnapshot []*p, timerpMaskSnapshot pMask, pollUntil int64) int64 { + for id, p2 := range allpSnapshot { + if timerpMaskSnapshot.read(uint32(id)) { + w := nobarrierWakeTime(p2) + if w != 0 && (pollUntil == 0 || w < pollUntil) { + pollUntil = w + } + } + } + + return pollUntil +} + +// Check for idle-priority GC, without a P on entry. +// +// If some GC work, a P, and a worker G are all available, the P and G will be +// returned. The returned P has not been wired yet. +func checkIdleGCNoP() (*p, *g) { + // N.B. Since we have no P, gcBlackenEnabled may change at any time; we + // must check again after acquiring a P. + if atomic.Load(&gcBlackenEnabled) == 0 { + return nil, nil + } + if !gcMarkWorkAvailable(nil) { + return nil, nil + } + + // Work is available; we can start an idle GC worker only if there is + // an available P and available worker G. + // + // We can attempt to acquire these in either order, though both have + // synchronization concerns (see below). Workers are almost always + // available (see comment in findRunnableGCWorker for the one case + // there may be none). Since we're slightly less likely to find a P, + // check for that first. + // + // Synchronization: note that we must hold sched.lock until we are + // committed to keeping it. Otherwise we cannot put the unnecessary P + // back in sched.pidle without performing the full set of idle + // transition checks. + // + // If we were to check gcBgMarkWorkerPool first, we must somehow handle + // the assumption in gcControllerState.findRunnableGCWorker that an + // empty gcBgMarkWorkerPool is only possible if gcMarkDone is running. + lock(&sched.lock) + pp := pidleget() + if pp == nil { + unlock(&sched.lock) + return nil, nil + } + + // Now that we own a P, gcBlackenEnabled can't change (as it requires + // STW). + if gcBlackenEnabled == 0 { + pidleput(pp) + unlock(&sched.lock) + return nil, nil + } + + node := (*gcBgMarkWorkerNode)(gcBgMarkWorkerPool.pop()) + if node == nil { + pidleput(pp) + unlock(&sched.lock) + return nil, nil + } + + unlock(&sched.lock) + + return pp, node.gp.ptr() +} + // wakeNetPoller wakes up the thread sleeping in the network poller if it isn't // going to wake up before the when argument; or it wakes an idle P to service // timers and the network poller if there isn't one already. @@ -2908,7 +3095,9 @@ top: } if gp == nil && gcBlackenEnabled != 0 { gp = gcController.findRunnableGCWorker(_g_.m.p.ptr()) - tryWakeP = tryWakeP || gp != nil + if gp != nil { + tryWakeP = true + } } if gp == nil { // Check the global runnable queue once in a while to ensure fairness. @@ -2999,7 +3188,7 @@ func dropg() { // checkTimers runs any timers for the P that are ready. // If now is not 0 it is the current time. -// It returns the current time or 0 if it is not known, +// It returns the passed time or the current time if now was passed as 0. // and the time when the next timer should run or 0 if there is no next timer, // and reports whether it ran any timers. // If the time when the next timer should run is not 0, @@ -3149,6 +3338,7 @@ func preemptPark(gp *g) { throw("bad g status") } gp.waitreason = waitReasonPreempted + // Transition from _Grunning to _Gscan|_Gpreempted. We can't // be in _Grunning when we dropg because then we'd be running // without an M, but the moment we're in _Gpreempted, @@ -3527,20 +3717,28 @@ func exitsyscallfast_pidle() bool { // exitsyscall slow path on g0. // Failed to acquire P, enqueue gp as runnable. // +// Called via mcall, so gp is the calling g from this M. +// //go:nowritebarrierrec func exitsyscall0(gp *g) { - _g_ := getg() - casgstatus(gp, _Gsyscall, _Gexitingsyscall) dropg() casgstatus(gp, _Gexitingsyscall, _Grunnable) lock(&sched.lock) var _p_ *p - if schedEnabled(_g_) { + if schedEnabled(gp) { _p_ = pidleget() } + var locked bool if _p_ == nil { globrunqput(gp) + + // Below, we stoplockedm if gp is locked. globrunqput releases + // ownership of gp, so we must check if gp is locked prior to + // committing the release by unlocking sched.lock, otherwise we + // could race with another M transitioning gp from unlocked to + // locked. + locked = gp.lockedm != 0 } else if atomic.Load(&sched.sysmonwait) != 0 { atomic.Store(&sched.sysmonwait, 0) notewakeup(&sched.sysmonnote) @@ -3550,8 +3748,11 @@ func exitsyscall0(gp *g) { acquirep(_p_) execute(gp, false) // Never returns. } - if _g_.m.lockedg != 0 { + if locked { // Wait until another thread schedules gp and so m again. + // + // N.B. lockedm must be this M, as this g was running on this M + // before entersyscall. stoplockedm() execute(gp, false) // Never returns. } @@ -3586,7 +3787,10 @@ func syscall_exitsyscall() { exitsyscall() } -func beforefork() { +// Called from syscall package before fork. +//go:linkname syscall_runtime_BeforeFork syscall.runtime__BeforeFork +//go:nosplit +func syscall_runtime_BeforeFork() { gp := getg().m.curg // Block signals during a fork, so that the child does not run @@ -3597,14 +3801,10 @@ func beforefork() { sigblock(false) } -// Called from syscall package before fork. -//go:linkname syscall_runtime_BeforeFork syscall.runtime__BeforeFork +// Called from syscall package after fork in parent. +//go:linkname syscall_runtime_AfterFork syscall.runtime__AfterFork //go:nosplit -func syscall_runtime_BeforeFork() { - systemstack(beforefork) -} - -func afterfork() { +func syscall_runtime_AfterFork() { gp := getg().m.curg msigrestore(gp.m.sigmask) @@ -3612,13 +3812,6 @@ func afterfork() { gp.m.locks-- } -// Called from syscall package after fork in parent. -//go:linkname syscall_runtime_AfterFork syscall.runtime__AfterFork -//go:nosplit -func syscall_runtime_AfterFork() { - systemstack(afterfork) -} - // inForkedChild is true while manipulating signals in the child process. // This is used to avoid calling libc functions in case we are using vfork. var inForkedChild bool @@ -3734,6 +3927,11 @@ func newproc(fn uintptr, arg unsafe.Pointer) *g { if isSystemGoroutine(newg, false) { atomic.Xadd(&sched.ngsys, +1) } + // Track initial transition? + newg.trackingSeq = uint8(fastrand()) + if newg.trackingSeq%gTrackingPeriod == 0 { + newg.tracking = true + } casgstatus(newg, _Gdead, _Grunnable) if _p_.goidcache == _p_.goidcacheend { @@ -3844,13 +4042,19 @@ func gfput(_p_ *p, gp *g) { _p_.gFree.push(gp) _p_.gFree.n++ if _p_.gFree.n >= 64 { - lock(&sched.gFree.lock) + var ( + inc int32 + noStackQ gQueue + ) for _p_.gFree.n >= 32 { - _p_.gFree.n-- gp = _p_.gFree.pop() - sched.gFree.list.push(gp) - sched.gFree.n++ + _p_.gFree.n-- + noStackQ.push(gp) + inc++ } + lock(&sched.gFree.lock) + sched.gFree.list.pushAll(noStackQ) + sched.gFree.n += inc unlock(&sched.gFree.lock) } } @@ -3884,13 +4088,19 @@ retry: // Purge all cached G's from gfree list to the global list. func gfpurge(_p_ *p) { - lock(&sched.gFree.lock) + var ( + inc int32 + noStackQ gQueue + ) for !_p_.gFree.empty() { gp := _p_.gFree.pop() _p_.gFree.n-- - sched.gFree.list.push(gp) - sched.gFree.n++ + noStackQ.push(gp) + inc++ } + lock(&sched.gFree.lock) + sched.gFree.list.pushAll(noStackQ) + sched.gFree.n += inc unlock(&sched.gFree.lock) } @@ -4061,71 +4271,6 @@ func sigprof(pc uintptr, gp *g, mp *m) { // See golang.org/issue/17165. getg().m.mallocing++ - // Define that a "user g" is a user-created goroutine, and a "system g" - // is one that is m->g0 or m->gsignal. - // - // We might be interrupted for profiling halfway through a - // goroutine switch. The switch involves updating three (or four) values: - // g, PC, SP, and (on arm) LR. The PC must be the last to be updated, - // because once it gets updated the new g is running. - // - // When switching from a user g to a system g, LR is not considered live, - // so the update only affects g, SP, and PC. Since PC must be last, there - // the possible partial transitions in ordinary execution are (1) g alone is updated, - // (2) both g and SP are updated, and (3) SP alone is updated. - // If SP or g alone is updated, we can detect the partial transition by checking - // whether the SP is within g's stack bounds. (We could also require that SP - // be changed only after g, but the stack bounds check is needed by other - // cases, so there is no need to impose an additional requirement.) - // - // There is one exceptional transition to a system g, not in ordinary execution. - // When a signal arrives, the operating system starts the signal handler running - // with an updated PC and SP. The g is updated last, at the beginning of the - // handler. There are two reasons this is okay. First, until g is updated the - // g and SP do not match, so the stack bounds check detects the partial transition. - // Second, signal handlers currently run with signals disabled, so a profiling - // signal cannot arrive during the handler. - // - // When switching from a system g to a user g, there are three possibilities. - // - // First, it may be that the g switch has no PC update, because the SP - // either corresponds to a user g throughout (as in asmcgocall) - // or because it has been arranged to look like a user g frame - // (as in cgocallback). In this case, since the entire - // transition is a g+SP update, a partial transition updating just one of - // those will be detected by the stack bounds check. - // - // Second, when returning from a signal handler, the PC and SP updates - // are performed by the operating system in an atomic update, so the g - // update must be done before them. The stack bounds check detects - // the partial transition here, and (again) signal handlers run with signals - // disabled, so a profiling signal cannot arrive then anyway. - // - // Third, the common case: it may be that the switch updates g, SP, and PC - // separately. If the PC is within any of the functions that does this, - // we don't ask for a traceback. C.F. the function setsSP for more about this. - // - // There is another apparently viable approach, recorded here in case - // the "PC within setsSP function" check turns out not to be usable. - // It would be possible to delay the update of either g or SP until immediately - // before the PC update instruction. Then, because of the stack bounds check, - // the only problematic interrupt point is just before that PC update instruction, - // and the sigprof handler can detect that instruction and simulate stepping past - // it in order to reach a consistent state. On ARM, the update of g must be made - // in two places (in R10 and also in a TLS slot), so the delayed update would - // need to be the SP update. The sigprof handler must read the instruction at - // the current PC and if it was the known instruction (for example, JMP BX or - // MOV R2, PC), use that other register in place of the PC value. - // The biggest drawback to this solution is that it requires that we can tell - // whether it's safe to read from the memory pointed at by PC. - // In a correct program, we can test PC == nil and otherwise read, - // but if a profiling signal happens at the instant that a program executes - // a bad jump (before the program manages to handle the resulting fault) - // the profiling handler could fault trying to read nonexistent memory. - // - // To recap, there are no constraints on the assembly being used for the - // transition. We simply require that g and SP match and that the PC is not - // in gogo. traceback := true // If SIGPROF arrived while already fetching runtime callers @@ -4351,7 +4496,6 @@ func (pp *p) destroy() { moveTimers(plocal, pp.timers) pp.timers = nil pp.numTimers = 0 - pp.adjustTimers = 0 pp.deletedTimers = 0 atomic.Store64(&pp.timer0When, 0) unlock(&pp.timersLock) @@ -4650,11 +4794,9 @@ func checkdead() { } grunning := 0 - lock(&allglock) - for i := 0; i < len(allgs); i++ { - gp := allgs[i] + forEachG(func(gp *g) { if isSystemGoroutine(gp, false) { - continue + return } s := readgstatus(gp) switch s &^ _Gscan { @@ -4667,8 +4809,7 @@ func checkdead() { print("runtime: checkdead: find g ", gp.goid, " in status ", s, "\n") throw("checkdead: runnable g") } - } - unlock(&allglock) + }) if grunning == 0 { // possible if main goroutine calls runtime·Goexit() unlock(&sched.lock) // unlock so that GODEBUG=scheddetail=1 doesn't hang throw("no goroutines (main called runtime.Goexit) - deadlock!") @@ -4972,7 +5113,7 @@ func preemptall() bool { // Tell the goroutine running on processor P to stop. // This function is purely best-effort. It can incorrectly fail to inform the -// goroutine. It can send inform the wrong goroutine. Even if it informs the +// goroutine. It can inform the wrong goroutine. Even if it informs the // correct goroutine, that goroutine might ignore the request if it is // simultaneously executing newstack. // No lock needs to be held. @@ -5080,9 +5221,7 @@ func schedtrace(detailed bool) { print(" M", mp.id, ": p=", id1, " curg=", id2, " mallocing=", mp.mallocing, " throwing=", mp.throwing, " preemptoff=", mp.preemptoff, ""+" locks=", mp.locks, " dying=", mp.dying, " spinning=", mp.spinning, " blocked=", mp.blocked, " lockedg=", id3, "\n") } - lock(&allglock) - for gi := 0; gi < len(allgs); gi++ { - gp := allgs[gi] + forEachG(func(gp *g) { mp := gp.m lockedm := gp.lockedm.ptr() id1 := int64(-1) @@ -5094,8 +5233,7 @@ func schedtrace(detailed bool) { id2 = lockedm.id } print(" G", gp.goid, ": status=", readgstatus(gp), "(", gp.waitreason.String(), ") m=", id1, " lockedm=", id2, "\n") - } - unlock(&allglock) + }) unlock(&sched.lock) } @@ -5190,6 +5328,8 @@ func globrunqputhead(gp *g) { // Put a batch of runnable goroutines on the global runnable queue. // This clears *batch. // sched.lock must be held. +// May run during STW, so write barriers are not allowed. +//go:nowritebarrierrec func globrunqputbatch(batch *gQueue, n int32) { assertLockHeld(&sched.lock) @@ -5505,6 +5645,45 @@ func runqget(_p_ *p) (gp *g, inheritTime bool) { } } +// runqdrain drains the local runnable queue of _p_ and returns all goroutines in it. +// Executed only by the owner P. +func runqdrain(_p_ *p) (drainQ gQueue, n uint32) { + oldNext := _p_.runnext + if oldNext != 0 && _p_.runnext.cas(oldNext, 0) { + drainQ.pushBack(oldNext.ptr()) + n++ + } + +retry: + h := atomic.LoadAcq(&_p_.runqhead) // load-acquire, synchronize with other consumers + t := _p_.runqtail + qn := t - h + if qn == 0 { + return + } + if qn > uint32(len(_p_.runq)) { // read inconsistent h and t + goto retry + } + + if !atomic.CasRel(&_p_.runqhead, h, h+qn) { // cas-release, commits consume + goto retry + } + + // We've inverted the order in which it gets G's from the local P's runnable queue + // and then advances the head pointer because we don't want to mess up the statuses of G's + // while runqdrain() and runqsteal() are running in parallel. + // Thus we should advance the head pointer before draining the local P into a gQueue, + // so that we can update any gp.schedlink only after we take the full ownership of G, + // meanwhile, other P's can't access to all G's in local P's runnable queue and steal them. + // See https://groups.google.com/g/golang-dev/c/0pTKxEKhHSc/m/6Q85QjdVBQAJ for more details. + for i := uint32(0); i < qn; i++ { + gp := _p_.runq[(h+i)%uint32(len(_p_.runq))].ptr() + drainQ.pushBack(gp) + n++ + } + return +} + // Grabs a batch of goroutines from _p_'s runnable queue into batch. // Batch is a ring buffer starting at batchHead. // Returns number of grabbed goroutines. @@ -5698,11 +5877,6 @@ func setMaxThreads(in int) (out int) { return } -func haveexperiment(name string) bool { - // The gofrontend does not support experiments. - return false -} - //go:nosplit func procPin() int { _g_ := getg() @@ -5828,7 +6002,7 @@ var inittrace tracestat type tracestat struct { active bool // init tracing activation status - id int64 // init go routine id + id int64 // init goroutine id allocs uint64 // heap allocations bytes uint64 // heap allocated bytes } diff --git a/libgo/go/runtime/proc_test.go b/libgo/go/runtime/proc_test.go index a8f0dc3..d7549a8 100644 --- a/libgo/go/runtime/proc_test.go +++ b/libgo/go/runtime/proc_test.go @@ -699,6 +699,55 @@ func BenchmarkCreateGoroutinesCapture(b *testing.B) { } } +// warmupScheduler ensures the scheduler has at least targetThreadCount threads +// in its thread pool. +func warmupScheduler(targetThreadCount int) { + var wg sync.WaitGroup + var count int32 + for i := 0; i < targetThreadCount; i++ { + wg.Add(1) + go func() { + atomic.AddInt32(&count, 1) + for atomic.LoadInt32(&count) < int32(targetThreadCount) { + // spin until all threads started + } + + // spin a bit more to ensure they are all running on separate CPUs. + doWork(time.Millisecond) + wg.Done() + }() + } + wg.Wait() +} + +func doWork(dur time.Duration) { + start := time.Now() + for time.Since(start) < dur { + } +} + +// BenchmarkCreateGoroutinesSingle creates many goroutines, all from a single +// producer (the main benchmark goroutine). +// +// Compared to BenchmarkCreateGoroutines, this causes different behavior in the +// scheduler because Ms are much more likely to need to steal work from the +// main P rather than having work in the local run queue. +func BenchmarkCreateGoroutinesSingle(b *testing.B) { + // Since we are interested in stealing behavior, warm the scheduler to + // get all the Ps running first. + warmupScheduler(runtime.GOMAXPROCS(0)) + b.ResetTimer() + + var wg sync.WaitGroup + wg.Add(b.N) + for i := 0; i < b.N; i++ { + go func() { + wg.Done() + }() + } + wg.Wait() +} + func BenchmarkClosureCall(b *testing.B) { sum := 0 off1 := 1 diff --git a/libgo/go/runtime/race0.go b/libgo/go/runtime/race0.go index 180f707..0e431b8 100644 --- a/libgo/go/runtime/race0.go +++ b/libgo/go/runtime/race0.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !race // +build !race // Dummy race detection API, used when not built with -race. diff --git a/libgo/go/runtime/relax_stub.go b/libgo/go/runtime/relax_stub.go index 81ed129..5b92879c2 100644 --- a/libgo/go/runtime/relax_stub.go +++ b/libgo/go/runtime/relax_stub.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !windows // +build !windows package runtime diff --git a/libgo/go/runtime/runtime-lldb_test.go b/libgo/go/runtime/runtime-lldb_test.go index c923b87..19a6cc6 100644 --- a/libgo/go/runtime/runtime-lldb_test.go +++ b/libgo/go/runtime/runtime-lldb_test.go @@ -142,14 +142,10 @@ func TestLldbPython(t *testing.T) { checkLldbPython(t) - dir, err := os.MkdirTemp("", "go-build") - if err != nil { - t.Fatalf("failed to create temp directory: %v", err) - } - defer os.RemoveAll(dir) + dir := t.TempDir() src := filepath.Join(dir, "main.go") - err = os.WriteFile(src, []byte(lldbHelloSource), 0644) + err := os.WriteFile(src, []byte(lldbHelloSource), 0644) if err != nil { t.Fatalf("failed to create src file: %v", err) } diff --git a/libgo/go/runtime/runtime1.go b/libgo/go/runtime/runtime1.go index 143d19e..68e7b9e 100644 --- a/libgo/go/runtime/runtime1.go +++ b/libgo/go/runtime/runtime1.go @@ -321,7 +321,6 @@ var debug struct { gctrace int32 invalidptr int32 madvdontneed int32 // for Linux; issue 28466 - scavenge int32 scavtrace int32 scheddetail int32 schedtrace int32 @@ -350,7 +349,6 @@ var dbgvars = []dbgVar{ {"invalidptr", &debug.invalidptr}, {"madvdontneed", &debug.madvdontneed}, {"sbrk", &debug.sbrk}, - {"scavenge", &debug.scavenge}, {"scavtrace", &debug.scavtrace}, {"scheddetail", &debug.scheddetail}, {"schedtrace", &debug.schedtrace}, diff --git a/libgo/go/runtime/runtime2.go b/libgo/go/runtime/runtime2.go index 1879b82..81a40d5 100644 --- a/libgo/go/runtime/runtime2.go +++ b/libgo/go/runtime/runtime2.go @@ -5,7 +5,6 @@ package runtime import ( - "internal/cpu" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -412,7 +411,18 @@ type g struct { syscallsp uintptr // if status==Gsyscall, syscallsp = sched.sp to use during gc syscallpc uintptr // if status==Gsyscall, syscallpc = sched.pc to use during gc // Not for gccgo: stktopsp uintptr // expected sp at top of stack, to check in traceback - param unsafe.Pointer // passed parameter on wakeup + // param is a generic pointer parameter field used to pass + // values in particular contexts where other storage for the + // parameter would be difficult to find. It is currently used + // in three ways: + // 1. When a channel operation wakes up a blocked goroutine, it sets param to + // point to the sudog of the completed blocking operation. + // 2. By gcAssistAlloc1 to signal back to its caller that the goroutine completed + // the GC cycle. It is unsafe to do so in any other way, because the goroutine's + // stack may have moved in the meantime. + // 3. By debugCallWrap to pass parameters to a new goroutine because allocating a + // closure in the runtime is forbidden. + param unsafe.Pointer atomicstatus uint32 // Not for gccgo: stackLock uint32 // sigprof/scang lock; TODO: fold in to atomicstatus goid int64 @@ -446,6 +456,10 @@ type g struct { raceignore int8 // ignore race detection events sysblocktraced bool // StartTrace has emitted EvGoInSyscall about this goroutine + tracking bool // whether we're tracking this G for sched latency statistics + trackingSeq uint8 // used to decide whether to track this G + runnableStamp int64 // timestamp of when the G last became runnable, only used when tracking + runnableTime int64 // the amount of time spent runnable, cleared when running, only used when tracking sysexitticks int64 // cputicks when syscall has returned (for tracing) traceseq uint64 // trace event sequencer tracelastp puintptr // last P emitted an event for this goroutine @@ -529,6 +543,17 @@ type g struct { stackcontext [10]uintptr // split-stack context } +// gTrackingPeriod is the number of transitions out of _Grunning between +// latency tracking runs. +const gTrackingPeriod = 8 + +const ( + // tlsSlots is the number of pointer-sized slots reserved for TLS on some platforms, + // like Windows. + tlsSlots = 6 + tlsSize = tlsSlots * sys.PtrSize +) + type m struct { g0 *g // goroutine with scheduling stack // Not for gccgo: morebuf gobuf // gobuf arg to morestack @@ -539,7 +564,7 @@ type m struct { gsignal *g // signal-handling g // Not for gccgo: goSigStack gsignalStack // Go-allocated signal handling stack sigmask sigset // storage for saved signal mask - // Not for gccgo: tls [6]uintptr // thread-local storage (for x86 extern register) + // Not for gccgo: tls [tlsSlots]uintptr // thread-local storage (for x86 extern register) mstartfn func() curg *g // current running goroutine caughtsig guintptr // goroutine running during fatal signal @@ -663,6 +688,9 @@ type p struct { // unit and eliminates the (potentially large) scheduling // latency that otherwise arises from adding the ready'd // goroutines to the end of the run queue. + // + // Note that while other P's may atomically CAS this to zero, + // only the owner P can CAS it to a valid G. runnext guintptr // Available G's (status == Gdead) @@ -708,7 +736,7 @@ type p struct { // timerModifiedEarlier status. Because the timer may have been // modified again, there need not be any timer with this value. // This is updated using atomic functions. - // This is 0 if the value is unknown. + // This is 0 if there are no timerModifiedEarlier timers. timerModifiedEarliest uint64 // Per-P GC state @@ -754,12 +782,6 @@ type p struct { // Modified using atomic instructions. numTimers uint32 - // Number of timerModifiedEarlier timers on P's heap. - // This should only be modified while holding timersLock, - // or while the timer status is in a transient state - // such as timerModifying. - adjustTimers uint32 - // Number of timerDeleted timers in P's heap. // Modified using atomic instructions. deletedTimers uint32 @@ -771,7 +793,8 @@ type p struct { // scheduler ASAP (regardless of what G is running on it). preempt bool - pad cpu.CacheLinePad + // Padding is no longer needed. False sharing is now not a worry because p is large enough + // that its size class is an integer multiple of the cache line size (for any of our architectures). } type schedt struct { @@ -860,6 +883,13 @@ type schedt struct { // Acquire and hold this mutex to block sysmon from interacting // with the rest of the runtime. sysmonlock mutex + + // timeToRun is a distribution of scheduling latencies, defined + // as the sum of time a G spends in the _Grunnable state before + // it transitions to _Grunning. + // + // timeToRun is protected by sched.lock. + timeToRun timeHistogram } // Values for the flags field of a sigTabT. diff --git a/libgo/go/runtime/runtime_mmap_test.go b/libgo/go/runtime/runtime_mmap_test.go index 21918c5..8f72daa 100644 --- a/libgo/go/runtime/runtime_mmap_test.go +++ b/libgo/go/runtime/runtime_mmap_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package runtime_test diff --git a/libgo/go/runtime/runtime_test.go b/libgo/go/runtime/runtime_test.go index ca35205..bda09cf 100644 --- a/libgo/go/runtime/runtime_test.go +++ b/libgo/go/runtime/runtime_test.go @@ -270,8 +270,8 @@ func TestTrailingZero(t *testing.T) { n int64 z struct{} } - if unsafe.Sizeof(T2{}) != 8+unsafe.Sizeof(Uintreg(0)) { - t.Errorf("sizeof(%#v)==%d, want %d", T2{}, unsafe.Sizeof(T2{}), 8+unsafe.Sizeof(Uintreg(0))) + if unsafe.Sizeof(T2{}) != 8+unsafe.Sizeof(uintptr(0)) { + t.Errorf("sizeof(%#v)==%d, want %d", T2{}, unsafe.Sizeof(T2{}), 8+unsafe.Sizeof(uintptr(0))) } type T3 struct { n byte diff --git a/libgo/go/runtime/runtime_unix_test.go b/libgo/go/runtime/runtime_unix_test.go index cdad0e2..54e14c9 100644 --- a/libgo/go/runtime/runtime_unix_test.go +++ b/libgo/go/runtime/runtime_unix_test.go @@ -6,6 +6,7 @@ // We need a fast system call to provoke the race, // and Close(-1) is nearly universally fast. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || plan9 // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd plan9 package runtime_test diff --git a/libgo/go/runtime/select.go b/libgo/go/runtime/select.go index 31272b0..d84af07 100644 --- a/libgo/go/runtime/select.go +++ b/libgo/go/runtime/select.go @@ -20,7 +20,7 @@ const debugSelect = false // Select case descriptor. // Known to compiler. -// Changes here must also be made in src/cmd/internal/gc/select.go's scasetype. +// Changes here must also be made in src/cmd/compile/internal/walk/select.go's scasetype. type scase struct { c *hchan // chan elem unsafe.Pointer // data element diff --git a/libgo/go/runtime/semasleep_test.go b/libgo/go/runtime/semasleep_test.go index 9b371b0..905e932 100644 --- a/libgo/go/runtime/semasleep_test.go +++ b/libgo/go/runtime/semasleep_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 && !windows && !js // +build !plan9,!windows,!js package runtime_test diff --git a/libgo/go/runtime/signal_unix.go b/libgo/go/runtime/signal_unix.go index e85136a..a291d2b 100644 --- a/libgo/go/runtime/signal_unix.go +++ b/libgo/go/runtime/signal_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package runtime @@ -288,6 +289,8 @@ func setProcessCPUProfiler(hz int32) { it.it_value = it.it_interval setitimer(_ITIMER_PROF, &it, nil) } else { + setitimer(_ITIMER_PROF, &_itimerval{}, nil) + // If the Go signal handler should be disabled by default, // switch back to the signal handler that was installed // when we enabled profiling. We don't try to handle the case @@ -311,8 +314,6 @@ func setProcessCPUProfiler(hz int32) { setsig(_SIGPROF, h) } } - - setitimer(_ITIMER_PROF, &_itimerval{}, nil) } } diff --git a/libgo/go/runtime/signal_windows_test.go b/libgo/go/runtime/signal_windows_test.go index 33a9b92..1b7cb9d 100644 --- a/libgo/go/runtime/signal_windows_test.go +++ b/libgo/go/runtime/signal_windows_test.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package runtime_test @@ -7,7 +8,6 @@ import ( "bytes" "fmt" "internal/testenv" - "os" "os/exec" "path/filepath" "runtime" @@ -28,15 +28,11 @@ func TestVectoredHandlerDontCrashOnLibrary(t *testing.T) { testenv.MustHaveExecPath(t, "gcc") testprog.Lock() defer testprog.Unlock() - dir, err := os.MkdirTemp("", "go-build") - if err != nil { - t.Fatalf("failed to create temp directory: %v", err) - } - defer os.RemoveAll(dir) + dir := t.TempDir() // build go dll dll := filepath.Join(dir, "testwinlib.dll") - cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", dll, "--buildmode", "c-shared", "testdata/testwinlib/main.go") + cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", dll, "-buildmode", "c-shared", "testdata/testwinlib/main.go") out, err := testenv.CleanCmdEnv(cmd).CombinedOutput() if err != nil { t.Fatalf("failed to build go library: %s\n%s", err, out) @@ -156,15 +152,11 @@ func TestLibraryCtrlHandler(t *testing.T) { testenv.MustHaveExecPath(t, "gcc") testprog.Lock() defer testprog.Unlock() - dir, err := os.MkdirTemp("", "go-build") - if err != nil { - t.Fatalf("failed to create temp directory: %v", err) - } - defer os.RemoveAll(dir) + dir := t.TempDir() // build go dll dll := filepath.Join(dir, "dummy.dll") - cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", dll, "--buildmode", "c-shared", "testdata/testwinlibsignal/dummy.go") + cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", dll, "-buildmode", "c-shared", "testdata/testwinlibsignal/dummy.go") out, err := testenv.CleanCmdEnv(cmd).CombinedOutput() if err != nil { t.Fatalf("failed to build go library: %s\n%s", err, out) diff --git a/libgo/go/runtime/sigqueue.go b/libgo/go/runtime/sigqueue.go index 7ca7557..d5539f1 100644 --- a/libgo/go/runtime/sigqueue.go +++ b/libgo/go/runtime/sigqueue.go @@ -28,6 +28,7 @@ // unnecessary rechecks of sig.mask, but it cannot lead to missed signals // nor deadlocks. +//go:build !plan9 // +build !plan9 package runtime @@ -71,7 +72,7 @@ const ( // It runs from the signal handler, so it's limited in what it can do. func sigsend(s uint32) bool { bit := uint32(1) << uint(s&31) - if !sig.inuse || s >= uint32(32*len(sig.wanted)) { + if s >= uint32(32*len(sig.wanted)) { return false } diff --git a/libgo/go/runtime/sigqueue_note.go b/libgo/go/runtime/sigqueue_note.go index 16aeeb2..e23446b 100644 --- a/libgo/go/runtime/sigqueue_note.go +++ b/libgo/go/runtime/sigqueue_note.go @@ -7,8 +7,8 @@ // signal_recv thread. This file holds the non-Darwin implementations of // those functions. These functions will never be called. -// +build !darwin -// +build !plan9 +//go:build !darwin && !plan9 +// +build !darwin,!plan9 package runtime diff --git a/libgo/go/runtime/sizeclasses.go b/libgo/go/runtime/sizeclasses.go index c5521ce..067871e 100644 --- a/libgo/go/runtime/sizeclasses.go +++ b/libgo/go/runtime/sizeclasses.go @@ -3,74 +3,83 @@ package runtime -// class bytes/obj bytes/span objects tail waste max waste -// 1 8 8192 1024 0 87.50% -// 2 16 8192 512 0 43.75% -// 3 24 8192 341 8 29.24% -// 4 32 8192 256 0 21.88% -// 5 48 8192 170 32 31.52% -// 6 64 8192 128 0 23.44% -// 7 80 8192 102 32 19.07% -// 8 96 8192 85 32 15.95% -// 9 112 8192 73 16 13.56% -// 10 128 8192 64 0 11.72% -// 11 144 8192 56 128 11.82% -// 12 160 8192 51 32 9.73% -// 13 176 8192 46 96 9.59% -// 14 192 8192 42 128 9.25% -// 15 208 8192 39 80 8.12% -// 16 224 8192 36 128 8.15% -// 17 240 8192 34 32 6.62% -// 18 256 8192 32 0 5.86% -// 19 288 8192 28 128 12.16% -// 20 320 8192 25 192 11.80% -// 21 352 8192 23 96 9.88% -// 22 384 8192 21 128 9.51% -// 23 416 8192 19 288 10.71% -// 24 448 8192 18 128 8.37% -// 25 480 8192 17 32 6.82% -// 26 512 8192 16 0 6.05% -// 27 576 8192 14 128 12.33% -// 28 640 8192 12 512 15.48% -// 29 704 8192 11 448 13.93% -// 30 768 8192 10 512 13.94% -// 31 896 8192 9 128 15.52% -// 32 1024 8192 8 0 12.40% -// 33 1152 8192 7 128 12.41% -// 34 1280 8192 6 512 15.55% -// 35 1408 16384 11 896 14.00% -// 36 1536 8192 5 512 14.00% -// 37 1792 16384 9 256 15.57% -// 38 2048 8192 4 0 12.45% -// 39 2304 16384 7 256 12.46% -// 40 2688 8192 3 128 15.59% -// 41 3072 24576 8 0 12.47% -// 42 3200 16384 5 384 6.22% -// 43 3456 24576 7 384 8.83% -// 44 4096 8192 2 0 15.60% -// 45 4864 24576 5 256 16.65% -// 46 5376 16384 3 256 10.92% -// 47 6144 24576 4 0 12.48% -// 48 6528 32768 5 128 6.23% -// 49 6784 40960 6 256 4.36% -// 50 6912 49152 7 768 3.37% -// 51 8192 8192 1 0 15.61% -// 52 9472 57344 6 512 14.28% -// 53 9728 49152 5 512 3.64% -// 54 10240 40960 4 0 4.99% -// 55 10880 32768 3 128 6.24% -// 56 12288 24576 2 0 11.45% -// 57 13568 40960 3 256 9.99% -// 58 14336 57344 4 0 5.35% -// 59 16384 16384 1 0 12.49% -// 60 18432 73728 4 0 11.11% -// 61 19072 57344 3 128 3.57% -// 62 20480 40960 2 0 6.87% -// 63 21760 65536 3 256 6.25% -// 64 24576 24576 1 0 11.45% -// 65 27264 81920 3 128 10.00% -// 66 28672 57344 2 0 4.91% -// 67 32768 32768 1 0 12.50% +// class bytes/obj bytes/span objects tail waste max waste min align +// 1 8 8192 1024 0 87.50% 8 +// 2 16 8192 512 0 43.75% 16 +// 3 24 8192 341 8 29.24% 8 +// 4 32 8192 256 0 21.88% 32 +// 5 48 8192 170 32 31.52% 16 +// 6 64 8192 128 0 23.44% 64 +// 7 80 8192 102 32 19.07% 16 +// 8 96 8192 85 32 15.95% 32 +// 9 112 8192 73 16 13.56% 16 +// 10 128 8192 64 0 11.72% 128 +// 11 144 8192 56 128 11.82% 16 +// 12 160 8192 51 32 9.73% 32 +// 13 176 8192 46 96 9.59% 16 +// 14 192 8192 42 128 9.25% 64 +// 15 208 8192 39 80 8.12% 16 +// 16 224 8192 36 128 8.15% 32 +// 17 240 8192 34 32 6.62% 16 +// 18 256 8192 32 0 5.86% 256 +// 19 288 8192 28 128 12.16% 32 +// 20 320 8192 25 192 11.80% 64 +// 21 352 8192 23 96 9.88% 32 +// 22 384 8192 21 128 9.51% 128 +// 23 416 8192 19 288 10.71% 32 +// 24 448 8192 18 128 8.37% 64 +// 25 480 8192 17 32 6.82% 32 +// 26 512 8192 16 0 6.05% 512 +// 27 576 8192 14 128 12.33% 64 +// 28 640 8192 12 512 15.48% 128 +// 29 704 8192 11 448 13.93% 64 +// 30 768 8192 10 512 13.94% 256 +// 31 896 8192 9 128 15.52% 128 +// 32 1024 8192 8 0 12.40% 1024 +// 33 1152 8192 7 128 12.41% 128 +// 34 1280 8192 6 512 15.55% 256 +// 35 1408 16384 11 896 14.00% 128 +// 36 1536 8192 5 512 14.00% 512 +// 37 1792 16384 9 256 15.57% 256 +// 38 2048 8192 4 0 12.45% 2048 +// 39 2304 16384 7 256 12.46% 256 +// 40 2688 8192 3 128 15.59% 128 +// 41 3072 24576 8 0 12.47% 1024 +// 42 3200 16384 5 384 6.22% 128 +// 43 3456 24576 7 384 8.83% 128 +// 44 4096 8192 2 0 15.60% 4096 +// 45 4864 24576 5 256 16.65% 256 +// 46 5376 16384 3 256 10.92% 256 +// 47 6144 24576 4 0 12.48% 2048 +// 48 6528 32768 5 128 6.23% 128 +// 49 6784 40960 6 256 4.36% 128 +// 50 6912 49152 7 768 3.37% 256 +// 51 8192 8192 1 0 15.61% 8192 +// 52 9472 57344 6 512 14.28% 256 +// 53 9728 49152 5 512 3.64% 512 +// 54 10240 40960 4 0 4.99% 2048 +// 55 10880 32768 3 128 6.24% 128 +// 56 12288 24576 2 0 11.45% 4096 +// 57 13568 40960 3 256 9.99% 256 +// 58 14336 57344 4 0 5.35% 2048 +// 59 16384 16384 1 0 12.49% 8192 +// 60 18432 73728 4 0 11.11% 2048 +// 61 19072 57344 3 128 3.57% 128 +// 62 20480 40960 2 0 6.87% 4096 +// 63 21760 65536 3 256 6.25% 256 +// 64 24576 24576 1 0 11.45% 8192 +// 65 27264 81920 3 128 10.00% 128 +// 66 28672 57344 2 0 4.91% 4096 +// 67 32768 32768 1 0 12.50% 8192 + +// alignment bits min obj size +// 8 3 8 +// 16 4 32 +// 32 5 256 +// 64 6 512 +// 128 7 768 +// 4096 12 28672 +// 8192 13 32768 const ( _MaxSmallSize = 32768 @@ -83,14 +92,6 @@ const ( var class_to_size = [_NumSizeClasses]uint16{0, 8, 16, 24, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256, 288, 320, 352, 384, 416, 448, 480, 512, 576, 640, 704, 768, 896, 1024, 1152, 1280, 1408, 1536, 1792, 2048, 2304, 2688, 3072, 3200, 3456, 4096, 4864, 5376, 6144, 6528, 6784, 6912, 8192, 9472, 9728, 10240, 10880, 12288, 13568, 14336, 16384, 18432, 19072, 20480, 21760, 24576, 27264, 28672, 32768} var class_to_allocnpages = [_NumSizeClasses]uint8{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 2, 3, 1, 3, 2, 3, 4, 5, 6, 1, 7, 6, 5, 4, 3, 5, 7, 2, 9, 7, 5, 8, 3, 10, 7, 4} - -type divMagic struct { - shift uint8 - shift2 uint8 - mul uint16 - baseMask uint16 -} - -var class_to_divmagic = [_NumSizeClasses]divMagic{{0, 0, 0, 0}, {3, 0, 1, 65528}, {4, 0, 1, 65520}, {3, 11, 683, 0}, {5, 0, 1, 65504}, {4, 11, 683, 0}, {6, 0, 1, 65472}, {4, 10, 205, 0}, {5, 9, 171, 0}, {4, 11, 293, 0}, {7, 0, 1, 65408}, {4, 13, 911, 0}, {5, 10, 205, 0}, {4, 12, 373, 0}, {6, 9, 171, 0}, {4, 13, 631, 0}, {5, 11, 293, 0}, {4, 13, 547, 0}, {8, 0, 1, 65280}, {5, 9, 57, 0}, {6, 9, 103, 0}, {5, 12, 373, 0}, {7, 7, 43, 0}, {5, 10, 79, 0}, {6, 10, 147, 0}, {5, 11, 137, 0}, {9, 0, 1, 65024}, {6, 9, 57, 0}, {7, 9, 103, 0}, {6, 11, 187, 0}, {8, 7, 43, 0}, {7, 8, 37, 0}, {10, 0, 1, 64512}, {7, 9, 57, 0}, {8, 6, 13, 0}, {7, 11, 187, 0}, {9, 5, 11, 0}, {8, 8, 37, 0}, {11, 0, 1, 63488}, {8, 9, 57, 0}, {7, 10, 49, 0}, {10, 5, 11, 0}, {7, 10, 41, 0}, {7, 9, 19, 0}, {12, 0, 1, 61440}, {8, 9, 27, 0}, {8, 10, 49, 0}, {11, 5, 11, 0}, {7, 13, 161, 0}, {7, 13, 155, 0}, {8, 9, 19, 0}, {13, 0, 1, 57344}, {8, 12, 111, 0}, {9, 9, 27, 0}, {11, 6, 13, 0}, {7, 14, 193, 0}, {12, 3, 3, 0}, {8, 13, 155, 0}, {11, 8, 37, 0}, {14, 0, 1, 49152}, {11, 8, 29, 0}, {7, 13, 55, 0}, {12, 5, 7, 0}, {8, 14, 193, 0}, {13, 3, 3, 0}, {7, 14, 77, 0}, {12, 7, 19, 0}, {15, 0, 1, 32768}} +var class_to_divmagic = [_NumSizeClasses]uint32{0, ^uint32(0)/8 + 1, ^uint32(0)/16 + 1, ^uint32(0)/24 + 1, ^uint32(0)/32 + 1, ^uint32(0)/48 + 1, ^uint32(0)/64 + 1, ^uint32(0)/80 + 1, ^uint32(0)/96 + 1, ^uint32(0)/112 + 1, ^uint32(0)/128 + 1, ^uint32(0)/144 + 1, ^uint32(0)/160 + 1, ^uint32(0)/176 + 1, ^uint32(0)/192 + 1, ^uint32(0)/208 + 1, ^uint32(0)/224 + 1, ^uint32(0)/240 + 1, ^uint32(0)/256 + 1, ^uint32(0)/288 + 1, ^uint32(0)/320 + 1, ^uint32(0)/352 + 1, ^uint32(0)/384 + 1, ^uint32(0)/416 + 1, ^uint32(0)/448 + 1, ^uint32(0)/480 + 1, ^uint32(0)/512 + 1, ^uint32(0)/576 + 1, ^uint32(0)/640 + 1, ^uint32(0)/704 + 1, ^uint32(0)/768 + 1, ^uint32(0)/896 + 1, ^uint32(0)/1024 + 1, ^uint32(0)/1152 + 1, ^uint32(0)/1280 + 1, ^uint32(0)/1408 + 1, ^uint32(0)/1536 + 1, ^uint32(0)/1792 + 1, ^uint32(0)/2048 + 1, ^uint32(0)/2304 + 1, ^uint32(0)/2688 + 1, ^uint32(0)/3072 + 1, ^uint32(0)/3200 + 1, ^uint32(0)/3456 + 1, ^uint32(0)/4096 + 1, ^uint32(0)/4864 + 1, ^uint32(0)/5376 + 1, ^uint32(0)/6144 + 1, ^uint32(0)/6528 + 1, ^uint32(0)/6784 + 1, ^uint32(0)/6912 + 1, ^uint32(0)/8192 + 1, ^uint32(0)/9472 + 1, ^uint32(0)/9728 + 1, ^uint32(0)/10240 + 1, ^uint32(0)/10880 + 1, ^uint32(0)/12288 + 1, ^uint32(0)/13568 + 1, ^uint32(0)/14336 + 1, ^uint32(0)/16384 + 1, ^uint32(0)/18432 + 1, ^uint32(0)/19072 + 1, ^uint32(0)/20480 + 1, ^uint32(0)/21760 + 1, ^uint32(0)/24576 + 1, ^uint32(0)/27264 + 1, ^uint32(0)/28672 + 1, ^uint32(0)/32768 + 1} var size_to_class8 = [smallSizeMax/smallSizeDiv + 1]uint8{0, 1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32} var size_to_class128 = [(_MaxSmallSize-smallSizeMax)/largeSizeDiv + 1]uint8{32, 33, 34, 35, 36, 37, 37, 38, 38, 39, 39, 40, 40, 40, 41, 41, 41, 42, 43, 43, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 48, 48, 48, 49, 49, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67} diff --git a/libgo/go/runtime/sizeof_test.go b/libgo/go/runtime/sizeof_test.go index 0afb05e..f510eeb 100644 --- a/libgo/go/runtime/sizeof_test.go +++ b/libgo/go/runtime/sizeof_test.go @@ -25,7 +25,7 @@ func TestSizeof(t *testing.T) { _32bit uintptr // size on 32bit platforms _64bit uintptr // size on 64bit platforms }{ - {runtime.G{}, 216, 376}, // g, but exported for testing + {runtime.G{}, 236, 392}, // g, but exported for testing {runtime.Sudog{}, 56, 88}, // sudog, but exported for testing } diff --git a/libgo/go/runtime/slice.go b/libgo/go/runtime/slice.go index d4c0e90..8654aba 100644 --- a/libgo/go/runtime/slice.go +++ b/libgo/go/runtime/slice.go @@ -152,6 +152,18 @@ func unsafeslice64(et *_type, ptr unsafe.Pointer, len64 int64) { unsafeslice(et, ptr, len) } +func unsafeslicecheckptr(et *_type, ptr unsafe.Pointer, len64 int64) { + unsafeslice64(et, ptr, len64) + + /* Commented out for gofrontend. + // Check that underlying array doesn't straddle multiple heap objects. + // unsafeslice64 has already checked for overflow. + if checkptrStraddles(ptr, uintptr(len64)*et.size) { + throw("checkptr: unsafe.Slice result straddles multiple allocations") + } + */ +} + func panicunsafeslicelen() { panic(errorString("unsafe.Slice: len out of range")) } diff --git a/libgo/go/runtime/stubs.go b/libgo/go/runtime/stubs.go index dea7234..e24313c 100644 --- a/libgo/go/runtime/stubs.go +++ b/libgo/go/runtime/stubs.go @@ -274,9 +274,6 @@ func checkASM() bool { return true } -// For gccgo this is in the C code. -func osyield() - //extern __go_syscall6 func syscall(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) uintptr diff --git a/libgo/go/runtime/stubs2.go b/libgo/go/runtime/stubs2.go index 93ff566..c9e5f3d 100644 --- a/libgo/go/runtime/stubs2.go +++ b/libgo/go/runtime/stubs2.go @@ -2,9 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !js -// +build !plan9 -// +build !windows +//go:build !js && !plan9 && !windows +// +build !js,!plan9,!windows package runtime @@ -21,6 +20,11 @@ func closefd(fd int32) int32 func exit(code int32) func usleep(usec uint32) +//go:nosplit +func usleep_no_g(usec uint32) { + usleep(usec) +} + // write calls the write system call. // It returns a non-negative number of bytes written or a negative errno value. //go:noescape diff --git a/libgo/go/runtime/stubs3.go b/libgo/go/runtime/stubs3.go index 35feb10..cb900b2 100644 --- a/libgo/go/runtime/stubs3.go +++ b/libgo/go/runtime/stubs3.go @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//-go:build !aix && !darwin && !freebsd && !openbsd && !plan9 && !solaris +// -build !aix,!darwin,!freebsd,!openbsd,!plan9,!solaris + package runtime func nanotime1() int64 diff --git a/libgo/go/runtime/stubs_linux.go b/libgo/go/runtime/stubs_linux.go index 3c733e3..b8c9579 100644 --- a/libgo/go/runtime/stubs_linux.go +++ b/libgo/go/runtime/stubs_linux.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux // +build linux package runtime diff --git a/libgo/go/runtime/stubs_nonlinux.go b/libgo/go/runtime/stubs_nonlinux.go index 325d35d..4f081d5 100644 --- a/libgo/go/runtime/stubs_nonlinux.go +++ b/libgo/go/runtime/stubs_nonlinux.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !linux // +build !linux package runtime diff --git a/libgo/go/runtime/symtab.go b/libgo/go/runtime/symtab.go index 22a2b13..89a27c4 100644 --- a/libgo/go/runtime/symtab.go +++ b/libgo/go/runtime/symtab.go @@ -62,8 +62,15 @@ func CallersFrames(callers []uintptr) *Frames { return &Frames{callers: callers} } -// Next returns frame information for the next caller. -// If more is false, there are no more callers (the Frame value is valid). +// Next returns a Frame representing the next call frame in the slice +// of PC values. If it has already returned all call frames, Next +// returns a zero Frame. +// +// The more result indicates whether the next call to Next will return +// a valid Frame. It does not necessarily indicate whether this call +// returned one. +// +// See the Frames example for idiomatic usage. func (ci *Frames) Next() (frame Frame, more bool) { if len(ci.callers) == 0 { return Frame{}, false diff --git a/libgo/go/runtime/sys_wasm.go b/libgo/go/runtime/sys_wasm.go index 9bf710b..057ed4c 100644 --- a/libgo/go/runtime/sys_wasm.go +++ b/libgo/go/runtime/sys_wasm.go @@ -27,13 +27,9 @@ func wasmTruncU() func wasmExit(code int32) // adjust Gobuf as it if executed a call to fn with context ctxt -// and then did an immediate gosave. +// and then stopped before the first instruction in fn. func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) { sp := buf.sp - if sys.RegSize > sys.PtrSize { - sp -= sys.PtrSize - *(*uintptr)(unsafe.Pointer(sp)) = 0 - } sp -= sys.PtrSize *(*uintptr)(unsafe.Pointer(sp)) = buf.pc buf.sp = sp diff --git a/libgo/go/runtime/testdata/testprog/checkptr.go b/libgo/go/runtime/testdata/testprog/checkptr.go index e0a2794..9c55613 100644 --- a/libgo/go/runtime/testdata/testprog/checkptr.go +++ b/libgo/go/runtime/testdata/testprog/checkptr.go @@ -4,15 +4,22 @@ package main -import "unsafe" +import ( + "runtime" + "time" + "unsafe" +) func init() { register("CheckPtrAlignmentNoPtr", CheckPtrAlignmentNoPtr) register("CheckPtrAlignmentPtr", CheckPtrAlignmentPtr) + register("CheckPtrAlignmentNilPtr", CheckPtrAlignmentNilPtr) register("CheckPtrArithmetic", CheckPtrArithmetic) register("CheckPtrArithmetic2", CheckPtrArithmetic2) register("CheckPtrSize", CheckPtrSize) register("CheckPtrSmall", CheckPtrSmall) + register("CheckPtrSliceOK", CheckPtrSliceOK) + register("CheckPtrSliceFail", CheckPtrSliceFail) } func CheckPtrAlignmentNoPtr() { @@ -27,6 +34,35 @@ func CheckPtrAlignmentPtr() { sink2 = (**int64)(unsafe.Pointer(uintptr(p) + 1)) } +// CheckPtrAlignmentNilPtr tests that checkptrAlignment doesn't crash +// on nil pointers (#47430). +func CheckPtrAlignmentNilPtr() { + var do func(int) + do = func(n int) { + // Inflate the stack so runtime.shrinkstack gets called during GC + if n > 0 { + do(n - 1) + } + + var p unsafe.Pointer + _ = (*int)(p) + } + + go func() { + for { + runtime.GC() + } + }() + + go func() { + for i := 0; ; i++ { + do(i % 1024) + } + }() + + time.Sleep(time.Second) +} + func CheckPtrArithmetic() { var x int i := uintptr(unsafe.Pointer(&x)) @@ -49,3 +85,14 @@ func CheckPtrSize() { func CheckPtrSmall() { sink2 = unsafe.Pointer(uintptr(1)) } + +func CheckPtrSliceOK() { + p := new([4]int64) + sink2 = unsafe.Slice(&p[1], 3) +} + +func CheckPtrSliceFail() { + p := new(int64) + sink2 = p + sink2 = unsafe.Slice(p, 100) +} diff --git a/libgo/go/runtime/testdata/testprog/crashdump.go b/libgo/go/runtime/testdata/testprog/crashdump.go new file mode 100644 index 0000000..bced397 --- /dev/null +++ b/libgo/go/runtime/testdata/testprog/crashdump.go @@ -0,0 +1,47 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "os" + "runtime" +) + +func init() { + register("CrashDumpsAllThreads", CrashDumpsAllThreads) +} + +func CrashDumpsAllThreads() { + const count = 4 + runtime.GOMAXPROCS(count + 1) + + chans := make([]chan bool, count) + for i := range chans { + chans[i] = make(chan bool) + go crashDumpsAllThreadsLoop(i, chans[i]) + } + + // Wait for all the goroutines to start executing. + for _, c := range chans { + <-c + } + + // Tell our parent that all the goroutines are executing. + if _, err := os.NewFile(3, "pipe").WriteString("x"); err != nil { + fmt.Fprintf(os.Stderr, "write to pipe failed: %v\n", err) + os.Exit(2) + } + + select {} +} + +func crashDumpsAllThreadsLoop(i int, c chan bool) { + close(c) + for { + for j := 0; j < 0x7fffffff; j++ { + } + } +} diff --git a/libgo/go/runtime/testdata/testprogcgo/aprof.go b/libgo/go/runtime/testdata/testprogcgo/aprof.go index aabca9e..44a15b0 100644 --- a/libgo/go/runtime/testdata/testprogcgo/aprof.go +++ b/libgo/go/runtime/testdata/testprogcgo/aprof.go @@ -10,7 +10,7 @@ package main // The test fails when the function is the first C function. // The exported functions are the first C functions, so we use that. -// extern void GoNop(); +// extern void CallGoNop(); import "C" import ( @@ -38,7 +38,7 @@ func CgoCCodeSIGPROF() { break } } - C.GoNop() + C.CallGoNop() } c <- true }() diff --git a/libgo/go/runtime/testdata/testprogcgo/aprof_c.c b/libgo/go/runtime/testdata/testprogcgo/aprof_c.c new file mode 100644 index 0000000..d588e13 --- /dev/null +++ b/libgo/go/runtime/testdata/testprogcgo/aprof_c.c @@ -0,0 +1,9 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "_cgo_export.h" + +void CallGoNop() { + GoNop(); +} diff --git a/libgo/go/runtime/testdata/testprogcgo/bigstack1_windows.c b/libgo/go/runtime/testdata/testprogcgo/bigstack1_windows.c new file mode 100644 index 0000000..551fb68 --- /dev/null +++ b/libgo/go/runtime/testdata/testprogcgo/bigstack1_windows.c @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This is not in bigstack_windows.c because it needs to be part of +// testprogcgo but is not part of the DLL built from bigstack_windows.c. + +#include "_cgo_export.h" + +void CallGoBigStack1(char* p) { + goBigStack1(p); +} diff --git a/libgo/go/runtime/testdata/testprogcgo/bigstack_windows.go b/libgo/go/runtime/testdata/testprogcgo/bigstack_windows.go index f58fcf9..135b5fc 100644 --- a/libgo/go/runtime/testdata/testprogcgo/bigstack_windows.go +++ b/libgo/go/runtime/testdata/testprogcgo/bigstack_windows.go @@ -6,7 +6,7 @@ package main /* typedef void callback(char*); -extern void goBigStack1(char*); +extern void CallGoBigStack1(char*); extern void bigStack(callback*); */ import "C" @@ -18,7 +18,7 @@ func init() { func BigStack() { // Create a large thread stack and call back into Go to test // if Go correctly determines the stack bounds. - C.bigStack((*C.callback)(C.goBigStack1)) + C.bigStack((*C.callback)(C.CallGoBigStack1)) } //export goBigStack1 diff --git a/libgo/go/runtime/testdata/testprogcgo/lockosthread.c b/libgo/go/runtime/testdata/testprogcgo/lockosthread.c index 9a8c057..b10cc4f 100644 --- a/libgo/go/runtime/testdata/testprogcgo/lockosthread.c +++ b/libgo/go/runtime/testdata/testprogcgo/lockosthread.c @@ -9,5 +9,5 @@ uint32_t threadExited; void setExited(void *x) { - __atomic_add_fetch(&threadExited, 1, __ATOMIC_SEQ_CST); + __sync_fetch_and_add(&threadExited, 1); } diff --git a/libgo/go/runtime/testdata/testprogcgo/pprof.go b/libgo/go/runtime/testdata/testprogcgo/pprof.go index 3a3176d..668d4e0 100644 --- a/libgo/go/runtime/testdata/testprogcgo/pprof.go +++ b/libgo/go/runtime/testdata/testprogcgo/pprof.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !gccgo // +build !gccgo package main diff --git a/libgo/go/runtime/testdata/testprogcgo/raceprof.go b/libgo/go/runtime/testdata/testprogcgo/raceprof.go index 0750ec1..c17bb39 100644 --- a/libgo/go/runtime/testdata/testprogcgo/raceprof.go +++ b/libgo/go/runtime/testdata/testprogcgo/raceprof.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ((linux && amd64) || (freebsd && amd64)) && !gccgo // +build linux,amd64 freebsd,amd64 // +build !gccgo diff --git a/libgo/go/runtime/testdata/testprogcgo/threadpprof.go b/libgo/go/runtime/testdata/testprogcgo/threadpprof.go index 3b36c30..ed3faed 100644 --- a/libgo/go/runtime/testdata/testprogcgo/threadpprof.go +++ b/libgo/go/runtime/testdata/testprogcgo/threadpprof.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !plan9,!windows -// +build !gccgo +//go:build !plan9 && !windows && !gccgo +// +build !plan9,!windows,!gccgo package main @@ -50,13 +50,13 @@ void pprofCgoThreadTraceback(void* parg) { arg->buf[0] = (uintptr_t)(cpuHogThread) + 0x10; arg->buf[1] = (uintptr_t)(cpuHogThread2) + 0x4; arg->buf[2] = 0; - __atomic_add_fetch(&cpuHogThreadCount, 1, __ATOMIC_SEQ_CST); + __sync_add_and_fetch(&cpuHogThreadCount, 1); } // getCPUHogThreadCount fetches the number of times we've seen cpuHogThread // in the traceback. int getCPUHogThreadCount() { - return __atomic_load(&cpuHogThreadCount, __ATOMIC_SEQ_CST); + return __sync_add_and_fetch(&cpuHogThreadCount, 0); } static void* cpuHogDriver(void* arg __attribute__ ((unused))) { diff --git a/libgo/go/runtime/testdata/testprogcgo/traceback.go b/libgo/go/runtime/testdata/testprogcgo/traceback.go index 46cf644..e04a635 100644 --- a/libgo/go/runtime/testdata/testprogcgo/traceback.go +++ b/libgo/go/runtime/testdata/testprogcgo/traceback.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !gccgo // +build !gccgo package main diff --git a/libgo/go/runtime/testdata/testprogcgo/traceback_c.c b/libgo/go/runtime/testdata/testprogcgo/traceback_c.c new file mode 100644 index 0000000..4de749c --- /dev/null +++ b/libgo/go/runtime/testdata/testprogcgo/traceback_c.c @@ -0,0 +1,68 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !gccgo +// +build !gccgo + +// The C definitions for traceback.go. That file uses //export so +// it can't put function definitions in the "C" import comment. + +#include <stdint.h> + +char *p; + +int crashInGo; +extern void h1(void); + +int tracebackF3(void) { + if (crashInGo) + h1(); + else + *p = 0; + return 0; +} + +int tracebackF2(void) { + return tracebackF3(); +} + +int tracebackF1(void) { + return tracebackF2(); +} + +struct cgoTracebackArg { + uintptr_t context; + uintptr_t sigContext; + uintptr_t* buf; + uintptr_t max; +}; + +struct cgoSymbolizerArg { + uintptr_t pc; + const char* file; + uintptr_t lineno; + const char* func; + uintptr_t entry; + uintptr_t more; + uintptr_t data; +}; + +void cgoTraceback(void* parg) { + struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg); + arg->buf[0] = 1; + arg->buf[1] = 2; + arg->buf[2] = 3; + arg->buf[3] = 0; +} + +void cgoSymbolizer(void* parg) { + struct cgoSymbolizerArg* arg = (struct cgoSymbolizerArg*)(parg); + if (arg->pc != arg->data + 1) { + arg->file = "unexpected data"; + } else { + arg->file = "cgo symbolizer"; + } + arg->lineno = arg->data + 1; + arg->data++; +} diff --git a/libgo/go/runtime/testdata/testprogcgo/traceback_gccgo.go b/libgo/go/runtime/testdata/testprogcgo/traceback_gccgo.go index 83357fd..2d07c2d 100644 --- a/libgo/go/runtime/testdata/testprogcgo/traceback_gccgo.go +++ b/libgo/go/runtime/testdata/testprogcgo/traceback_gccgo.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build gccgo // +build gccgo package main diff --git a/libgo/go/runtime/testdata/testprogcgo/tracebackctxt.go b/libgo/go/runtime/testdata/testprogcgo/tracebackctxt.go index 3940a77..69078b7 100644 --- a/libgo/go/runtime/testdata/testprogcgo/tracebackctxt.go +++ b/libgo/go/runtime/testdata/testprogcgo/tracebackctxt.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// The __attribute__((weak)) used below doesn't seem to work on Windows. - +//go:build !gccgo // +build !gccgo package main @@ -16,20 +15,24 @@ package main extern void C1(void); extern void C2(void); extern void tcContext(void*); +extern void tcContextSimple(void*); extern void tcTraceback(void*); extern void tcSymbolizer(void*); extern int getContextCount(void); +extern void TracebackContextPreemptionCallGo(int); */ import "C" import ( "fmt" "runtime" + "sync" "unsafe" ) func init() { register("TracebackContext", TracebackContext) + register("TracebackContextPreemption", TracebackContextPreemption) } var tracebackOK bool @@ -107,3 +110,30 @@ wantLoop: tracebackOK = false } } + +// Issue 47441. +func TracebackContextPreemption() { + runtime.SetCgoTraceback(0, unsafe.Pointer(C.tcTraceback), unsafe.Pointer(C.tcContextSimple), unsafe.Pointer(C.tcSymbolizer)) + + const funcs = 10 + const calls = 1e5 + var wg sync.WaitGroup + for i := 0; i < funcs; i++ { + wg.Add(1) + go func(i int) { + defer wg.Done() + for j := 0; j < calls; j++ { + C.TracebackContextPreemptionCallGo(C.int(i*calls + j)) + } + }(i) + } + wg.Wait() + + fmt.Println("OK") +} + +//export TracebackContextPreemptionGoFunction +func TracebackContextPreemptionGoFunction(i C.int) { + // Do some busy work. + fmt.Sprintf("%d\n", i) +} diff --git a/libgo/go/runtime/testdata/testprogcgo/tracebackctxt_c.c b/libgo/go/runtime/testdata/testprogcgo/tracebackctxt_c.c index ff6895e..ff84309 100644 --- a/libgo/go/runtime/testdata/testprogcgo/tracebackctxt_c.c +++ b/libgo/go/runtime/testdata/testprogcgo/tracebackctxt_c.c @@ -5,6 +5,7 @@ // The C definitions for tracebackctxt.go. That file uses //export so // it can't put function definitions in the "C" import comment. +//go:build !gccgo // +build !gccgo #include <stdlib.h> @@ -13,6 +14,7 @@ // Functions exported from Go. extern void G1(void); extern void G2(void); +extern void TracebackContextPreemptionGoFunction(int); void C1() { G1(); @@ -49,25 +51,32 @@ struct cgoSymbolizerArg { static int contextCount; int getContextCount() { - return __atomic_load_n(&contextCount, __ATOMIC_SEQ_CST); + return __sync_add_and_fetch(&contextCount, 0); } void tcContext(void* parg) { struct cgoContextArg* arg = (struct cgoContextArg*)(parg); if (arg->context == 0) { - arg->context = __atomic_add_fetch(&contextCount, 1, __ATOMIC_SEQ_CST); + arg->context = __sync_add_and_fetch(&contextCount, 1); } else { - if (arg->context != __atomic_load_n(&contextCount, __ATOMIC_SEQ_CST)) + if (arg->context != __sync_add_and_fetch(&contextCount, 0)) { abort(); } - __atomic_sub_fetch(&contextCount, 1, __ATOMIC_SEQ_CST); + __sync_sub_and_fetch(&contextCount, 1); + } +} + +void tcContextSimple(void* parg) { + struct cgoContextArg* arg = (struct cgoContextArg*)(parg); + if (arg->context == 0) { + arg->context = 1; } } void tcTraceback(void* parg) { int base, i; struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg); - if (arg->context == 0) { + if (arg->context == 0 && arg->sigContext == 0) { // This shouldn't happen in this program. abort(); } @@ -91,3 +100,7 @@ void tcSymbolizer(void *parg) { arg->func = "cFunction"; arg->lineno = arg->pc + (arg->more << 16); } + +void TracebackContextPreemptionCallGo(int i) { + TracebackContextPreemptionGoFunction(i); +} diff --git a/libgo/go/runtime/testdata/testprogcgo/windows/win.go b/libgo/go/runtime/testdata/testprogcgo/windows/win.go index f2eabb9..12488aa 100644 --- a/libgo/go/runtime/testdata/testprogcgo/windows/win.go +++ b/libgo/go/runtime/testdata/testprogcgo/windows/win.go @@ -1,7 +1,7 @@ package windows /* -#cgo CFLAGS: -mnop-fun-dllimport +#cgo amd64 386 CFLAGS: -mnop-fun-dllimport #include <windows.h> diff --git a/libgo/go/runtime/testdata/testwinlibsignal/dummy.go b/libgo/go/runtime/testdata/testwinlibsignal/dummy.go index 82dfd91..e610f15 100644 --- a/libgo/go/runtime/testdata/testwinlibsignal/dummy.go +++ b/libgo/go/runtime/testdata/testwinlibsignal/dummy.go @@ -1,7 +1,10 @@ +//go:build windows // +build windows package main +import "C" + //export Dummy func Dummy() int { return 42 diff --git a/libgo/go/runtime/testdata/testwinlibsignal/main.c b/libgo/go/runtime/testdata/testwinlibsignal/main.c new file mode 100644 index 0000000..37f2482 --- /dev/null +++ b/libgo/go/runtime/testdata/testwinlibsignal/main.c @@ -0,0 +1,57 @@ +#include <windows.h> +#include <stdio.h> + +HANDLE waitForCtrlBreakEvent; + +BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) +{ + switch (fdwCtrlType) + { + case CTRL_BREAK_EVENT: + SetEvent(waitForCtrlBreakEvent); + return TRUE; + default: + return FALSE; + } +} + +int main(void) +{ + waitForCtrlBreakEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!waitForCtrlBreakEvent) { + fprintf(stderr, "ERROR: Could not create event\n"); + return 1; + } + + if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) + { + fprintf(stderr, "ERROR: Could not set control handler\n"); + return 1; + } + + // The library must be loaded after the SetConsoleCtrlHandler call + // so that the library handler registers after the main program. + // This way the library handler gets called first. + HMODULE dummyDll = LoadLibrary("dummy.dll"); + if (!dummyDll) { + fprintf(stderr, "ERROR: Could not load dummy.dll\n"); + return 1; + } + + // Call the Dummy function so that Go initialization completes, since + // all cgo entry points call out to _cgo_wait_runtime_init_done. + if (((int(*)(void))GetProcAddress(dummyDll, "Dummy"))() != 42) { + fprintf(stderr, "ERROR: Dummy function did not return 42\n"); + return 1; + } + + printf("ready\n"); + fflush(stdout); + + if (WaitForSingleObject(waitForCtrlBreakEvent, 5000) != WAIT_OBJECT_0) { + fprintf(stderr, "FAILURE: No signal received\n"); + return 1; + } + + return 0; +} diff --git a/libgo/go/runtime/time.go b/libgo/go/runtime/time.go index 327726c..7cc9156 100644 --- a/libgo/go/runtime/time.go +++ b/libgo/go/runtime/time.go @@ -332,7 +332,6 @@ func deltimer(t *timer) bool { // Must fetch t.pp before setting status // to timerDeleted. tpp := t.pp.ptr() - atomic.Xadd(&tpp.adjustTimers, -1) if !atomic.Cas(&t.status, timerModifying, timerDeleted) { badTimer() } @@ -509,20 +508,9 @@ loop: tpp := t.pp.ptr() - // Update the adjustTimers field. Subtract one if we - // are removing a timerModifiedEarlier, add one if we - // are adding a timerModifiedEarlier. - adjust := int32(0) - if status == timerModifiedEarlier { - adjust-- - } if newStatus == timerModifiedEarlier { - adjust++ updateTimerModifiedEarliest(tpp, when) } - if adjust != 0 { - atomic.Xadd(&tpp.adjustTimers, adjust) - } // Set the new status of the timer. if !atomic.Cas(&t.status, timerModifying, newStatus) { @@ -590,9 +578,6 @@ func cleantimers(pp *p) { // Move t to the right position. dodeltimer0(pp) doaddtimer(pp, t) - if s == timerModifiedEarlier { - atomic.Xadd(&pp.adjustTimers, -1) - } if !atomic.Cas(&t.status, timerMoving, timerWaiting) { badTimer() } @@ -663,37 +648,23 @@ func moveTimers(pp *p, timers []*timer) { // it also moves timers that have been modified to run later, // and removes deleted timers. The caller must have locked the timers for pp. func adjusttimers(pp *p, now int64) { - if atomic.Load(&pp.adjustTimers) == 0 { - if verifyTimers { - verifyTimerHeap(pp) - } - // There are no timers to adjust, so it is safe to clear - // timerModifiedEarliest. Do so in case it is stale. - // Everything will work if we don't do this, - // but clearing here may save future calls to adjusttimers. - atomic.Store64(&pp.timerModifiedEarliest, 0) - return - } - // If we haven't yet reached the time of the first timerModifiedEarlier // timer, don't do anything. This speeds up programs that adjust // a lot of timers back and forth if the timers rarely expire. // We'll postpone looking through all the adjusted timers until // one would actually expire. - if first := atomic.Load64(&pp.timerModifiedEarliest); first != 0 { - if int64(first) > now { - if verifyTimers { - verifyTimerHeap(pp) - } - return + first := atomic.Load64(&pp.timerModifiedEarliest) + if first == 0 || int64(first) > now { + if verifyTimers { + verifyTimerHeap(pp) } - - // We are going to clear all timerModifiedEarlier timers. - atomic.Store64(&pp.timerModifiedEarliest, 0) + return } + // We are going to clear all timerModifiedEarlier timers. + atomic.Store64(&pp.timerModifiedEarliest, 0) + var moved []*timer -loop: for i := 0; i < len(pp.timers); i++ { t := pp.timers[i] if t.pp.ptr() != pp { @@ -720,11 +691,6 @@ loop: // loop to skip some other timer. dodeltimer(pp, i) moved = append(moved, t) - if s == timerModifiedEarlier { - if n := atomic.Xadd(&pp.adjustTimers, -1); int32(n) <= 0 { - break loop - } - } // Look at this heap position again. i-- } @@ -823,9 +789,6 @@ func runtimer(pp *p, now int64) int64 { t.when = t.nextwhen dodeltimer0(pp) doaddtimer(pp, t) - if s == timerModifiedEarlier { - atomic.Xadd(&pp.adjustTimers, -1) - } if !atomic.Cas(&t.status, timerMoving, timerWaiting) { badTimer() } @@ -898,7 +861,6 @@ func clearDeletedTimers(pp *p) { atomic.Store64(&pp.timerModifiedEarliest, 0) cdel := int32(0) - cearlier := int32(0) to := 0 changedHeap := false timers := pp.timers @@ -923,9 +885,6 @@ nextTimer: if !atomic.Cas(&t.status, timerMoving, timerWaiting) { badTimer() } - if s == timerModifiedEarlier { - cearlier++ - } continue nextTimer } case timerDeleted: @@ -962,7 +921,6 @@ nextTimer: atomic.Xadd(&pp.deletedTimers, -cdel) atomic.Xadd(&pp.numTimers, -cdel) - atomic.Xadd(&pp.adjustTimers, -cearlier) timers = timers[:to] pp.timers = timers diff --git a/libgo/go/runtime/time_fake.go b/libgo/go/runtime/time_fake.go index c64d299..c790fab 100644 --- a/libgo/go/runtime/time_fake.go +++ b/libgo/go/runtime/time_fake.go @@ -2,20 +2,13 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build faketime -// +build !windows - -// Faketime isn't currently supported on Windows. This would require: -// -// 1. Shadowing time_now, which is implemented in assembly on Windows. -// Since that's exported directly to the time package from runtime -// assembly, this would involve moving it from sys_windows_*.s into -// its own assembly files build-tagged with !faketime and using the -// implementation of time_now from timestub.go in faketime mode. -// -// 2. Modifying syscall.Write to call syscall.faketimeWrite, -// translating the Stdout and Stderr handles into FDs 1 and 2. -// (See CL 192739 PS 3.) +//go:build faketime && !windows +// +build faketime,!windows + +// Faketime isn't currently supported on Windows. This would require +// modifying syscall.Write to call syscall.faketimeWrite, +// translating the Stdout and Stderr handles into FDs 1 and 2. +// (See CL 192739 PS 3.) package runtime @@ -44,8 +37,9 @@ func nanotime() int64 { return faketime } -func walltime() (sec int64, nsec int32) { - return faketime / 1000000000, int32(faketime % 1000000000) +//go:linkname time_now time.now +func time_now() (sec int64, nsec int32, mono int64) { + return faketime / 1e9, int32(faketime % 1e9), faketime } func write(fd uintptr, p unsafe.Pointer, n int32) int32 { diff --git a/libgo/go/runtime/time_nofake.go b/libgo/go/runtime/time_nofake.go index 1912a94..5a4ceaf 100644 --- a/libgo/go/runtime/time_nofake.go +++ b/libgo/go/runtime/time_nofake.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !faketime // +build !faketime package runtime @@ -19,10 +20,6 @@ func nanotime() int64 { return nanotime1() } -func walltime() (sec int64, nsec int32) { - return walltime1() -} - // write must be nosplit on Windows (see write1) // //go:nosplit diff --git a/libgo/go/runtime/timeasm.go b/libgo/go/runtime/timeasm.go index 6bfaa8a8..2c06dcb 100644 --- a/libgo/go/runtime/timeasm.go +++ b/libgo/go/runtime/timeasm.go @@ -4,8 +4,10 @@ // Declarations for operating systems implementing time.now directly in assembly. +//go:build ignore && !faketime && (windows || (linux && amd64)) // +build ignore -// +build windows +// +build !faketime +// +build windows linux,amd64 package runtime diff --git a/libgo/go/runtime/timestub.go b/libgo/go/runtime/timestub.go index 14165ce..76de76f 100644 --- a/libgo/go/runtime/timestub.go +++ b/libgo/go/runtime/timestub.go @@ -5,7 +5,10 @@ // Declarations for operating systems implementing time.now // indirectly, in terms of walltime and nanotime assembly. +//-go:build !faketime && !windows && !(linux && amd64) +// -build !faketime // -build !windows +// -build !linux !amd64 package runtime diff --git a/libgo/go/runtime/timestub2.go b/libgo/go/runtime/timestub2.go index f691388..d9b4ee0 100644 --- a/libgo/go/runtime/timestub2.go +++ b/libgo/go/runtime/timestub2.go @@ -2,6 +2,15 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//-go:build !aix && !darwin && !freebsd && !openbsd && !solaris && !windows && !(linux && amd64) +// -build !aix +// -build !darwin +// -build !freebsd +// -build !openbsd +// -build !solaris +// -build !windows +// -build !linux !amd64 + package runtime -func walltime1() (sec int64, nsec int32) +func walltime() (sec int64, nsec int32) diff --git a/libgo/go/runtime/tls_stub.go b/libgo/go/runtime/tls_stub.go new file mode 100644 index 0000000..95dafd0 --- /dev/null +++ b/libgo/go/runtime/tls_stub.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (windows && !amd64) || !windows +// +build windows,!amd64 !windows + +package runtime + +//go:nosplit +func osSetupTLS(mp *m) {} diff --git a/libgo/go/runtime/tls_windows_amd64.go b/libgo/go/runtime/tls_windows_amd64.go new file mode 100644 index 0000000..cacaa84 --- /dev/null +++ b/libgo/go/runtime/tls_windows_amd64.go @@ -0,0 +1,10 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +// osSetupTLS is called by needm to set up TLS for non-Go threads. +// +// Defined in assembly. +func osSetupTLS(mp *m) diff --git a/libgo/go/runtime/trace.go b/libgo/go/runtime/trace.go index f13c81a..a7c36ba 100644 --- a/libgo/go/runtime/trace.go +++ b/libgo/go/runtime/trace.go @@ -53,8 +53,8 @@ const ( traceEvGoSysBlock = 30 // syscall blocks [timestamp] traceEvGoWaiting = 31 // denotes that goroutine is blocked when tracing starts [timestamp, goroutine id] traceEvGoInSyscall = 32 // denotes that goroutine is in syscall when tracing starts [timestamp, goroutine id] - traceEvHeapAlloc = 33 // memstats.heap_live change [timestamp, heap_alloc] - traceEvNextGC = 34 // memstats.next_gc change [timestamp, next_gc] + traceEvHeapAlloc = 33 // gcController.heapLive change [timestamp, heap_alloc] + traceEvHeapGoal = 34 // gcController.heapGoal (formerly next_gc) change [timestamp, heap goal in bytes] traceEvTimerGoroutine = 35 // not currently used; previously denoted timer goroutine [timer goroutine id] traceEvFutileWakeup = 36 // denotes that the previous wakeup of this goroutine was futile [timestamp] traceEvString = 37 // string dictionary entry [ID, length, string] @@ -222,7 +222,8 @@ func StartTrace() error { stackID := traceStackID(mp, stkBuf, 2) releasem(mp) - for _, gp := range allgs { + // World is stopped, no need to lock. + forEachGRace(func(gp *g) { status := readgstatus(gp) if status != _Gdead { gp.traceseq = 0 @@ -242,7 +243,7 @@ func StartTrace() error { } else { gp.sysblocktraced = false } - } + }) traceProcStart() traceGoStart() // Note: ticksStart needs to be set after we emit traceEvGoInSyscall events. @@ -1138,15 +1139,15 @@ func traceGoSysBlock(pp *p) { } func traceHeapAlloc() { - traceEvent(traceEvHeapAlloc, -1, memstats.heap_live) + traceEvent(traceEvHeapAlloc, -1, gcController.heapLive) } -func traceNextGC() { - if nextGC := atomic.Load64(&memstats.next_gc); nextGC == ^uint64(0) { +func traceHeapGoal() { + if heapGoal := atomic.Load64(&gcController.heapGoal); heapGoal == ^uint64(0) { // Heap-based triggering is disabled. - traceEvent(traceEvNextGC, -1, 0) + traceEvent(traceEvHeapGoal, -1, 0) } else { - traceEvent(traceEvNextGC, -1, nextGC) + traceEvent(traceEvHeapGoal, -1, heapGoal) } } diff --git a/libgo/go/runtime/traceback_test.go b/libgo/go/runtime/traceback_test.go new file mode 100644 index 0000000..152db6c --- /dev/null +++ b/libgo/go/runtime/traceback_test.go @@ -0,0 +1,297 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime_test + +import ( + "bytes" + "runtime" + "strings" + "testing" +) + +var testTracebackArgsBuf [1000]byte + +func TestTracebackArgs(t *testing.T) { + tests := []struct { + fn func() int + expect string + }{ + // simple ints + { + func() int { return testTracebackArgs1(1, 2, 3, 4, 5) }, + "testTracebackArgs1(0x1, 0x2, 0x3, 0x4, 0x5)", + }, + // some aggregates + { + func() int { + return testTracebackArgs2(false, struct { + a, b, c int + x [2]int + }{1, 2, 3, [2]int{4, 5}}, [0]int{}, [3]byte{6, 7, 8}) + }, + "testTracebackArgs2(0x0, {0x1, 0x2, 0x3, {0x4, 0x5}}, {}, {0x6, 0x7, 0x8})", + }, + { + func() int { return testTracebackArgs3([3]byte{1, 2, 3}, 4, 5, 6, [3]byte{7, 8, 9}) }, + "testTracebackArgs3({0x1, 0x2, 0x3}, 0x4, 0x5, 0x6, {0x7, 0x8, 0x9})", + }, + // too deeply nested type + { + func() int { return testTracebackArgs4(false, [1][1][1][1][1][1][1][1][1][1]int{}) }, + "testTracebackArgs4(0x0, {{{{{...}}}}})", + }, + // a lot of zero-sized type + { + func() int { + z := [0]int{} + return testTracebackArgs5(false, struct { + x int + y [0]int + z [2][0]int + }{1, z, [2][0]int{}}, z, z, z, z, z, z, z, z, z, z, z, z) + }, + "testTracebackArgs5(0x0, {0x1, {}, {{}, {}}}, {}, {}, {}, {}, {}, ...)", + }, + + // edge cases for ... + // no ... for 10 args + { + func() int { return testTracebackArgs6a(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) }, + "testTracebackArgs6a(0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa)", + }, + // has ... for 11 args + { + func() int { return testTracebackArgs6b(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) }, + "testTracebackArgs6b(0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, ...)", + }, + // no ... for aggregates with 10 words + { + func() int { return testTracebackArgs7a([10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) }, + "testTracebackArgs7a({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa})", + }, + // has ... for aggregates with 11 words + { + func() int { return testTracebackArgs7b([11]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}) }, + "testTracebackArgs7b({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, ...})", + }, + // no ... for aggregates, but with more args + { + func() int { return testTracebackArgs7c([10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 11) }, + "testTracebackArgs7c({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa}, ...)", + }, + // has ... for aggregates and also for more args + { + func() int { return testTracebackArgs7d([11]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 12) }, + "testTracebackArgs7d({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, ...}, ...)", + }, + // nested aggregates, no ... + { + func() int { return testTracebackArgs8a(testArgsType8a{1, 2, 3, 4, 5, 6, 7, 8, [2]int{9, 10}}) }, + "testTracebackArgs8a({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa}})", + }, + // nested aggregates, ... in inner but not outer + { + func() int { return testTracebackArgs8b(testArgsType8b{1, 2, 3, 4, 5, 6, 7, 8, [3]int{9, 10, 11}}) }, + "testTracebackArgs8b({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa, ...}})", + }, + // nested aggregates, ... in outer but not inner + { + func() int { return testTracebackArgs8c(testArgsType8c{1, 2, 3, 4, 5, 6, 7, 8, [2]int{9, 10}, 11}) }, + "testTracebackArgs8c({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa}, ...})", + }, + // nested aggregates, ... in both inner and outer + { + func() int { return testTracebackArgs8d(testArgsType8d{1, 2, 3, 4, 5, 6, 7, 8, [3]int{9, 10, 11}, 12}) }, + "testTracebackArgs8d({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa, ...}, ...})", + }, + } + for _, test := range tests { + n := test.fn() + got := testTracebackArgsBuf[:n] + expect := test.expect + if runtime.Compiler == "gccgo" { + expect = expect[:strings.Index(expect, "(")] + } + if !bytes.Contains(got, []byte(expect)) { + t.Errorf("traceback does not contain expected string: want %q, got\n%s", expect, got) + } + } +} + +//go:noinline +func testTracebackArgs1(a, b, c, d, e int) int { + n := runtime.Stack(testTracebackArgsBuf[:], false) + if a < 0 { + // use in-reg args to keep them alive + return a + b + c + d + e + } + return n +} + +//go:noinline +func testTracebackArgs2(a bool, b struct { + a, b, c int + x [2]int +}, _ [0]int, d [3]byte) int { + n := runtime.Stack(testTracebackArgsBuf[:], false) + if a { + // use in-reg args to keep them alive + return b.a + b.b + b.c + b.x[0] + b.x[1] + int(d[0]) + int(d[1]) + int(d[2]) + } + return n + +} + +//go:noinline +//go:registerparams +func testTracebackArgs3(x [3]byte, a, b, c int, y [3]byte) int { + n := runtime.Stack(testTracebackArgsBuf[:], false) + if a < 0 { + // use in-reg args to keep them alive + return int(x[0]) + int(x[1]) + int(x[2]) + a + b + c + int(y[0]) + int(y[1]) + int(y[2]) + } + return n +} + +//go:noinline +func testTracebackArgs4(a bool, x [1][1][1][1][1][1][1][1][1][1]int) int { + n := runtime.Stack(testTracebackArgsBuf[:], false) + if a { + panic(x) // use args to keep them alive + } + return n +} + +//go:noinline +func testTracebackArgs5(a bool, x struct { + x int + y [0]int + z [2][0]int +}, _, _, _, _, _, _, _, _, _, _, _, _ [0]int) int { + n := runtime.Stack(testTracebackArgsBuf[:], false) + if a { + panic(x) // use args to keep them alive + } + return n +} + +//go:noinline +func testTracebackArgs6a(a, b, c, d, e, f, g, h, i, j int) int { + n := runtime.Stack(testTracebackArgsBuf[:], false) + if a < 0 { + // use in-reg args to keep them alive + return a + b + c + d + e + f + g + h + i + j + } + return n +} + +//go:noinline +func testTracebackArgs6b(a, b, c, d, e, f, g, h, i, j, k int) int { + n := runtime.Stack(testTracebackArgsBuf[:], false) + if a < 0 { + // use in-reg args to keep them alive + return a + b + c + d + e + f + g + h + i + j + k + } + return n +} + +//go:noinline +func testTracebackArgs7a(a [10]int) int { + n := runtime.Stack(testTracebackArgsBuf[:], false) + if a[0] < 0 { + // use in-reg args to keep them alive + return a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + } + return n +} + +//go:noinline +func testTracebackArgs7b(a [11]int) int { + n := runtime.Stack(testTracebackArgsBuf[:], false) + if a[0] < 0 { + // use in-reg args to keep them alive + return a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + a[10] + } + return n +} + +//go:noinline +func testTracebackArgs7c(a [10]int, b int) int { + n := runtime.Stack(testTracebackArgsBuf[:], false) + if a[0] < 0 { + // use in-reg args to keep them alive + return a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + b + } + return n +} + +//go:noinline +func testTracebackArgs7d(a [11]int, b int) int { + n := runtime.Stack(testTracebackArgsBuf[:], false) + if a[0] < 0 { + // use in-reg args to keep them alive + return a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + a[10] + b + } + return n +} + +type testArgsType8a struct { + a, b, c, d, e, f, g, h int + i [2]int +} +type testArgsType8b struct { + a, b, c, d, e, f, g, h int + i [3]int +} +type testArgsType8c struct { + a, b, c, d, e, f, g, h int + i [2]int + j int +} +type testArgsType8d struct { + a, b, c, d, e, f, g, h int + i [3]int + j int +} + +//go:noinline +func testTracebackArgs8a(a testArgsType8a) int { + n := runtime.Stack(testTracebackArgsBuf[:], false) + if a.a < 0 { + // use in-reg args to keep them alive + return a.b + a.c + a.d + a.e + a.f + a.g + a.h + a.i[0] + a.i[1] + } + return n +} + +//go:noinline +func testTracebackArgs8b(a testArgsType8b) int { + n := runtime.Stack(testTracebackArgsBuf[:], false) + if a.a < 0 { + // use in-reg args to keep them alive + return a.b + a.c + a.d + a.e + a.f + a.g + a.h + a.i[0] + a.i[1] + a.i[2] + } + return n +} + +//go:noinline +func testTracebackArgs8c(a testArgsType8c) int { + n := runtime.Stack(testTracebackArgsBuf[:], false) + if a.a < 0 { + // use in-reg args to keep them alive + return a.b + a.c + a.d + a.e + a.f + a.g + a.h + a.i[0] + a.i[1] + a.j + } + return n +} + +//go:noinline +func testTracebackArgs8d(a testArgsType8d) int { + n := runtime.Stack(testTracebackArgsBuf[:], false) + if a.a < 0 { + // use in-reg args to keep them alive + return a.b + a.c + a.d + a.e + a.f + a.g + a.h + a.i[0] + a.i[1] + a.i[2] + a.j + } + return n +} diff --git a/libgo/go/runtime/type.go b/libgo/go/runtime/type.go index 56b4fe6..c788342 100644 --- a/libgo/go/runtime/type.go +++ b/libgo/go/runtime/type.go @@ -24,6 +24,10 @@ const ( tflagRegularMemory tflag = 1 << 3 // equal and hash can treat values of this type as a single region of t.size bytes ) +// Needs to be in sync with +// go/types.cc +// ../reflect/type.go:/^type.rtype. +// ../internal/reflectlite/type.go:/^type.rtype. type _type struct { size uintptr ptrdata uintptr @@ -118,7 +122,7 @@ type maptype struct { } // Note: flag values must match those used in the TMAP case -// in ../cmd/compile/internal/gc/reflect.go:dtypesym. +// in ../cmd/compile/internal/reflectdata/reflect.go:writeType. func (mt *maptype) indirectkey() bool { // store ptr to key instead of key itself return mt.flags&1 != 0 } diff --git a/libgo/go/runtime/write_err.go b/libgo/go/runtime/write_err.go index 6b1467b..a4656fd 100644 --- a/libgo/go/runtime/write_err.go +++ b/libgo/go/runtime/write_err.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !android // +build !android package runtime diff --git a/libgo/go/runtime/write_err_android.go b/libgo/go/runtime/write_err_android.go index 2419fc8..a876900 100644 --- a/libgo/go/runtime/write_err_android.go +++ b/libgo/go/runtime/write_err_android.go @@ -144,7 +144,7 @@ func writeLogdHeader() int { // hdr[3:7] sec unsigned uint32, little endian. // hdr[7:11] nsec unsigned uint32, little endian. hdr[0] = 0 // LOG_ID_MAIN - sec, nsec := walltime() + sec, nsec, _ := time_now() packUint32(hdr[3:7], uint32(sec)) packUint32(hdr[7:11], uint32(nsec)) diff --git a/libgo/go/sort/example_search_test.go b/libgo/go/sort/example_search_test.go index 6928f0f..856422a 100644 --- a/libgo/go/sort/example_search_test.go +++ b/libgo/go/sort/example_search_test.go @@ -40,3 +40,35 @@ func ExampleSearch_descendingOrder() { // Output: // found 6 at index 7 in [55 45 36 28 21 15 10 6 3 1] } + +// This example demonstrates searching for float64 in a list sorted in ascending order. +func ExampleSearchFloat64s() { + a := []float64{1.0, 2.0, 3.3, 4.6, 6.1, 7.2, 8.0} + + x := 2.0 + i := sort.SearchFloat64s(a, x) + fmt.Printf("found %g at index %d in %v\n", x, i, a) + + x = 0.5 + i = sort.SearchFloat64s(a, x) + fmt.Printf("%g not found, can be inserted at index %d in %v\n", x, i, a) + // Output: + // found 2 at index 1 in [1 2 3.3 4.6 6.1 7.2 8] + // 0.5 not found, can be inserted at index 0 in [1 2 3.3 4.6 6.1 7.2 8] +} + +// This example demonstrates searching for int in a list sorted in ascending order. +func ExampleSearchInts() { + a := []int{1, 2, 3, 4, 6, 7, 8} + + x := 2 + i := sort.SearchInts(a, x) + fmt.Printf("found %d at index %d in %v\n", x, i, a) + + x = 5 + i = sort.SearchInts(a, x) + fmt.Printf("%d not found, can be inserted at index %d in %v\n", x, i, a) + // Output: + // found 2 at index 1 in [1 2 3 4 6 7 8] + // 5 not found, can be inserted at index 4 in [1 2 3 4 6 7 8] +} diff --git a/libgo/go/sort/genzfunc.go b/libgo/go/sort/genzfunc.go index e7eb573..ed04e33 100644 --- a/libgo/go/sort/genzfunc.go +++ b/libgo/go/sort/genzfunc.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // This program is run via "go generate" (via a directive in sort.go) diff --git a/libgo/go/sort/slice_go113.go b/libgo/go/sort/slice_go113.go index bf24db7..53542db 100644 --- a/libgo/go/sort/slice_go113.go +++ b/libgo/go/sort/slice_go113.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build go1.13 // +build go1.13 package sort diff --git a/libgo/go/sort/slice_go14.go b/libgo/go/sort/slice_go14.go index 3bf5cbc..5d5949f 100644 --- a/libgo/go/sort/slice_go14.go +++ b/libgo/go/sort/slice_go14.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !go1.8 // +build !go1.8 package sort diff --git a/libgo/go/sort/slice_go18.go b/libgo/go/sort/slice_go18.go index e176604..1538477 100644 --- a/libgo/go/sort/slice_go18.go +++ b/libgo/go/sort/slice_go18.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build go1.8 && !go1.13 // +build go1.8,!go1.13 package sort diff --git a/libgo/go/strconv/atof.go b/libgo/go/strconv/atof.go index 1c50057..6ecd4f1 100644 --- a/libgo/go/strconv/atof.go +++ b/libgo/go/strconv/atof.go @@ -695,7 +695,7 @@ func atof64(s string) (f float64, n int, err error) { // as their respective special floating point values. It ignores case when matching. func ParseFloat(s string, bitSize int) (float64, error) { f, n, err := parseFloatPrefix(s, bitSize) - if err == nil && n != len(s) { + if n != len(s) && (err == nil || err.(*NumError).Err != ErrSyntax) { return 0, syntaxError(fnParseFloat, s) } return f, err diff --git a/libgo/go/strconv/atof_test.go b/libgo/go/strconv/atof_test.go index 3c058b9..aa587a4 100644 --- a/libgo/go/strconv/atof_test.go +++ b/libgo/go/strconv/atof_test.go @@ -342,6 +342,9 @@ var atoftests = []atofTest{ {"0x12.345p-_12", "0", ErrSyntax}, {"0x12.345p+1__2", "0", ErrSyntax}, {"0x12.345p+12_", "0", ErrSyntax}, + + {"1e100x", "0", ErrSyntax}, + {"1e1000x", "0", ErrSyntax}, } var atof32tests = []atofTest{ diff --git a/libgo/go/strconv/atoi.go b/libgo/go/strconv/atoi.go index f6c4efa..631b487 100644 --- a/libgo/go/strconv/atoi.go +++ b/libgo/go/strconv/atoi.go @@ -57,6 +57,8 @@ const IntSize = intSize const maxUint64 = 1<<64 - 1 // ParseUint is like ParseInt but for unsigned numbers. +// +// A sign prefix is not permitted. func ParseUint(s string, base int, bitSize int) (uint64, error) { const fnParseUint = "ParseUint" @@ -143,7 +145,7 @@ func ParseUint(s string, base int, bitSize int) (uint64, error) { n1 := n + uint64(d) if n1 < n || n1 > maxVal { - // n+v overflows + // n+d overflows return maxVal, rangeError(fnParseUint, s0) } n = n1 @@ -159,10 +161,13 @@ func ParseUint(s string, base int, bitSize int) (uint64, error) { // ParseInt interprets a string s in the given base (0, 2 to 36) and // bit size (0 to 64) and returns the corresponding value i. // +// The string may begin with a leading sign: "+" or "-". +// // If the base argument is 0, the true base is implied by the string's -// prefix: 2 for "0b", 8 for "0" or "0o", 16 for "0x", and 10 otherwise. -// Also, for argument base 0 only, underscore characters are permitted -// as defined by the Go syntax for integer literals. +// prefix following the sign (if present): 2 for "0b", 8 for "0" or "0o", +// 16 for "0x", and 10 otherwise. Also, for argument base 0 only, +// underscore characters are permitted as defined by the Go syntax for +// integer literals. // // The bitSize argument specifies the integer type // that the result must fit into. Bit sizes 0, 8, 16, 32, and 64 diff --git a/libgo/go/strconv/atoi_test.go b/libgo/go/strconv/atoi_test.go index 178fb01..867fa66 100644 --- a/libgo/go/strconv/atoi_test.go +++ b/libgo/go/strconv/atoi_test.go @@ -33,6 +33,9 @@ var parseUint64Tests = []parseUint64Test{ {"_12345", 0, ErrSyntax}, {"1__2345", 0, ErrSyntax}, {"12345_", 0, ErrSyntax}, + {"-0", 0, ErrSyntax}, + {"-1", 0, ErrSyntax}, + {"+1", 0, ErrSyntax}, } type parseUint64BaseTest struct { @@ -140,8 +143,10 @@ var parseInt64Tests = []parseInt64Test{ {"", 0, ErrSyntax}, {"0", 0, nil}, {"-0", 0, nil}, + {"+0", 0, nil}, {"1", 1, nil}, {"-1", -1, nil}, + {"+1", 1, nil}, {"12345", 12345, nil}, {"-12345", -12345, nil}, {"012345", 12345, nil}, @@ -236,6 +241,11 @@ var parseInt64BaseTests = []parseInt64BaseTest{ {"0__12345", 0, 0, ErrSyntax}, {"01234__5", 0, 0, ErrSyntax}, {"012345_", 0, 0, ErrSyntax}, + + {"+0xf", 0, 0xf, nil}, + {"-0xf", 0, -0xf, nil}, + {"0x+f", 0, 0, ErrSyntax}, + {"0x-f", 0, 0, ErrSyntax}, } type parseUint32Test struct { diff --git a/libgo/go/strconv/bytealg.go b/libgo/go/strconv/bytealg.go new file mode 100644 index 0000000..a2bb12c --- /dev/null +++ b/libgo/go/strconv/bytealg.go @@ -0,0 +1,15 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !compiler_bootstrap +// +build !compiler_bootstrap + +package strconv + +import "internal/bytealg" + +// index returns the index of the first instance of c in s, or -1 if missing. +func index(s string, c byte) int { + return bytealg.IndexByteString(s, c) +} diff --git a/libgo/go/strconv/bytealg_bootstrap.go b/libgo/go/strconv/bytealg_bootstrap.go new file mode 100644 index 0000000..0ed79f4 --- /dev/null +++ b/libgo/go/strconv/bytealg_bootstrap.go @@ -0,0 +1,18 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build compiler_bootstrap +// +build compiler_bootstrap + +package strconv + +// index returns the index of the first instance of c in s, or -1 if missing. +func index(s string, c byte) int { + for i := 0; i < len(s); i++ { + if s[i] == c { + return i + } + } + return -1 +} diff --git a/libgo/go/strconv/eisel_lemire.go b/libgo/go/strconv/eisel_lemire.go index 6c7f852..fecd1b9 100644 --- a/libgo/go/strconv/eisel_lemire.go +++ b/libgo/go/strconv/eisel_lemire.go @@ -29,7 +29,7 @@ func eiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) { // Exp10 Range. if man == 0 { if neg { - f = math.Float64frombits(0x80000000_00000000) // Negative zero. + f = math.Float64frombits(0x8000000000000000) // Negative zero. } return f, true } @@ -39,7 +39,7 @@ func eiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) { // Normalization. clz := bits.LeadingZeros64(man) - man <<= clz + man <<= uint(clz) const float64ExponentBias = 1023 retExp2 := uint64(217706*exp10>>16+64+float64ExponentBias) - uint64(clz) @@ -84,9 +84,9 @@ func eiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) { if retExp2-1 >= 0x7FF-1 { return 0, false } - retBits := retExp2<<52 | retMantissa&0x000FFFFF_FFFFFFFF + retBits := retExp2<<52 | retMantissa&0x000FFFFFFFFFFFFF if neg { - retBits |= 0x80000000_00000000 + retBits |= 0x8000000000000000 } return math.Float64frombits(retBits), true } @@ -114,7 +114,7 @@ func eiselLemire32(man uint64, exp10 int, neg bool) (f float32, ok bool) { // Normalization. clz := bits.LeadingZeros64(man) - man <<= clz + man <<= uint(clz) const float32ExponentBias = 127 retExp2 := uint64(217706*exp10>>16+64+float32ExponentBias) - uint64(clz) @@ -122,13 +122,13 @@ func eiselLemire32(man uint64, exp10 int, neg bool) (f float32, ok bool) { xHi, xLo := bits.Mul64(man, detailedPowersOfTen[exp10-detailedPowersOfTenMinExp10][1]) // Wider Approximation. - if xHi&0x3F_FFFFFFFF == 0x3F_FFFFFFFF && xLo+man < man { + if xHi&0x3FFFFFFFFF == 0x3FFFFFFFFF && xLo+man < man { yHi, yLo := bits.Mul64(man, detailedPowersOfTen[exp10-detailedPowersOfTenMinExp10][0]) mergedHi, mergedLo := xHi, xLo+yHi if mergedLo < xLo { mergedHi++ } - if mergedHi&0x3F_FFFFFFFF == 0x3F_FFFFFFFF && mergedLo+1 == 0 && yLo+man < man { + if mergedHi&0x3FFFFFFFFF == 0x3FFFFFFFFF && mergedLo+1 == 0 && yLo+man < man { return 0, false } xHi, xLo = mergedHi, mergedLo @@ -140,7 +140,7 @@ func eiselLemire32(man uint64, exp10 int, neg bool) (f float32, ok bool) { retExp2 -= 1 ^ msb // Half-way Ambiguity. - if xLo == 0 && xHi&0x3F_FFFFFFFF == 0 && retMantissa&3 == 1 { + if xLo == 0 && xHi&0x3FFFFFFFFF == 0 && retMantissa&3 == 1 { return 0, false } diff --git a/libgo/go/strconv/extfloat.go b/libgo/go/strconv/extfloat.go deleted file mode 100644 index e7bfe51..0000000 --- a/libgo/go/strconv/extfloat.go +++ /dev/null @@ -1,517 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package strconv - -import ( - "math/bits" -) - -// An extFloat represents an extended floating-point number, with more -// precision than a float64. It does not try to save bits: the -// number represented by the structure is mant*(2^exp), with a negative -// sign if neg is true. -type extFloat struct { - mant uint64 - exp int - neg bool -} - -// Powers of ten taken from double-conversion library. -// https://code.google.com/p/double-conversion/ -const ( - firstPowerOfTen = -348 - stepPowerOfTen = 8 -) - -var smallPowersOfTen = [...]extFloat{ - {1 << 63, -63, false}, // 1 - {0xa << 60, -60, false}, // 1e1 - {0x64 << 57, -57, false}, // 1e2 - {0x3e8 << 54, -54, false}, // 1e3 - {0x2710 << 50, -50, false}, // 1e4 - {0x186a0 << 47, -47, false}, // 1e5 - {0xf4240 << 44, -44, false}, // 1e6 - {0x989680 << 40, -40, false}, // 1e7 -} - -var powersOfTen = [...]extFloat{ - {0xfa8fd5a0081c0288, -1220, false}, // 10^-348 - {0xbaaee17fa23ebf76, -1193, false}, // 10^-340 - {0x8b16fb203055ac76, -1166, false}, // 10^-332 - {0xcf42894a5dce35ea, -1140, false}, // 10^-324 - {0x9a6bb0aa55653b2d, -1113, false}, // 10^-316 - {0xe61acf033d1a45df, -1087, false}, // 10^-308 - {0xab70fe17c79ac6ca, -1060, false}, // 10^-300 - {0xff77b1fcbebcdc4f, -1034, false}, // 10^-292 - {0xbe5691ef416bd60c, -1007, false}, // 10^-284 - {0x8dd01fad907ffc3c, -980, false}, // 10^-276 - {0xd3515c2831559a83, -954, false}, // 10^-268 - {0x9d71ac8fada6c9b5, -927, false}, // 10^-260 - {0xea9c227723ee8bcb, -901, false}, // 10^-252 - {0xaecc49914078536d, -874, false}, // 10^-244 - {0x823c12795db6ce57, -847, false}, // 10^-236 - {0xc21094364dfb5637, -821, false}, // 10^-228 - {0x9096ea6f3848984f, -794, false}, // 10^-220 - {0xd77485cb25823ac7, -768, false}, // 10^-212 - {0xa086cfcd97bf97f4, -741, false}, // 10^-204 - {0xef340a98172aace5, -715, false}, // 10^-196 - {0xb23867fb2a35b28e, -688, false}, // 10^-188 - {0x84c8d4dfd2c63f3b, -661, false}, // 10^-180 - {0xc5dd44271ad3cdba, -635, false}, // 10^-172 - {0x936b9fcebb25c996, -608, false}, // 10^-164 - {0xdbac6c247d62a584, -582, false}, // 10^-156 - {0xa3ab66580d5fdaf6, -555, false}, // 10^-148 - {0xf3e2f893dec3f126, -529, false}, // 10^-140 - {0xb5b5ada8aaff80b8, -502, false}, // 10^-132 - {0x87625f056c7c4a8b, -475, false}, // 10^-124 - {0xc9bcff6034c13053, -449, false}, // 10^-116 - {0x964e858c91ba2655, -422, false}, // 10^-108 - {0xdff9772470297ebd, -396, false}, // 10^-100 - {0xa6dfbd9fb8e5b88f, -369, false}, // 10^-92 - {0xf8a95fcf88747d94, -343, false}, // 10^-84 - {0xb94470938fa89bcf, -316, false}, // 10^-76 - {0x8a08f0f8bf0f156b, -289, false}, // 10^-68 - {0xcdb02555653131b6, -263, false}, // 10^-60 - {0x993fe2c6d07b7fac, -236, false}, // 10^-52 - {0xe45c10c42a2b3b06, -210, false}, // 10^-44 - {0xaa242499697392d3, -183, false}, // 10^-36 - {0xfd87b5f28300ca0e, -157, false}, // 10^-28 - {0xbce5086492111aeb, -130, false}, // 10^-20 - {0x8cbccc096f5088cc, -103, false}, // 10^-12 - {0xd1b71758e219652c, -77, false}, // 10^-4 - {0x9c40000000000000, -50, false}, // 10^4 - {0xe8d4a51000000000, -24, false}, // 10^12 - {0xad78ebc5ac620000, 3, false}, // 10^20 - {0x813f3978f8940984, 30, false}, // 10^28 - {0xc097ce7bc90715b3, 56, false}, // 10^36 - {0x8f7e32ce7bea5c70, 83, false}, // 10^44 - {0xd5d238a4abe98068, 109, false}, // 10^52 - {0x9f4f2726179a2245, 136, false}, // 10^60 - {0xed63a231d4c4fb27, 162, false}, // 10^68 - {0xb0de65388cc8ada8, 189, false}, // 10^76 - {0x83c7088e1aab65db, 216, false}, // 10^84 - {0xc45d1df942711d9a, 242, false}, // 10^92 - {0x924d692ca61be758, 269, false}, // 10^100 - {0xda01ee641a708dea, 295, false}, // 10^108 - {0xa26da3999aef774a, 322, false}, // 10^116 - {0xf209787bb47d6b85, 348, false}, // 10^124 - {0xb454e4a179dd1877, 375, false}, // 10^132 - {0x865b86925b9bc5c2, 402, false}, // 10^140 - {0xc83553c5c8965d3d, 428, false}, // 10^148 - {0x952ab45cfa97a0b3, 455, false}, // 10^156 - {0xde469fbd99a05fe3, 481, false}, // 10^164 - {0xa59bc234db398c25, 508, false}, // 10^172 - {0xf6c69a72a3989f5c, 534, false}, // 10^180 - {0xb7dcbf5354e9bece, 561, false}, // 10^188 - {0x88fcf317f22241e2, 588, false}, // 10^196 - {0xcc20ce9bd35c78a5, 614, false}, // 10^204 - {0x98165af37b2153df, 641, false}, // 10^212 - {0xe2a0b5dc971f303a, 667, false}, // 10^220 - {0xa8d9d1535ce3b396, 694, false}, // 10^228 - {0xfb9b7cd9a4a7443c, 720, false}, // 10^236 - {0xbb764c4ca7a44410, 747, false}, // 10^244 - {0x8bab8eefb6409c1a, 774, false}, // 10^252 - {0xd01fef10a657842c, 800, false}, // 10^260 - {0x9b10a4e5e9913129, 827, false}, // 10^268 - {0xe7109bfba19c0c9d, 853, false}, // 10^276 - {0xac2820d9623bf429, 880, false}, // 10^284 - {0x80444b5e7aa7cf85, 907, false}, // 10^292 - {0xbf21e44003acdd2d, 933, false}, // 10^300 - {0x8e679c2f5e44ff8f, 960, false}, // 10^308 - {0xd433179d9c8cb841, 986, false}, // 10^316 - {0x9e19db92b4e31ba9, 1013, false}, // 10^324 - {0xeb96bf6ebadf77d9, 1039, false}, // 10^332 - {0xaf87023b9bf0ee6b, 1066, false}, // 10^340 -} - -// AssignComputeBounds sets f to the floating point value -// defined by mant, exp and precision given by flt. It returns -// lower, upper such that any number in the closed interval -// [lower, upper] is converted back to the same floating point number. -func (f *extFloat) AssignComputeBounds(mant uint64, exp int, neg bool, flt *floatInfo) (lower, upper extFloat) { - f.mant = mant - f.exp = exp - int(flt.mantbits) - f.neg = neg - if f.exp <= 0 && mant == (mant>>uint(-f.exp))<<uint(-f.exp) { - // An exact integer - f.mant >>= uint(-f.exp) - f.exp = 0 - return *f, *f - } - expBiased := exp - flt.bias - - upper = extFloat{mant: 2*f.mant + 1, exp: f.exp - 1, neg: f.neg} - if mant != 1<<flt.mantbits || expBiased == 1 { - lower = extFloat{mant: 2*f.mant - 1, exp: f.exp - 1, neg: f.neg} - } else { - lower = extFloat{mant: 4*f.mant - 1, exp: f.exp - 2, neg: f.neg} - } - return -} - -// Normalize normalizes f so that the highest bit of the mantissa is -// set, and returns the number by which the mantissa was left-shifted. -func (f *extFloat) Normalize() uint { - // bits.LeadingZeros64 would return 64 - if f.mant == 0 { - return 0 - } - shift := bits.LeadingZeros64(f.mant) - f.mant <<= uint(shift) - f.exp -= shift - return uint(shift) -} - -// Multiply sets f to the product f*g: the result is correctly rounded, -// but not normalized. -func (f *extFloat) Multiply(g extFloat) { - hi, lo := bits.Mul64(f.mant, g.mant) - // Round up. - f.mant = hi + (lo >> 63) - f.exp = f.exp + g.exp + 64 -} - -var uint64pow10 = [...]uint64{ - 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, - 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, -} - -// Frexp10 is an analogue of math.Frexp for decimal powers. It scales -// f by an approximate power of ten 10^-exp, and returns exp10, so -// that f*10^exp10 has the same value as the old f, up to an ulp, -// as well as the index of 10^-exp in the powersOfTen table. -func (f *extFloat) frexp10() (exp10, index int) { - // The constants expMin and expMax constrain the final value of the - // binary exponent of f. We want a small integral part in the result - // because finding digits of an integer requires divisions, whereas - // digits of the fractional part can be found by repeatedly multiplying - // by 10. - const expMin = -60 - const expMax = -32 - // Find power of ten such that x * 10^n has a binary exponent - // between expMin and expMax. - approxExp10 := ((expMin+expMax)/2 - f.exp) * 28 / 93 // log(10)/log(2) is close to 93/28. - i := (approxExp10 - firstPowerOfTen) / stepPowerOfTen -Loop: - for { - exp := f.exp + powersOfTen[i].exp + 64 - switch { - case exp < expMin: - i++ - case exp > expMax: - i-- - default: - break Loop - } - } - // Apply the desired decimal shift on f. It will have exponent - // in the desired range. This is multiplication by 10^-exp10. - f.Multiply(powersOfTen[i]) - - return -(firstPowerOfTen + i*stepPowerOfTen), i -} - -// frexp10Many applies a common shift by a power of ten to a, b, c. -func frexp10Many(a, b, c *extFloat) (exp10 int) { - exp10, i := c.frexp10() - a.Multiply(powersOfTen[i]) - b.Multiply(powersOfTen[i]) - return -} - -// FixedDecimal stores in d the first n significant digits -// of the decimal representation of f. It returns false -// if it cannot be sure of the answer. -func (f *extFloat) FixedDecimal(d *decimalSlice, n int) bool { - if f.mant == 0 { - d.nd = 0 - d.dp = 0 - d.neg = f.neg - return true - } - if n == 0 { - panic("strconv: internal error: extFloat.FixedDecimal called with n == 0") - } - // Multiply by an appropriate power of ten to have a reasonable - // number to process. - f.Normalize() - exp10, _ := f.frexp10() - - shift := uint(-f.exp) - integer := uint32(f.mant >> shift) - fraction := f.mant - (uint64(integer) << shift) - ε := uint64(1) // ε is the uncertainty we have on the mantissa of f. - - // Write exactly n digits to d. - needed := n // how many digits are left to write. - integerDigits := 0 // the number of decimal digits of integer. - pow10 := uint64(1) // the power of ten by which f was scaled. - for i, pow := 0, uint64(1); i < 20; i++ { - if pow > uint64(integer) { - integerDigits = i - break - } - pow *= 10 - } - rest := integer - if integerDigits > needed { - // the integral part is already large, trim the last digits. - pow10 = uint64pow10[integerDigits-needed] - integer /= uint32(pow10) - rest -= integer * uint32(pow10) - } else { - rest = 0 - } - - // Write the digits of integer: the digits of rest are omitted. - var buf [32]byte - pos := len(buf) - for v := integer; v > 0; { - v1 := v / 10 - v -= 10 * v1 - pos-- - buf[pos] = byte(v + '0') - v = v1 - } - for i := pos; i < len(buf); i++ { - d.d[i-pos] = buf[i] - } - nd := len(buf) - pos - d.nd = nd - d.dp = integerDigits + exp10 - needed -= nd - - if needed > 0 { - if rest != 0 || pow10 != 1 { - panic("strconv: internal error, rest != 0 but needed > 0") - } - // Emit digits for the fractional part. Each time, 10*fraction - // fits in a uint64 without overflow. - for needed > 0 { - fraction *= 10 - ε *= 10 // the uncertainty scales as we multiply by ten. - if 2*ε > 1<<shift { - // the error is so large it could modify which digit to write, abort. - return false - } - digit := fraction >> shift - d.d[nd] = byte(digit + '0') - fraction -= digit << shift - nd++ - needed-- - } - d.nd = nd - } - - // We have written a truncation of f (a numerator / 10^d.dp). The remaining part - // can be interpreted as a small number (< 1) to be added to the last digit of the - // numerator. - // - // If rest > 0, the amount is: - // (rest<<shift | fraction) / (pow10 << shift) - // fraction being known with a ±ε uncertainty. - // The fact that n > 0 guarantees that pow10 << shift does not overflow a uint64. - // - // If rest = 0, pow10 == 1 and the amount is - // fraction / (1 << shift) - // fraction being known with a ±ε uncertainty. - // - // We pass this information to the rounding routine for adjustment. - - ok := adjustLastDigitFixed(d, uint64(rest)<<shift|fraction, pow10, shift, ε) - if !ok { - return false - } - // Trim trailing zeros. - for i := d.nd - 1; i >= 0; i-- { - if d.d[i] != '0' { - d.nd = i + 1 - break - } - } - return true -} - -// adjustLastDigitFixed assumes d contains the representation of the integral part -// of some number, whose fractional part is num / (den << shift). The numerator -// num is only known up to an uncertainty of size ε, assumed to be less than -// (den << shift)/2. -// -// It will increase the last digit by one to account for correct rounding, typically -// when the fractional part is greater than 1/2, and will return false if ε is such -// that no correct answer can be given. -func adjustLastDigitFixed(d *decimalSlice, num, den uint64, shift uint, ε uint64) bool { - if num > den<<shift { - panic("strconv: num > den<<shift in adjustLastDigitFixed") - } - if 2*ε > den<<shift { - panic("strconv: ε > (den<<shift)/2") - } - if 2*(num+ε) < den<<shift { - return true - } - if 2*(num-ε) > den<<shift { - // increment d by 1. - i := d.nd - 1 - for ; i >= 0; i-- { - if d.d[i] == '9' { - d.nd-- - } else { - break - } - } - if i < 0 { - d.d[0] = '1' - d.nd = 1 - d.dp++ - } else { - d.d[i]++ - } - return true - } - return false -} - -// ShortestDecimal stores in d the shortest decimal representation of f -// which belongs to the open interval (lower, upper), where f is supposed -// to lie. It returns false whenever the result is unsure. The implementation -// uses the Grisu3 algorithm. -func (f *extFloat) ShortestDecimal(d *decimalSlice, lower, upper *extFloat) bool { - if f.mant == 0 { - d.nd = 0 - d.dp = 0 - d.neg = f.neg - return true - } - if f.exp == 0 && *lower == *f && *lower == *upper { - // an exact integer. - var buf [24]byte - n := len(buf) - 1 - for v := f.mant; v > 0; { - v1 := v / 10 - v -= 10 * v1 - buf[n] = byte(v + '0') - n-- - v = v1 - } - nd := len(buf) - n - 1 - for i := 0; i < nd; i++ { - d.d[i] = buf[n+1+i] - } - d.nd, d.dp = nd, nd - for d.nd > 0 && d.d[d.nd-1] == '0' { - d.nd-- - } - if d.nd == 0 { - d.dp = 0 - } - d.neg = f.neg - return true - } - upper.Normalize() - // Uniformize exponents. - if f.exp > upper.exp { - f.mant <<= uint(f.exp - upper.exp) - f.exp = upper.exp - } - if lower.exp > upper.exp { - lower.mant <<= uint(lower.exp - upper.exp) - lower.exp = upper.exp - } - - exp10 := frexp10Many(lower, f, upper) - // Take a safety margin due to rounding in frexp10Many, but we lose precision. - upper.mant++ - lower.mant-- - - // The shortest representation of f is either rounded up or down, but - // in any case, it is a truncation of upper. - shift := uint(-upper.exp) - integer := uint32(upper.mant >> shift) - fraction := upper.mant - (uint64(integer) << shift) - - // How far we can go down from upper until the result is wrong. - allowance := upper.mant - lower.mant - // How far we should go to get a very precise result. - targetDiff := upper.mant - f.mant - - // Count integral digits: there are at most 10. - var integerDigits int - for i, pow := 0, uint64(1); i < 20; i++ { - if pow > uint64(integer) { - integerDigits = i - break - } - pow *= 10 - } - for i := 0; i < integerDigits; i++ { - pow := uint64pow10[integerDigits-i-1] - digit := integer / uint32(pow) - d.d[i] = byte(digit + '0') - integer -= digit * uint32(pow) - // evaluate whether we should stop. - if currentDiff := uint64(integer)<<shift + fraction; currentDiff < allowance { - d.nd = i + 1 - d.dp = integerDigits + exp10 - d.neg = f.neg - // Sometimes allowance is so large the last digit might need to be - // decremented to get closer to f. - return adjustLastDigit(d, currentDiff, targetDiff, allowance, pow<<shift, 2) - } - } - d.nd = integerDigits - d.dp = d.nd + exp10 - d.neg = f.neg - - // Compute digits of the fractional part. At each step fraction does not - // overflow. The choice of minExp implies that fraction is less than 2^60. - var digit int - multiplier := uint64(1) - for { - fraction *= 10 - multiplier *= 10 - digit = int(fraction >> shift) - d.d[d.nd] = byte(digit + '0') - d.nd++ - fraction -= uint64(digit) << shift - if fraction < allowance*multiplier { - // We are in the admissible range. Note that if allowance is about to - // overflow, that is, allowance > 2^64/10, the condition is automatically - // true due to the limited range of fraction. - return adjustLastDigit(d, - fraction, targetDiff*multiplier, allowance*multiplier, - 1<<shift, multiplier*2) - } - } -} - -// adjustLastDigit modifies d = x-currentDiff*ε, to get closest to -// d = x-targetDiff*ε, without becoming smaller than x-maxDiff*ε. -// It assumes that a decimal digit is worth ulpDecimal*ε, and that -// all data is known with an error estimate of ulpBinary*ε. -func adjustLastDigit(d *decimalSlice, currentDiff, targetDiff, maxDiff, ulpDecimal, ulpBinary uint64) bool { - if ulpDecimal < 2*ulpBinary { - // Approximation is too wide. - return false - } - for currentDiff+ulpDecimal/2+ulpBinary < targetDiff { - d.d[d.nd-1]-- - currentDiff += ulpDecimal - } - if currentDiff+ulpDecimal <= targetDiff+ulpDecimal/2+ulpBinary { - // we have two choices, and don't know what to do. - return false - } - if currentDiff < ulpBinary || currentDiff > maxDiff-ulpBinary { - // we went too far - return false - } - if d.nd == 1 && d.d[0] == '0' { - // the number has actually reached zero. - d.nd = 0 - d.dp = 0 - } - return true -} diff --git a/libgo/go/strconv/ftoa.go b/libgo/go/strconv/ftoa.go index 8ce6ef3..eca04b8 100644 --- a/libgo/go/strconv/ftoa.go +++ b/libgo/go/strconv/ftoa.go @@ -113,15 +113,11 @@ func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte { // Negative precision means "only as much as needed to be exact." shortest := prec < 0 if shortest { - // Try Grisu3 algorithm. - f := new(extFloat) - lower, upper := f.AssignComputeBounds(mant, exp, neg, flt) + // Use Ryu algorithm. var buf [32]byte digs.d = buf[:] - ok = f.ShortestDecimal(&digs, &lower, &upper) - if !ok { - return bigFtoa(dst, prec, fmt, neg, mant, exp, flt) - } + ryuFtoaShortest(&digs, mant, exp-int(flt.mantbits), flt) + ok = true // Precision for shortest representation mode. switch fmt { case 'e', 'E': @@ -143,12 +139,15 @@ func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte { } digits = prec } - if digits <= 15 { - // try fast algorithm when the number of digits is reasonable. - var buf [24]byte + var buf [24]byte + if bitSize == 32 && digits <= 9 { + digs.d = buf[:] + ryuFtoaFixed32(&digs, uint32(mant), exp-int(flt.mantbits), digits) + ok = true + } else if digits <= 18 { digs.d = buf[:] - f := extFloat{mant, exp - int(flt.mantbits), neg} - ok = f.FixedDecimal(&digs, digits) + ryuFtoaFixed64(&digs, mant, exp-int(flt.mantbits), digits) + ok = true } } if !ok { diff --git a/libgo/go/strconv/ftoa_test.go b/libgo/go/strconv/ftoa_test.go index 99cca17..73008b1 100644 --- a/libgo/go/strconv/ftoa_test.go +++ b/libgo/go/strconv/ftoa_test.go @@ -40,6 +40,7 @@ var ftoatests = []ftoaTest{ {200000, 'x', -1, "0x1.86ap+17"}, {200000, 'X', -1, "0X1.86AP+17"}, {2000000, 'g', -1, "2e+06"}, + {1e10, 'g', -1, "1e+10"}, // g conversion and zero suppression {400, 'g', 2, "4e+02"}, @@ -77,6 +78,15 @@ var ftoatests = []ftoaTest{ {1.2345e6, 'f', 5, "1234500.00000"}, {1.2345e6, 'g', 5, "1.2345e+06"}, + // Round to even + {1.2345e6, 'e', 3, "1.234e+06"}, + {1.2355e6, 'e', 3, "1.236e+06"}, + {1.2345, 'f', 3, "1.234"}, + {1.2355, 'f', 3, "1.236"}, + {1234567890123456.5, 'e', 15, "1.234567890123456e+15"}, + {1234567890123457.5, 'e', 15, "1.234567890123458e+15"}, + {108678236358137.625, 'g', -1, "1.0867823635813762e+14"}, + {1e23, 'e', 17, "9.99999999999999916e+22"}, {1e23, 'f', 17, "99999999999999991611392.00000000000000000"}, {1e23, 'g', 17, "9.9999999999999992e+22"}, @@ -183,6 +193,25 @@ func TestFtoa(t *testing.T) { } } +func TestFtoaPowersOfTwo(t *testing.T) { + for exp := -2048; exp <= 2048; exp++ { + f := math.Ldexp(1, exp) + if !math.IsInf(f, 0) { + s := FormatFloat(f, 'e', -1, 64) + if x, _ := ParseFloat(s, 64); x != f { + t.Errorf("failed roundtrip %v => %s => %v", f, s, x) + } + } + f32 := float32(f) + if !math.IsInf(float64(f32), 0) { + s := FormatFloat(float64(f32), 'e', -1, 32) + if x, _ := ParseFloat(s, 32); float32(x) != f32 { + t.Errorf("failed roundtrip %v => %s => %v", f32, s, float32(x)) + } + } + } +} + func TestFtoaRandom(t *testing.T) { N := int(1e4) if testing.Short() { @@ -232,6 +261,7 @@ var ftoaBenches = []struct { {"Float", 339.7784, 'g', -1, 64}, {"Exp", -5.09e75, 'g', -1, 64}, {"NegExp", -5.11e-95, 'g', -1, 64}, + {"LongExp", 1.234567890123456e-78, 'g', -1, 64}, {"Big", 123456789123456789123456789, 'g', -1, 64}, {"BinaryExp", -1, 'b', -1, 64}, @@ -241,14 +271,30 @@ var ftoaBenches = []struct { {"32Point", 339.7784, 'g', -1, 32}, {"32Exp", -5.09e25, 'g', -1, 32}, {"32NegExp", -5.11e-25, 'g', -1, 32}, + {"32Shortest", 1.234567e-8, 'g', -1, 32}, + {"32Fixed8Hard", math.Ldexp(15961084, -125), 'e', 8, 32}, + {"32Fixed9Hard", math.Ldexp(14855922, -83), 'e', 9, 32}, {"64Fixed1", 123456, 'e', 3, 64}, {"64Fixed2", 123.456, 'e', 3, 64}, {"64Fixed3", 1.23456e+78, 'e', 3, 64}, {"64Fixed4", 1.23456e-78, 'e', 3, 64}, + {"64Fixed12", 1.23456e-78, 'e', 12, 64}, + {"64Fixed16", 1.23456e-78, 'e', 16, 64}, + // From testdata/testfp.txt + {"64Fixed12Hard", math.Ldexp(6965949469487146, -249), 'e', 12, 64}, + {"64Fixed17Hard", math.Ldexp(8887055249355788, 665), 'e', 17, 64}, + {"64Fixed18Hard", math.Ldexp(6994187472632449, 690), 'e', 18, 64}, // Trigger slow path (see issue #15672). - {"Slowpath64", 622666234635.3213e-320, 'e', -1, 64}, + // The shortest is: 8.034137530808823e+43 + {"Slowpath64", 8.03413753080882349e+43, 'e', -1, 64}, + // This denormal is pathological because the lower/upper + // halfways to neighboring floats are: + // 622666234635.321003e-320 ~= 622666234635.321e-320 + // 622666234635.321497e-320 ~= 622666234635.3215e-320 + // making it hard to find the 3rd digit + {"SlowpathDenormal64", 622666234635.3213e-320, 'e', -1, 64}, } func BenchmarkFormatFloat(b *testing.B) { diff --git a/libgo/go/strconv/ftoaryu.go b/libgo/go/strconv/ftoaryu.go new file mode 100644 index 0000000..1c61288 --- /dev/null +++ b/libgo/go/strconv/ftoaryu.go @@ -0,0 +1,567 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import ( + "math/bits" +) + +// binary to decimal conversion using the Ryū algorithm. +// +// See Ulf Adams, "Ryū: Fast Float-to-String Conversion" (doi:10.1145/3192366.3192369) +// +// Fixed precision formatting is a variant of the original paper's +// algorithm, where a single multiplication by 10^k is required, +// sharing the same rounding guarantees. + +// ryuFtoaFixed32 formats mant*(2^exp) with prec decimal digits. +func ryuFtoaFixed32(d *decimalSlice, mant uint32, exp int, prec int) { + if prec < 0 { + panic("ryuFtoaFixed32 called with negative prec") + } + if prec > 9 { + panic("ryuFtoaFixed32 called with prec > 9") + } + // Zero input. + if mant == 0 { + d.nd, d.dp = 0, 0 + return + } + // Renormalize to a 25-bit mantissa. + e2 := exp + if b := bits.Len32(mant); b < 25 { + mant <<= uint(25 - b) + e2 += int(b) - 25 + } + // Choose an exponent such that rounded mant*(2^e2)*(10^q) has + // at least prec decimal digits, i.e + // mant*(2^e2)*(10^q) >= 10^(prec-1) + // Because mant >= 2^24, it is enough to choose: + // 2^(e2+24) >= 10^(-q+prec-1) + // or q = -mulByLog2Log10(e2+24) + prec - 1 + q := -mulByLog2Log10(e2+24) + prec - 1 + + // Now compute mant*(2^e2)*(10^q). + // Is it an exact computation? + // Only small positive powers of 10 are exact (5^28 has 66 bits). + exact := q <= 27 && q >= 0 + + di, dexp2, d0 := mult64bitPow10(mant, e2, q) + if dexp2 >= 0 { + panic("not enough significant bits after mult64bitPow10") + } + // As a special case, computation might still be exact, if exponent + // was negative and if it amounts to computing an exact division. + // In that case, we ignore all lower bits. + // Note that division by 10^11 cannot be exact as 5^11 has 26 bits. + if q < 0 && q >= -10 && divisibleByPower5(uint64(mant), -q) { + exact = true + d0 = true + } + // Remove extra lower bits and keep rounding info. + extra := uint(-dexp2) + extraMask := uint32(1<<extra - 1) + + di, dfrac := di>>extra, di&extraMask + roundUp := false + if exact { + // If we computed an exact product, d + 1/2 + // should round to d+1 if 'd' is odd. + roundUp = dfrac > 1<<(extra-1) || + (dfrac == 1<<(extra-1) && !d0) || + (dfrac == 1<<(extra-1) && d0 && di&1 == 1) + } else { + // otherwise, d+1/2 always rounds up because + // we truncated below. + roundUp = dfrac>>(extra-1) == 1 + } + if dfrac != 0 { + d0 = false + } + // Proceed to the requested number of digits + formatDecimal(d, uint64(di), !d0, roundUp, prec) + // Adjust exponent + d.dp -= q +} + +// ryuFtoaFixed64 formats mant*(2^exp) with prec decimal digits. +func ryuFtoaFixed64(d *decimalSlice, mant uint64, exp int, prec int) { + if prec > 18 { + panic("ryuFtoaFixed64 called with prec > 18") + } + // Zero input. + if mant == 0 { + d.nd, d.dp = 0, 0 + return + } + // Renormalize to a 55-bit mantissa. + e2 := exp + if b := bits.Len64(mant); b < 55 { + mant = mant << uint(55-b) + e2 += int(b) - 55 + } + // Choose an exponent such that rounded mant*(2^e2)*(10^q) has + // at least prec decimal digits, i.e + // mant*(2^e2)*(10^q) >= 10^(prec-1) + // Because mant >= 2^54, it is enough to choose: + // 2^(e2+54) >= 10^(-q+prec-1) + // or q = -mulByLog2Log10(e2+54) + prec - 1 + // + // The minimal required exponent is -mulByLog2Log10(1025)+18 = -291 + // The maximal required exponent is mulByLog2Log10(1074)+18 = 342 + q := -mulByLog2Log10(e2+54) + prec - 1 + + // Now compute mant*(2^e2)*(10^q). + // Is it an exact computation? + // Only small positive powers of 10 are exact (5^55 has 128 bits). + exact := q <= 55 && q >= 0 + + di, dexp2, d0 := mult128bitPow10(mant, e2, q) + if dexp2 >= 0 { + panic("not enough significant bits after mult128bitPow10") + } + // As a special case, computation might still be exact, if exponent + // was negative and if it amounts to computing an exact division. + // In that case, we ignore all lower bits. + // Note that division by 10^23 cannot be exact as 5^23 has 54 bits. + if q < 0 && q >= -22 && divisibleByPower5(mant, -q) { + exact = true + d0 = true + } + // Remove extra lower bits and keep rounding info. + extra := uint(-dexp2) + extraMask := uint64(1<<extra - 1) + + di, dfrac := di>>extra, di&extraMask + roundUp := false + if exact { + // If we computed an exact product, d + 1/2 + // should round to d+1 if 'd' is odd. + roundUp = dfrac > 1<<(extra-1) || + (dfrac == 1<<(extra-1) && !d0) || + (dfrac == 1<<(extra-1) && d0 && di&1 == 1) + } else { + // otherwise, d+1/2 always rounds up because + // we truncated below. + roundUp = dfrac>>(extra-1) == 1 + } + if dfrac != 0 { + d0 = false + } + // Proceed to the requested number of digits + formatDecimal(d, di, !d0, roundUp, prec) + // Adjust exponent + d.dp -= q +} + +var uint64pow10 = [...]uint64{ + 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, +} + +// formatDecimal fills d with at most prec decimal digits +// of mantissa m. The boolean trunc indicates whether m +// is truncated compared to the original number being formatted. +func formatDecimal(d *decimalSlice, m uint64, trunc bool, roundUp bool, prec int) { + max := uint64pow10[prec] + trimmed := 0 + for m >= max { + a, b := m/10, m%10 + m = a + trimmed++ + if b > 5 { + roundUp = true + } else if b < 5 { + roundUp = false + } else { // b == 5 + // round up if there are trailing digits, + // or if the new value of m is odd (round-to-even convention) + roundUp = trunc || m&1 == 1 + } + if b != 0 { + trunc = true + } + } + if roundUp { + m++ + } + if m >= max { + // Happens if di was originally 99999....xx + m /= 10 + trimmed++ + } + // render digits (similar to formatBits) + n := uint(prec) + d.nd = int(prec) + v := m + for v >= 100 { + var v1, v2 uint64 + if v>>32 == 0 { + v1, v2 = uint64(uint32(v)/100), uint64(uint32(v)%100) + } else { + v1, v2 = v/100, v%100 + } + n -= 2 + d.d[n+1] = smallsString[2*v2+1] + d.d[n+0] = smallsString[2*v2+0] + v = v1 + } + if v > 0 { + n-- + d.d[n] = smallsString[2*v+1] + } + if v >= 10 { + n-- + d.d[n] = smallsString[2*v] + } + for d.d[d.nd-1] == '0' { + d.nd-- + trimmed++ + } + d.dp = d.nd + trimmed +} + +// ryuFtoaShortest formats mant*2^exp with prec decimal digits. +func ryuFtoaShortest(d *decimalSlice, mant uint64, exp int, flt *floatInfo) { + if mant == 0 { + d.nd, d.dp = 0, 0 + return + } + // If input is an exact integer with fewer bits than the mantissa, + // the previous and next integer are not admissible representations. + if exp <= 0 && bits.TrailingZeros64(mant) >= -exp { + mant >>= uint(-exp) + ryuDigits(d, mant, mant, mant, true, false) + return + } + ml, mc, mu, e2 := computeBounds(mant, exp, flt) + if e2 == 0 { + ryuDigits(d, ml, mc, mu, true, false) + return + } + // Find 10^q *larger* than 2^-e2 + q := mulByLog2Log10(-e2) + 1 + + // We are going to multiply by 10^q using 128-bit arithmetic. + // The exponent is the same for all 3 numbers. + var dl, dc, du uint64 + var dl0, dc0, du0 bool + if flt == &float32info { + var dl32, dc32, du32 uint32 + dl32, _, dl0 = mult64bitPow10(uint32(ml), e2, q) + dc32, _, dc0 = mult64bitPow10(uint32(mc), e2, q) + du32, e2, du0 = mult64bitPow10(uint32(mu), e2, q) + dl, dc, du = uint64(dl32), uint64(dc32), uint64(du32) + } else { + dl, _, dl0 = mult128bitPow10(ml, e2, q) + dc, _, dc0 = mult128bitPow10(mc, e2, q) + du, e2, du0 = mult128bitPow10(mu, e2, q) + } + if e2 >= 0 { + panic("not enough significant bits after mult128bitPow10") + } + // Is it an exact computation? + if q > 55 { + // Large positive powers of ten are not exact + dl0, dc0, du0 = false, false, false + } + if q < 0 && q >= -24 { + // Division by a power of ten may be exact. + // (note that 5^25 is a 59-bit number so division by 5^25 is never exact). + if divisibleByPower5(ml, -q) { + dl0 = true + } + if divisibleByPower5(mc, -q) { + dc0 = true + } + if divisibleByPower5(mu, -q) { + du0 = true + } + } + // Express the results (dl, dc, du)*2^e2 as integers. + // Extra bits must be removed and rounding hints computed. + extra := uint(-e2) + extraMask := uint64(1<<extra - 1) + // Now compute the floored, integral base 10 mantissas. + dl, fracl := dl>>extra, dl&extraMask + dc, fracc := dc>>extra, dc&extraMask + du, fracu := du>>extra, du&extraMask + // Is it allowed to use 'du' as a result? + // It is always allowed when it is truncated, but also + // if it is exact and the original binary mantissa is even + // When disallowed, we can substract 1. + uok := !du0 || fracu > 0 + if du0 && fracu == 0 { + uok = mant&1 == 0 + } + if !uok { + du-- + } + // Is 'dc' the correctly rounded base 10 mantissa? + // The correct rounding might be dc+1 + cup := false // don't round up. + if dc0 { + // If we computed an exact product, the half integer + // should round to next (even) integer if 'dc' is odd. + cup = fracc > 1<<(extra-1) || + (fracc == 1<<(extra-1) && dc&1 == 1) + } else { + // otherwise, the result is a lower truncation of the ideal + // result. + cup = fracc>>(extra-1) == 1 + } + // Is 'dl' an allowed representation? + // Only if it is an exact value, and if the original binary mantissa + // was even. + lok := dl0 && fracl == 0 && (mant&1 == 0) + if !lok { + dl++ + } + // We need to remember whether the trimmed digits of 'dc' are zero. + c0 := dc0 && fracc == 0 + // render digits + ryuDigits(d, dl, dc, du, c0, cup) + d.dp -= q +} + +// mulByLog2Log10 returns math.Floor(x * log(2)/log(10)) for an integer x in +// the range -1600 <= x && x <= +1600. +// +// The range restriction lets us work in faster integer arithmetic instead of +// slower floating point arithmetic. Correctness is verified by unit tests. +func mulByLog2Log10(x int) int { + // log(2)/log(10) ≈ 0.30102999566 ≈ 78913 / 2^18 + return (x * 78913) >> 18 +} + +// mulByLog10Log2 returns math.Floor(x * log(10)/log(2)) for an integer x in +// the range -500 <= x && x <= +500. +// +// The range restriction lets us work in faster integer arithmetic instead of +// slower floating point arithmetic. Correctness is verified by unit tests. +func mulByLog10Log2(x int) int { + // log(10)/log(2) ≈ 3.32192809489 ≈ 108853 / 2^15 + return (x * 108853) >> 15 +} + +// computeBounds returns a floating-point vector (l, c, u)×2^e2 +// where the mantissas are 55-bit (or 26-bit) integers, describing the interval +// represented by the input float64 or float32. +func computeBounds(mant uint64, exp int, flt *floatInfo) (lower, central, upper uint64, e2 int) { + if mant != 1<<flt.mantbits || exp == flt.bias+1-int(flt.mantbits) { + // regular case (or denormals) + lower, central, upper = 2*mant-1, 2*mant, 2*mant+1 + e2 = exp - 1 + return + } else { + // border of an exponent + lower, central, upper = 4*mant-1, 4*mant, 4*mant+2 + e2 = exp - 2 + return + } +} + +func ryuDigits(d *decimalSlice, lower, central, upper uint64, + c0, cup bool) { + lhi, llo := divmod1e9(lower) + chi, clo := divmod1e9(central) + uhi, ulo := divmod1e9(upper) + if uhi == 0 { + // only low digits (for denormals) + ryuDigits32(d, llo, clo, ulo, c0, cup, 8) + } else if lhi < uhi { + // truncate 9 digits at once. + if llo != 0 { + lhi++ + } + c0 = c0 && clo == 0 + cup = (clo > 5e8) || (clo == 5e8 && cup) + ryuDigits32(d, lhi, chi, uhi, c0, cup, 8) + d.dp += 9 + } else { + d.nd = 0 + // emit high part + n := uint(9) + for v := chi; v > 0; { + v1, v2 := v/10, v%10 + v = v1 + n-- + d.d[n] = byte(v2 + '0') + } + d.d = d.d[n:] + d.nd = int(9 - n) + // emit low part + ryuDigits32(d, llo, clo, ulo, + c0, cup, d.nd+8) + } + // trim trailing zeros + for d.nd > 0 && d.d[d.nd-1] == '0' { + d.nd-- + } + // trim initial zeros + for d.nd > 0 && d.d[0] == '0' { + d.nd-- + d.dp-- + d.d = d.d[1:] + } +} + +// ryuDigits32 emits decimal digits for a number less than 1e9. +func ryuDigits32(d *decimalSlice, lower, central, upper uint32, + c0, cup bool, endindex int) { + if upper == 0 { + d.dp = endindex + 1 + return + } + trimmed := 0 + // Remember last trimmed digit to check for round-up. + // c0 will be used to remember zeroness of following digits. + cNextDigit := 0 + for upper > 0 { + // Repeatedly compute: + // l = Ceil(lower / 10^k) + // c = Round(central / 10^k) + // u = Floor(upper / 10^k) + // and stop when c goes out of the (l, u) interval. + l := (lower + 9) / 10 + c, cdigit := central/10, central%10 + u := upper / 10 + if l > u { + // don't trim the last digit as it is forbidden to go below l + // other, trim and exit now. + break + } + // Check that we didn't cross the lower boundary. + // The case where l < u but c == l-1 is essentially impossible, + // but may happen if: + // lower = ..11 + // central = ..19 + // upper = ..31 + // and means that 'central' is very close but less than + // an integer ending with many zeros, and usually + // the "round-up" logic hides the problem. + if l == c+1 && c < u { + c++ + cdigit = 0 + cup = false + } + trimmed++ + // Remember trimmed digits of c + c0 = c0 && cNextDigit == 0 + cNextDigit = int(cdigit) + lower, central, upper = l, c, u + } + // should we round up? + if trimmed > 0 { + cup = cNextDigit > 5 || + (cNextDigit == 5 && !c0) || + (cNextDigit == 5 && c0 && central&1 == 1) + } + if central < upper && cup { + central++ + } + // We know where the number ends, fill directly + endindex -= trimmed + v := central + n := endindex + for n > d.nd { + v1, v2 := v/100, v%100 + d.d[n] = smallsString[2*v2+1] + d.d[n-1] = smallsString[2*v2+0] + n -= 2 + v = v1 + } + if n == d.nd { + d.d[n] = byte(v + '0') + } + d.nd = endindex + 1 + d.dp = d.nd + trimmed +} + +// mult64bitPow10 takes a floating-point input with a 25-bit +// mantissa and multiplies it with 10^q. The resulting mantissa +// is m*P >> 57 where P is a 64-bit element of the detailedPowersOfTen tables. +// It is typically 31 or 32-bit wide. +// The returned boolean is true if all trimmed bits were zero. +// +// That is: +// m*2^e2 * round(10^q) = resM * 2^resE + ε +// exact = ε == 0 +func mult64bitPow10(m uint32, e2, q int) (resM uint32, resE int, exact bool) { + if q == 0 { + // P == 1<<63 + return m << 6, e2 - 6, true + } + if q < detailedPowersOfTenMinExp10 || detailedPowersOfTenMaxExp10 < q { + // This never happens due to the range of float32/float64 exponent + panic("mult64bitPow10: power of 10 is out of range") + } + pow := detailedPowersOfTen[q-detailedPowersOfTenMinExp10][1] + if q < 0 { + // Inverse powers of ten must be rounded up. + pow += 1 + } + hi, lo := bits.Mul64(uint64(m), pow) + e2 += mulByLog10Log2(q) - 63 + 57 + return uint32(hi<<7 | lo>>57), e2, lo<<7 == 0 +} + +// mult128bitPow10 takes a floating-point input with a 55-bit +// mantissa and multiplies it with 10^q. The resulting mantissa +// is m*P >> 119 where P is a 128-bit element of the detailedPowersOfTen tables. +// It is typically 63 or 64-bit wide. +// The returned boolean is true is all trimmed bits were zero. +// +// That is: +// m*2^e2 * round(10^q) = resM * 2^resE + ε +// exact = ε == 0 +func mult128bitPow10(m uint64, e2, q int) (resM uint64, resE int, exact bool) { + if q == 0 { + // P == 1<<127 + return m << 8, e2 - 8, true + } + if q < detailedPowersOfTenMinExp10 || detailedPowersOfTenMaxExp10 < q { + // This never happens due to the range of float32/float64 exponent + panic("mult128bitPow10: power of 10 is out of range") + } + pow := detailedPowersOfTen[q-detailedPowersOfTenMinExp10] + if q < 0 { + // Inverse powers of ten must be rounded up. + pow[0] += 1 + } + e2 += mulByLog10Log2(q) - 127 + 119 + + // long multiplication + l1, l0 := bits.Mul64(m, pow[0]) + h1, h0 := bits.Mul64(m, pow[1]) + mid, carry := bits.Add64(l1, h0, 0) + h1 += carry + return h1<<9 | mid>>55, e2, mid<<9 == 0 && l0 == 0 +} + +func divisibleByPower5(m uint64, k int) bool { + if m == 0 { + return true + } + for i := 0; i < k; i++ { + if m%5 != 0 { + return false + } + m /= 5 + } + return true +} + +// divmod1e9 computes quotient and remainder of division by 1e9, +// avoiding runtime uint64 division on 32-bit platforms. +func divmod1e9(x uint64) (uint32, uint32) { + if !host32bit { + return uint32(x / 1e9), uint32(x % 1e9) + } + // Use the same sequence of operations as the amd64 compiler. + hi, _ := bits.Mul64(x>>1, 0x89705f4136b4a598) // binary digits of 1e-9 + q := hi >> 28 + return uint32(q), uint32(x - q*1e9) +} diff --git a/libgo/go/strconv/ftoaryu_test.go b/libgo/go/strconv/ftoaryu_test.go new file mode 100644 index 0000000..9758619 --- /dev/null +++ b/libgo/go/strconv/ftoaryu_test.go @@ -0,0 +1,31 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv_test + +import ( + "math" + . "strconv" + "testing" +) + +func TestMulByLog2Log10(t *testing.T) { + for x := -1600; x <= +1600; x++ { + iMath := MulByLog2Log10(x) + fMath := int(math.Floor(float64(x) * math.Ln2 / math.Ln10)) + if iMath != fMath { + t.Errorf("mulByLog2Log10(%d) failed: %d vs %d\n", x, iMath, fMath) + } + } +} + +func TestMulByLog10Log2(t *testing.T) { + for x := -500; x <= +500; x++ { + iMath := MulByLog10Log2(x) + fMath := int(math.Floor(float64(x) * math.Ln10 / math.Ln2)) + if iMath != fMath { + t.Errorf("mulByLog10Log2(%d) failed: %d vs %d\n", x, iMath, fMath) + } + } +} diff --git a/libgo/go/strconv/internal_test.go b/libgo/go/strconv/internal_test.go index bb4a418..f2cceff 100644 --- a/libgo/go/strconv/internal_test.go +++ b/libgo/go/strconv/internal_test.go @@ -21,3 +21,11 @@ func SetOptimize(b bool) bool { func ParseFloatPrefix(s string, bitSize int) (float64, int, error) { return parseFloatPrefix(s, bitSize) } + +func MulByLog2Log10(x int) int { + return mulByLog2Log10(x) +} + +func MulByLog10Log2(x int) int { + return mulByLog10Log2(x) +} diff --git a/libgo/go/strconv/makeisprint.go b/libgo/go/strconv/makeisprint.go index 0e6e90a..909f9e4 100644 --- a/libgo/go/strconv/makeisprint.go +++ b/libgo/go/strconv/makeisprint.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // @@ -36,7 +37,7 @@ var ( func bsearch16(a []uint16, x uint16) int { i, j := 0, len(a) for i < j { - h := i + (j-i)/2 + h := i + (j-i)>>1 if a[h] < x { i = h + 1 } else { @@ -51,7 +52,7 @@ func bsearch16(a []uint16, x uint16) int { func bsearch32(a []uint32, x uint32) int { i, j := 0, len(a) for i < j { - h := i + (j-i)/2 + h := i + (j-i)>>1 if a[h] < x { i = h + 1 } else { diff --git a/libgo/go/strconv/quote.go b/libgo/go/strconv/quote.go index bcbdbc5..b3bbb16 100644 --- a/libgo/go/strconv/quote.go +++ b/libgo/go/strconv/quote.go @@ -7,7 +7,6 @@ package strconv import ( - "internal/bytealg" "unicode/utf8" ) @@ -16,6 +15,11 @@ const ( upperhex = "0123456789ABCDEF" ) +// contains reports whether the string contains the byte c. +func contains(s string, c byte) bool { + return index(s, c) != -1 +} + func quoteWith(s string, quote byte, ASCIIonly, graphicOnly bool) string { return string(appendQuotedWith(make([]byte, 0, 3*len(s)/2), s, quote, ASCIIonly, graphicOnly)) } @@ -360,85 +364,132 @@ func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, return } +// QuotedPrefix returns the quoted string (as understood by Unquote) at the prefix of s. +// If s does not start with a valid quoted string, QuotedPrefix returns an error. +func QuotedPrefix(s string) (string, error) { + out, _, err := unquote(s, false) + return out, err +} + // Unquote interprets s as a single-quoted, double-quoted, // or backquoted Go string literal, returning the string value // that s quotes. (If s is single-quoted, it would be a Go // character literal; Unquote returns the corresponding // one-character string.) func Unquote(s string) (string, error) { - n := len(s) - if n < 2 { + out, rem, err := unquote(s, true) + if len(rem) > 0 { return "", ErrSyntax } - quote := s[0] - if quote != s[n-1] { - return "", ErrSyntax + return out, err +} + +// unquote parses a quoted string at the start of the input, +// returning the parsed prefix, the remaining suffix, and any parse errors. +// If unescape is true, the parsed prefix is unescaped, +// otherwise the input prefix is provided verbatim. +func unquote(in string, unescape bool) (out, rem string, err error) { + // Determine the quote form and optimistically find the terminating quote. + if len(in) < 2 { + return "", in, ErrSyntax } - s = s[1 : n-1] + quote := in[0] + end := index(in[1:], quote) + if end < 0 { + return "", in, ErrSyntax + } + end += 2 // position after terminating quote; may be wrong if escape sequences are present - if quote == '`' { - if contains(s, '`') { - return "", ErrSyntax + switch quote { + case '`': + switch { + case !unescape: + out = in[:end] // include quotes + case !contains(in[:end], '\r'): + out = in[len("`") : end-len("`")] // exclude quotes + default: + // Carriage return characters ('\r') inside raw string literals + // are discarded from the raw string value. + buf := make([]byte, 0, end-len("`")-len("\r")-len("`")) + for i := len("`"); i < end-len("`"); i++ { + if in[i] != '\r' { + buf = append(buf, in[i]) + } + } + out = string(buf) } - if contains(s, '\r') { - // -1 because we know there is at least one \r to remove. - buf := make([]byte, 0, len(s)-1) - for i := 0; i < len(s); i++ { - if s[i] != '\r' { - buf = append(buf, s[i]) + // NOTE: Prior implementations did not verify that raw strings consist + // of valid UTF-8 characters and we continue to not verify it as such. + // The Go specification does not explicitly require valid UTF-8, + // but only mention that it is implicitly valid for Go source code + // (which must be valid UTF-8). + return out, in[end:], nil + case '"', '\'': + // Handle quoted strings without any escape sequences. + if !contains(in[:end], '\\') && !contains(in[:end], '\n') { + var valid bool + switch quote { + case '"': + valid = utf8.ValidString(in[len(`"`) : end-len(`"`)]) + case '\'': + r, n := utf8.DecodeRuneInString(in[len("'") : end-len("'")]) + valid = len("'")+n+len("'") == end && (r != utf8.RuneError || n != 1) + } + if valid { + out = in[:end] + if unescape { + out = out[1 : end-1] // exclude quotes } + return out, in[end:], nil } - return string(buf), nil } - return s, nil - } - if quote != '"' && quote != '\'' { - return "", ErrSyntax - } - if contains(s, '\n') { - return "", ErrSyntax - } - // Is it trivial? Avoid allocation. - if !contains(s, '\\') && !contains(s, quote) { - switch quote { - case '"': - if utf8.ValidString(s) { - return s, nil + // Handle quoted strings with escape sequences. + var buf []byte + in0 := in + in = in[1:] // skip starting quote + if unescape { + buf = make([]byte, 0, 3*end/2) // try to avoid more allocations + } + for len(in) > 0 && in[0] != quote { + // Process the next character, + // rejecting any unescaped newline characters which are invalid. + r, multibyte, rem, err := UnquoteChar(in, quote) + if in[0] == '\n' || err != nil { + return "", in0, ErrSyntax } - case '\'': - r, size := utf8.DecodeRuneInString(s) - if size == len(s) && (r != utf8.RuneError || size != 1) { - return s, nil + in = rem + + // Append the character if unescaping the input. + if unescape { + if r < utf8.RuneSelf || !multibyte { + buf = append(buf, byte(r)) + } else { + var arr [utf8.UTFMax]byte + n := utf8.EncodeRune(arr[:], r) + buf = append(buf, arr[:n]...) + } } - } - } - var runeTmp [utf8.UTFMax]byte - buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations. - for len(s) > 0 { - c, multibyte, ss, err := UnquoteChar(s, quote) - if err != nil { - return "", err + // Single quoted strings must be a single character. + if quote == '\'' { + break + } } - s = ss - if c < utf8.RuneSelf || !multibyte { - buf = append(buf, byte(c)) - } else { - n := utf8.EncodeRune(runeTmp[:], c) - buf = append(buf, runeTmp[:n]...) + + // Verify that the string ends with a terminating quote. + if !(len(in) > 0 && in[0] == quote) { + return "", in0, ErrSyntax } - if quote == '\'' && len(s) != 0 { - // single-quoted must be single character - return "", ErrSyntax + in = in[1:] // skip terminating quote + + if unescape { + return string(buf), in, nil } + return in0[:len(in0)-len(in)], in, nil + default: + return "", in, ErrSyntax } - return string(buf), nil -} - -// contains reports whether the string contains the byte c. -func contains(s string, c byte) bool { - return bytealg.IndexByteString(s, c) != -1 } // bsearch16 returns the smallest i such that a[i] >= x. @@ -446,7 +497,7 @@ func contains(s string, c byte) bool { func bsearch16(a []uint16, x uint16) int { i, j := 0, len(a) for i < j { - h := i + (j-i)/2 + h := i + (j-i)>>1 if a[h] < x { i = h + 1 } else { @@ -461,7 +512,7 @@ func bsearch16(a []uint16, x uint16) int { func bsearch32(a []uint32, x uint32) int { i, j := 0, len(a) for i < j { - h := i + (j-i)/2 + h := i + (j-i)>>1 if a[h] < x { i = h + 1 } else { diff --git a/libgo/go/strconv/quote_test.go b/libgo/go/strconv/quote_test.go index f1faf13..4750be2 100644 --- a/libgo/go/strconv/quote_test.go +++ b/libgo/go/strconv/quote_test.go @@ -6,6 +6,7 @@ package strconv_test import ( . "strconv" + "strings" "testing" "unicode" ) @@ -297,6 +298,7 @@ var misquoted = []string{ `"\z"`, "`", "`xxx", + "``x\r", "`\"", `"\'"`, `'\"'`, @@ -307,22 +309,13 @@ var misquoted = []string{ func TestUnquote(t *testing.T) { for _, tt := range unquotetests { - if out, err := Unquote(tt.in); err != nil || out != tt.out { - t.Errorf("Unquote(%#q) = %q, %v want %q, nil", tt.in, out, err, tt.out) - } + testUnquote(t, tt.in, tt.out, nil) } - - // run the quote tests too, backward for _, tt := range quotetests { - if in, err := Unquote(tt.out); in != tt.in { - t.Errorf("Unquote(%#q) = %q, %v, want %q, nil", tt.out, in, err, tt.in) - } + testUnquote(t, tt.out, tt.in, nil) } - for _, s := range misquoted { - if out, err := Unquote(s); out != "" || err != ErrSyntax { - t.Errorf("Unquote(%#q) = %q, %v want %q, %v", s, out, err, "", ErrSyntax) - } + testUnquote(t, s, "", ErrSyntax) } } @@ -333,26 +326,44 @@ func TestUnquoteInvalidUTF8(t *testing.T) { // one of: want string - wantErr string + wantErr error }{ {in: `"foo"`, want: "foo"}, - {in: `"foo`, wantErr: "invalid syntax"}, + {in: `"foo`, wantErr: ErrSyntax}, {in: `"` + "\xc0" + `"`, want: "\xef\xbf\xbd"}, {in: `"a` + "\xc0" + `"`, want: "a\xef\xbf\xbd"}, {in: `"\t` + "\xc0" + `"`, want: "\t\xef\xbf\xbd"}, } - for i, tt := range tests { - got, err := Unquote(tt.in) - var gotErr string - if err != nil { - gotErr = err.Error() - } - if gotErr != tt.wantErr { - t.Errorf("%d. Unquote(%q) = err %v; want %q", i, tt.in, err, tt.wantErr) - } - if tt.wantErr == "" && err == nil && got != tt.want { - t.Errorf("%d. Unquote(%q) = %02x; want %02x", i, tt.in, []byte(got), []byte(tt.want)) - } + for _, tt := range tests { + testUnquote(t, tt.in, tt.want, tt.wantErr) + } +} + +func testUnquote(t *testing.T, in, want string, wantErr error) { + // Test Unquote. + got, gotErr := Unquote(in) + if got != want || gotErr != wantErr { + t.Errorf("Unquote(%q) = (%q, %v), want (%q, %v)", in, got, gotErr, want, wantErr) + } + + // Test QuotedPrefix. + // Adding an arbitrary suffix should not change the result of QuotedPrefix + // assume that the suffix doesn't accidentally terminate a truncated input. + if gotErr == nil { + want = in + } + suffix := "\n\r\\\"`'" // special characters for quoted strings + if len(in) > 0 { + suffix = strings.ReplaceAll(suffix, in[:1], "") + } + in += suffix + got, gotErr = QuotedPrefix(in) + if gotErr == nil && wantErr != nil { + _, wantErr = Unquote(got) // original input had trailing junk, reparse with only valid prefix + want = got + } + if got != want || gotErr != wantErr { + t.Errorf("QuotedPrefix(%q) = (%q, %v), want (%q, %v)", in, got, gotErr, want, wantErr) } } diff --git a/libgo/go/strings/builder.go b/libgo/go/strings/builder.go index 6ff151d..547e52e84 100644 --- a/libgo/go/strings/builder.go +++ b/libgo/go/strings/builder.go @@ -103,7 +103,8 @@ func (b *Builder) WriteByte(c byte) error { // It returns the length of r and a nil error. func (b *Builder) WriteRune(r rune) (int, error) { b.copyCheck() - if r < utf8.RuneSelf { + // Compare as uint32 to correctly handle negative runes. + if uint32(r) < utf8.RuneSelf { b.buf = append(b.buf, byte(r)) return 1, nil } diff --git a/libgo/go/strings/builder_test.go b/libgo/go/strings/builder_test.go index fbf6617..61c0cf4 100644 --- a/libgo/go/strings/builder_test.go +++ b/libgo/go/strings/builder_test.go @@ -9,6 +9,7 @@ import ( "runtime" . "strings" "testing" + "unicode/utf8" ) func check(t *testing.T, b *Builder, want string) { @@ -308,6 +309,16 @@ func TestBuilderCopyPanic(t *testing.T) { } } +func TestBuilderWriteInvalidRune(t *testing.T) { + // Invalid runes, including negative ones, should be written as + // utf8.RuneError. + for _, r := range []rune{-1, utf8.MaxRune + 1} { + var b Builder + b.WriteRune(r) + check(t, &b, "\uFFFD") + } +} + var someBytes = []byte("some bytes sdljlk jsklj3lkjlk djlkjw") var sinkS string diff --git a/libgo/go/sync/atomic/value.go b/libgo/go/sync/atomic/value.go index eab7e70..61f81d8 100644 --- a/libgo/go/sync/atomic/value.go +++ b/libgo/go/sync/atomic/value.go @@ -25,7 +25,7 @@ type ifaceWords struct { // Load returns the value set by the most recent Store. // It returns nil if there has been no call to Store for this Value. -func (v *Value) Load() (x interface{}) { +func (v *Value) Load() (val interface{}) { vp := (*ifaceWords)(unsafe.Pointer(v)) typ := LoadPointer(&vp.typ) if typ == nil || uintptr(typ) == ^uintptr(0) { @@ -33,21 +33,21 @@ func (v *Value) Load() (x interface{}) { return nil } data := LoadPointer(&vp.data) - xp := (*ifaceWords)(unsafe.Pointer(&x)) - xp.typ = typ - xp.data = data + vlp := (*ifaceWords)(unsafe.Pointer(&val)) + vlp.typ = typ + vlp.data = data return } // Store sets the value of the Value to x. // All calls to Store for a given Value must use values of the same concrete type. // Store of an inconsistent type panics, as does Store(nil). -func (v *Value) Store(x interface{}) { - if x == nil { +func (v *Value) Store(val interface{}) { + if val == nil { panic("sync/atomic: store of nil value into Value") } vp := (*ifaceWords)(unsafe.Pointer(v)) - xp := (*ifaceWords)(unsafe.Pointer(&x)) + vlp := (*ifaceWords)(unsafe.Pointer(&val)) for { typ := LoadPointer(&vp.typ) if typ == nil { @@ -61,8 +61,8 @@ func (v *Value) Store(x interface{}) { continue } // Complete first store. - StorePointer(&vp.data, xp.data) - StorePointer(&vp.typ, xp.typ) + StorePointer(&vp.data, vlp.data) + StorePointer(&vp.typ, vlp.typ) runtime_procUnpin() return } @@ -73,14 +73,121 @@ func (v *Value) Store(x interface{}) { continue } // First store completed. Check type and overwrite data. - if typ != xp.typ { + if typ != vlp.typ { panic("sync/atomic: store of inconsistently typed value into Value") } - StorePointer(&vp.data, xp.data) + StorePointer(&vp.data, vlp.data) return } } +// Swap stores new into Value and returns the previous value. It returns nil if +// the Value is empty. +// +// All calls to Swap for a given Value must use values of the same concrete +// type. Swap of an inconsistent type panics, as does Swap(nil). +func (v *Value) Swap(new interface{}) (old interface{}) { + if new == nil { + panic("sync/atomic: swap of nil value into Value") + } + vp := (*ifaceWords)(unsafe.Pointer(v)) + np := (*ifaceWords)(unsafe.Pointer(&new)) + for { + typ := LoadPointer(&vp.typ) + if typ == nil { + // Attempt to start first store. + // Disable preemption so that other goroutines can use + // active spin wait to wait for completion; and so that + // GC does not see the fake type accidentally. + runtime_procPin() + if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) { + runtime_procUnpin() + continue + } + // Complete first store. + StorePointer(&vp.data, np.data) + StorePointer(&vp.typ, np.typ) + runtime_procUnpin() + return nil + } + if uintptr(typ) == ^uintptr(0) { + // First store in progress. Wait. + // Since we disable preemption around the first store, + // we can wait with active spinning. + continue + } + // First store completed. Check type and overwrite data. + if typ != np.typ { + panic("sync/atomic: swap of inconsistently typed value into Value") + } + op := (*ifaceWords)(unsafe.Pointer(&old)) + op.typ, op.data = np.typ, SwapPointer(&vp.data, np.data) + return old + } +} + +// CompareAndSwapPointer executes the compare-and-swap operation for the Value. +// +// All calls to CompareAndSwap for a given Value must use values of the same +// concrete type. CompareAndSwap of an inconsistent type panics, as does +// CompareAndSwap(old, nil). +func (v *Value) CompareAndSwap(old, new interface{}) (swapped bool) { + if new == nil { + panic("sync/atomic: compare and swap of nil value into Value") + } + vp := (*ifaceWords)(unsafe.Pointer(v)) + np := (*ifaceWords)(unsafe.Pointer(&new)) + op := (*ifaceWords)(unsafe.Pointer(&old)) + if op.typ != nil && np.typ != op.typ { + panic("sync/atomic: compare and swap of inconsistently typed values") + } + for { + typ := LoadPointer(&vp.typ) + if typ == nil { + if old != nil { + return false + } + // Attempt to start first store. + // Disable preemption so that other goroutines can use + // active spin wait to wait for completion; and so that + // GC does not see the fake type accidentally. + runtime_procPin() + if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) { + runtime_procUnpin() + continue + } + // Complete first store. + StorePointer(&vp.data, np.data) + StorePointer(&vp.typ, np.typ) + runtime_procUnpin() + return true + } + if uintptr(typ) == ^uintptr(0) { + // First store in progress. Wait. + // Since we disable preemption around the first store, + // we can wait with active spinning. + continue + } + // First store completed. Check type and overwrite data. + if typ != np.typ { + panic("sync/atomic: compare and swap of inconsistently typed value into Value") + } + // Compare old and current via runtime equality check. + // This allows value types to be compared, something + // not offered by the package functions. + // CompareAndSwapPointer below only ensures vp.data + // has not changed since LoadPointer. + data := LoadPointer(&vp.data) + var i interface{} + (*ifaceWords)(unsafe.Pointer(&i)).typ = typ + (*ifaceWords)(unsafe.Pointer(&i)).data = data + if i != old { + return false + } + return CompareAndSwapPointer(&vp.data, data, np.data) + } +} + // Disable/enable preemption, implemented in runtime. func runtime_procPin() func runtime_procUnpin() diff --git a/libgo/go/sync/atomic/value_test.go b/libgo/go/sync/atomic/value_test.go index f289766..a5e717d 100644 --- a/libgo/go/sync/atomic/value_test.go +++ b/libgo/go/sync/atomic/value_test.go @@ -7,6 +7,9 @@ package atomic_test import ( "math/rand" "runtime" + "strconv" + "sync" + "sync/atomic" . "sync/atomic" "testing" ) @@ -133,3 +136,139 @@ func BenchmarkValueRead(b *testing.B) { } }) } + +var Value_SwapTests = []struct { + init interface{} + new interface{} + want interface{} + err interface{} +}{ + {init: nil, new: nil, err: "sync/atomic: swap of nil value into Value"}, + {init: nil, new: true, want: nil, err: nil}, + {init: true, new: "", err: "sync/atomic: swap of inconsistently typed value into Value"}, + {init: true, new: false, want: true, err: nil}, +} + +func TestValue_Swap(t *testing.T) { + for i, tt := range Value_SwapTests { + t.Run(strconv.Itoa(i), func(t *testing.T) { + var v Value + if tt.init != nil { + v.Store(tt.init) + } + defer func() { + err := recover() + switch { + case tt.err == nil && err != nil: + t.Errorf("should not panic, got %v", err) + case tt.err != nil && err == nil: + t.Errorf("should panic %v, got <nil>", tt.err) + } + }() + if got := v.Swap(tt.new); got != tt.want { + t.Errorf("got %v, want %v", got, tt.want) + } + if got := v.Load(); got != tt.new { + t.Errorf("got %v, want %v", got, tt.new) + } + }) + } +} + +func TestValueSwapConcurrent(t *testing.T) { + var v Value + var count uint64 + var g sync.WaitGroup + var m, n uint64 = 10000, 10000 + if testing.Short() { + m = 1000 + n = 1000 + } + for i := uint64(0); i < m*n; i += n { + i := i + g.Add(1) + go func() { + var c uint64 + for new := i; new < i+n; new++ { + if old := v.Swap(new); old != nil { + c += old.(uint64) + } + } + atomic.AddUint64(&count, c) + g.Done() + }() + } + g.Wait() + if want, got := (m*n-1)*(m*n)/2, count+v.Load().(uint64); got != want { + t.Errorf("sum from 0 to %d was %d, want %v", m*n-1, got, want) + } +} + +var heapA, heapB = struct{ uint }{0}, struct{ uint }{0} + +var Value_CompareAndSwapTests = []struct { + init interface{} + new interface{} + old interface{} + want bool + err interface{} +}{ + {init: nil, new: nil, old: nil, err: "sync/atomic: compare and swap of nil value into Value"}, + {init: nil, new: true, old: "", err: "sync/atomic: compare and swap of inconsistently typed values into Value"}, + {init: nil, new: true, old: true, want: false, err: nil}, + {init: nil, new: true, old: nil, want: true, err: nil}, + {init: true, new: "", err: "sync/atomic: compare and swap of inconsistently typed value into Value"}, + {init: true, new: true, old: false, want: false, err: nil}, + {init: true, new: true, old: true, want: true, err: nil}, + {init: heapA, new: struct{ uint }{1}, old: heapB, want: true, err: nil}, +} + +func TestValue_CompareAndSwap(t *testing.T) { + for i, tt := range Value_CompareAndSwapTests { + t.Run(strconv.Itoa(i), func(t *testing.T) { + var v Value + if tt.init != nil { + v.Store(tt.init) + } + defer func() { + err := recover() + switch { + case tt.err == nil && err != nil: + t.Errorf("got %v, wanted no panic", err) + case tt.err != nil && err == nil: + t.Errorf("did not panic, want %v", tt.err) + } + }() + if got := v.CompareAndSwap(tt.old, tt.new); got != tt.want { + t.Errorf("got %v, want %v", got, tt.want) + } + }) + } +} + +func TestValueCompareAndSwapConcurrent(t *testing.T) { + var v Value + var w sync.WaitGroup + v.Store(0) + m, n := 1000, 100 + if testing.Short() { + m = 100 + n = 100 + } + for i := 0; i < m; i++ { + i := i + w.Add(1) + go func() { + for j := i; j < m*n; runtime.Gosched() { + if v.CompareAndSwap(j, j+1) { + j += m + } + } + w.Done() + }() + } + w.Wait() + if stop := v.Load().(int); stop != m*n { + t.Errorf("did not get to %v, stopped at %v", m*n, stop) + } +} diff --git a/libgo/go/sync/map.go b/libgo/go/sync/map.go index 9ad2535..dfb62dd 100644 --- a/libgo/go/sync/map.go +++ b/libgo/go/sync/map.go @@ -73,7 +73,8 @@ var expunged = unsafe.Pointer(new(interface{})) type entry struct { // p points to the interface{} value stored for the entry. // - // If p == nil, the entry has been deleted and m.dirty == nil. + // If p == nil, the entry has been deleted, and either m.dirty == nil or + // m.dirty[key] is e. // // If p == expunged, the entry has been deleted, m.dirty != nil, and the entry // is missing from m.dirty. diff --git a/libgo/go/sync/pool_test.go b/libgo/go/sync/pool_test.go index c67bd8c..9371644 100644 --- a/libgo/go/sync/pool_test.go +++ b/libgo/go/sync/pool_test.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. // Pool is no-op under race detector, so all these tests do not work. +//go:build !race // +build !race package sync_test diff --git a/libgo/go/sync/runtime2.go b/libgo/go/sync/runtime2.go index f10c4e8..c4b4489 100644 --- a/libgo/go/sync/runtime2.go +++ b/libgo/go/sync/runtime2.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !goexperiment.staticlockranking // +build !goexperiment.staticlockranking package sync diff --git a/libgo/go/sync/runtime2_lockrank.go b/libgo/go/sync/runtime2_lockrank.go index aaa1c27..e91fdb6 100644 --- a/libgo/go/sync/runtime2_lockrank.go +++ b/libgo/go/sync/runtime2_lockrank.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build goexperiment.staticlockranking // +build goexperiment.staticlockranking package sync diff --git a/libgo/go/syscall/bpf_bsd.go b/libgo/go/syscall/bpf_bsd.go index f67ee60..452d4cf 100644 --- a/libgo/go/syscall/bpf_bsd.go +++ b/libgo/go/syscall/bpf_bsd.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build dragonfly || freebsd || netbsd || openbsd // +build dragonfly freebsd netbsd openbsd // Berkeley packet filter for BSD variants diff --git a/libgo/go/syscall/creds_test.go b/libgo/go/syscall/creds_test.go index 524689a..c1a8b51 100644 --- a/libgo/go/syscall/creds_test.go +++ b/libgo/go/syscall/creds_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux // +build linux package syscall_test @@ -37,16 +38,19 @@ func TestSCMCredentials(t *testing.T) { if err != nil { t.Fatalf("Socketpair: %v", err) } - defer syscall.Close(fds[0]) - defer syscall.Close(fds[1]) err = syscall.SetsockoptInt(fds[0], syscall.SOL_SOCKET, syscall.SO_PASSCRED, 1) if err != nil { + syscall.Close(fds[0]) + syscall.Close(fds[1]) t.Fatalf("SetsockoptInt: %v", err) } srvFile := os.NewFile(uintptr(fds[0]), "server") + cliFile := os.NewFile(uintptr(fds[1]), "client") defer srvFile.Close() + defer cliFile.Close() + srv, err := net.FileConn(srvFile) if err != nil { t.Errorf("FileConn: %v", err) @@ -54,8 +58,6 @@ func TestSCMCredentials(t *testing.T) { } defer srv.Close() - cliFile := os.NewFile(uintptr(fds[1]), "client") - defer cliFile.Close() cli, err := net.FileConn(cliFile) if err != nil { t.Errorf("FileConn: %v", err) @@ -103,8 +105,8 @@ func TestSCMCredentials(t *testing.T) { if err != nil { t.Fatalf("ReadMsgUnix: %v", err) } - if flags != 0 { - t.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags) + if flags != syscall.MSG_CMSG_CLOEXEC { + t.Fatalf("ReadMsgUnix flags = %#x, want %#x (MSG_CMSG_CLOEXEC)", flags, syscall.MSG_CMSG_CLOEXEC) } if n != tt.dataLen { t.Fatalf("ReadMsgUnix n = %d, want %d", n, tt.dataLen) diff --git a/libgo/go/syscall/dirent.go b/libgo/go/syscall/dirent.go index 5726449..1e95946 100644 --- a/libgo/go/syscall/dirent.go +++ b/libgo/go/syscall/dirent.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package syscall diff --git a/libgo/go/syscall/dirent_test.go b/libgo/go/syscall/dirent_test.go index 7dac98f..71b445b 100644 --- a/libgo/go/syscall/dirent_test.go +++ b/libgo/go/syscall/dirent_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package syscall_test @@ -26,16 +27,12 @@ func TestDirent(t *testing.T) { filenameMinSize = 11 ) - d, err := os.MkdirTemp("", "dirent-test") - if err != nil { - t.Fatalf("tempdir: %v", err) - } - defer os.RemoveAll(d) + d := t.TempDir() t.Logf("tmpdir: %s", d) for i, c := range []byte("0123456789") { name := string(bytes.Repeat([]byte{c}, filenameMinSize+i)) - err = os.WriteFile(filepath.Join(d, name), nil, 0644) + err := os.WriteFile(filepath.Join(d, name), nil, 0644) if err != nil { t.Fatalf("writefile: %v", err) } @@ -92,18 +89,14 @@ func TestDirentRepeat(t *testing.T) { } // Make a directory containing N files - d, err := os.MkdirTemp("", "direntRepeat-test") - if err != nil { - t.Fatalf("tempdir: %v", err) - } - defer os.RemoveAll(d) + d := t.TempDir() var files []string for i := 0; i < N; i++ { files = append(files, fmt.Sprintf("file%d", i)) } for _, file := range files { - err = os.WriteFile(filepath.Join(d, file), []byte("contents"), 0644) + err := os.WriteFile(filepath.Join(d, file), []byte("contents"), 0644) if err != nil { t.Fatalf("writefile: %v", err) } diff --git a/libgo/go/syscall/endian_big.go b/libgo/go/syscall/endian_big.go index 24a4d1d..a38e9c6 100644 --- a/libgo/go/syscall/endian_big.go +++ b/libgo/go/syscall/endian_big.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +//go:build ppc64 || s390x || mips || mips64 || armbe || arm64be || m68k || ppc || mips64p32 || s390 || shbe || sparc || sparc64 // +build ppc64 s390x mips mips64 armbe arm64be m68k ppc mips64p32 s390 shbe sparc sparc64 package syscall diff --git a/libgo/go/syscall/endian_little.go b/libgo/go/syscall/endian_little.go index 22cac17..2332fa3 100644 --- a/libgo/go/syscall/endian_little.go +++ b/libgo/go/syscall/endian_little.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // -// +build 386 alpha amd64 amd64p32 arm arm64 ia64 mips64le mipsle mips64p32le nios2 ppc64le riscv riscv64 sh wasm +//go:build 386 || alpha || amd64 || amd64p32 || arm || arm64 || ia64 || ppc64le || mips64le || mipsle || mips64p32le || nios2 || riscv || riscv64 || sh || wasm +// +build 386 alpha amd64 amd64p32 arm arm64 ia64 ppc64le mips64le mipsle mips64p32le nios2 riscv riscv64 sh wasm package syscall diff --git a/libgo/go/syscall/env_unix.go b/libgo/go/syscall/env_unix.go index c56b6b8..0d95c55 100644 --- a/libgo/go/syscall/env_unix.go +++ b/libgo/go/syscall/env_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || plan9 // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris plan9 // Unix environment variables. diff --git a/libgo/go/syscall/exec_bsd.go b/libgo/go/syscall/exec_bsd.go index ca7fdc0..a081c09 100644 --- a/libgo/go/syscall/exec_bsd.go +++ b/libgo/go/syscall/exec_bsd.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd hurd netbsd openbsd solaris +//go:build dragonfly || freebsd || hurd || netbsd || (openbsd && mips64) +// +build dragonfly freebsd hurd netbsd openbsd,mips64 package syscall @@ -89,8 +90,6 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr // Fork succeeded, now in child. - runtime_AfterForkInChild() - // Enable tracing if requested. if sys.Ptrace { err1 = raw_ptrace(_PTRACE_TRACEME, 0, 0, 0) @@ -129,6 +128,10 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr } } + // Restore the signal mask. We do this after TIOCSPGRP to avoid + // having the kernel send a SIGTTOU signal to the process group. + runtime_AfterForkInChild() + // Chroot if chroot != nil { err1 = raw_chroot(chroot) diff --git a/libgo/go/syscall/exec_linux.go b/libgo/go/syscall/exec_linux.go index 0da6c96..c9be86b 100644 --- a/libgo/go/syscall/exec_linux.go +++ b/libgo/go/syscall/exec_linux.go @@ -2,11 +2,13 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux // +build linux package syscall import ( + "internal/itoa" "unsafe" ) @@ -244,8 +246,6 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att // Fork succeeded, now in child. - runtime_AfterForkInChild() - // Enable the "keep capabilities" flag to set ambient capabilities later. if len(sys.AmbientCaps) > 0 { _, err1 = raw_prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) @@ -303,6 +303,10 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att } } + // Restore the signal mask. We do this after TIOCSPGRP to avoid + // having the kernel send a SIGTTOU signal to the process group. + runtime_AfterForkInChild() + // Unshare if sys.Unshareflags != 0 { err1 = rawUnshare(int(sys.Unshareflags)) @@ -575,7 +579,7 @@ func forkExecPipe(p []int) (err error) { func formatIDMappings(idMap []SysProcIDMap) []byte { var data []byte for _, im := range idMap { - data = append(data, []byte(itoa(im.ContainerID)+" "+itoa(im.HostID)+" "+itoa(im.Size)+"\n")...) + data = append(data, []byte(itoa.Itoa(im.ContainerID)+" "+itoa.Itoa(im.HostID)+" "+itoa.Itoa(im.Size)+"\n")...) } return data } @@ -604,7 +608,7 @@ func writeIDMappings(path string, idMap []SysProcIDMap) error { // This is needed since kernel 3.19, because you can't write gid_map without // disabling setgroups() system call. func writeSetgroups(pid int, enable bool) error { - sgf := "/proc/" + itoa(pid) + "/setgroups" + sgf := "/proc/" + itoa.Itoa(pid) + "/setgroups" fd, err := Open(sgf, O_RDWR, 0) if err != nil { return err @@ -629,7 +633,7 @@ func writeSetgroups(pid int, enable bool) error { // for a process and it is called from the parent process. func writeUidGidMappings(pid int, sys *SysProcAttr) error { if sys.UidMappings != nil { - uidf := "/proc/" + itoa(pid) + "/uid_map" + uidf := "/proc/" + itoa.Itoa(pid) + "/uid_map" if err := writeIDMappings(uidf, sys.UidMappings); err != nil { return err } @@ -640,7 +644,7 @@ func writeUidGidMappings(pid int, sys *SysProcAttr) error { if err := writeSetgroups(pid, sys.GidMappingsEnableSetgroups); err != nil && err != ENOENT { return err } - gidf := "/proc/" + itoa(pid) + "/gid_map" + gidf := "/proc/" + itoa.Itoa(pid) + "/gid_map" if err := writeIDMappings(gidf, sys.GidMappings); err != nil { return err } diff --git a/libgo/go/syscall/exec_linux_test.go b/libgo/go/syscall/exec_linux_test.go index bbab36d..ec0a4c0 100644 --- a/libgo/go/syscall/exec_linux_test.go +++ b/libgo/go/syscall/exec_linux_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux // +build linux package syscall_test @@ -317,6 +318,7 @@ func TestGroupCleanupUserNamespace(t *testing.T) { "uid=0(root) gid=0(root) groups=0(root),65534", "uid=0(root) gid=0(root) groups=0(root),65534(nobody),65534(nobody),65534(nobody),65534(nobody),65534(nobody),65534(nobody),65534(nobody),65534(nobody),65534(nobody),65534(nobody)", // Alpine; see https://golang.org/issue/19938 "uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023", // CentOS with SELinux context, see https://golang.org/issue/34547 + "uid=0(root) gid=0(root) groups=0(root),65534(nobody) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023", // Fedora with SElinux context, see https://golang.org/issue/46752 } for _, e := range expected { if strOut == e { diff --git a/libgo/go/syscall/exec_unix.go b/libgo/go/syscall/exec_unix.go index d89bf38..7e01648 100644 --- a/libgo/go/syscall/exec_unix.go +++ b/libgo/go/syscall/exec_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris // Fork, exec, wait, etc. @@ -353,7 +354,7 @@ func Exec(argv0 string, argv []string, envv []string) (err error) { } else if runtime.GOOS == "darwin" || runtime.GOOS == "ios" { // Similarly on Darwin. err1 = execveDarwin(argv0p, &argvp[0], &envvp[0]) - } else if runtime.GOOS == "openbsd" && runtime.GOARCH == "amd64" { + } else if runtime.GOOS == "openbsd" && (runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") { // Similarly on OpenBSD. err1 = execveOpenBSD(argv0p, &argvp[0], &envvp[0]) } else { diff --git a/libgo/go/syscall/exec_unix_test.go b/libgo/go/syscall/exec_unix_test.go index 1399149..8595722 100644 --- a/libgo/go/syscall/exec_unix_test.go +++ b/libgo/go/syscall/exec_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package syscall_test @@ -169,11 +170,13 @@ func TestForeground(t *testing.T) { t.Skip("skipping; TestForeground: fails on GNU/Hurd") } signal.Ignore(syscall.SIGTTIN, syscall.SIGTTOU) + defer signal.Reset() tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0) if err != nil { t.Skipf("Can't test Foreground. Couldn't open /dev/tty: %s", err) } + defer tty.Close() fpgrp := syscall.Pid_t(0) @@ -212,12 +215,68 @@ func TestForeground(t *testing.T) { cmd.Stop() - errno = syscall.Ioctl(tty.Fd(), syscall.TIOCSPGRP, uintptr(unsafe.Pointer(&fpgrp))) + // This call fails on darwin/arm64. The failure doesn't matter, though. + // This is just best effort. + syscall.Ioctl(tty.Fd(), syscall.TIOCSPGRP, uintptr(unsafe.Pointer(&fpgrp))) +} + +func TestForegroundSignal(t *testing.T) { + tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0) + if err != nil { + t.Skipf("couldn't open /dev/tty: %s", err) + } + defer tty.Close() + + // This should really be pid_t, however _C_int (aka int32) is generally + // equivalent. + fpgrp := int32(0) + + errno := syscall.Ioctl(tty.Fd(), syscall.TIOCGPGRP, uintptr(unsafe.Pointer(&fpgrp))) if errno != 0 { - t.Fatalf("TIOCSPGRP failed with error code: %s", errno) + t.Fatalf("TIOCGPGRP failed with error code: %s", errno) } - signal.Reset() + if fpgrp == 0 { + t.Fatalf("Foreground process group is zero") + } + + defer func() { + signal.Ignore(syscall.SIGTTIN, syscall.SIGTTOU) + syscall.Ioctl(tty.Fd(), syscall.TIOCSPGRP, uintptr(unsafe.Pointer(&fpgrp))) + signal.Reset() + }() + + ch1 := make(chan os.Signal, 1) + ch2 := make(chan bool) + + signal.Notify(ch1, syscall.SIGTTIN, syscall.SIGTTOU) + defer signal.Stop(ch1) + + cmd := create(t) + + go func() { + cmd.proc.SysProcAttr = &syscall.SysProcAttr{ + Ctty: int(tty.Fd()), + Foreground: true, + } + cmd.Start() + cmd.Stop() + close(ch2) + }() + + timer := time.NewTimer(30 * time.Second) + defer timer.Stop() + for { + select { + case sig := <-ch1: + t.Errorf("unexpected signal %v", sig) + case <-ch2: + // Success. + return + case <-timer.C: + t.Fatal("timed out waiting for child process") + } + } } // Test a couple of cases that SysProcAttr can't handle. Issue 29458. diff --git a/libgo/go/syscall/exec_windows.go b/libgo/go/syscall/exec_windows.go index 46cbd75..18d1502 100644 --- a/libgo/go/syscall/exec_windows.go +++ b/libgo/go/syscall/exec_windows.go @@ -7,6 +7,7 @@ package syscall import ( + "runtime" "sync" "unicode/utf16" "unsafe" @@ -235,13 +236,15 @@ type ProcAttr struct { } type SysProcAttr struct { - HideWindow bool - CmdLine string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess - CreationFlags uint32 - Token Token // if set, runs new process in the security context represented by the token - ProcessAttributes *SecurityAttributes // if set, applies these security attributes as the descriptor for the new process - ThreadAttributes *SecurityAttributes // if set, applies these security attributes as the descriptor for the main thread of the new process - NoInheritHandles bool // if set, each inheritable handle in the calling process is not inherited by the new process + HideWindow bool + CmdLine string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess + CreationFlags uint32 + Token Token // if set, runs new process in the security context represented by the token + ProcessAttributes *SecurityAttributes // if set, applies these security attributes as the descriptor for the new process + ThreadAttributes *SecurityAttributes // if set, applies these security attributes as the descriptor for the main thread of the new process + NoInheritHandles bool // if set, each inheritable handle in the calling process is not inherited by the new process + AdditionalInheritedHandles []Handle // a list of additional handles, already marked as inheritable, that will be inherited by the new process + ParentProcess Handle // if non-zero, the new process regards the process given by this handle as its parent process, and AdditionalInheritedHandles, if set, should exist in this parent process } var zeroProcAttr ProcAttr @@ -310,46 +313,104 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle } } - // Acquire the fork lock so that no other threads - // create new fds that are not yet close-on-exec - // before we fork. - ForkLock.Lock() - defer ForkLock.Unlock() + var maj, min, build uint32 + rtlGetNtVersionNumbers(&maj, &min, &build) + isWin7 := maj < 6 || (maj == 6 && min <= 1) + // NT kernel handles are divisible by 4, with the bottom 3 bits left as + // a tag. The fully set tag correlates with the types of handles we're + // concerned about here. Except, the kernel will interpret some + // special handle values, like -1, -2, and so forth, so kernelbase.dll + // checks to see that those bottom three bits are checked, but that top + // bit is not checked. + isLegacyWin7ConsoleHandle := func(handle Handle) bool { return isWin7 && handle&0x10000003 == 3 } p, _ := GetCurrentProcess() + parentProcess := p + if sys.ParentProcess != 0 { + parentProcess = sys.ParentProcess + } fd := make([]Handle, len(attr.Files)) for i := range attr.Files { if attr.Files[i] > 0 { - err := DuplicateHandle(p, Handle(attr.Files[i]), p, &fd[i], 0, true, DUPLICATE_SAME_ACCESS) + destinationProcessHandle := parentProcess + + // On Windows 7, console handles aren't real handles, and can only be duplicated + // into the current process, not a parent one, which amounts to the same thing. + if parentProcess != p && isLegacyWin7ConsoleHandle(Handle(attr.Files[i])) { + destinationProcessHandle = p + } + + err := DuplicateHandle(p, Handle(attr.Files[i]), destinationProcessHandle, &fd[i], 0, true, DUPLICATE_SAME_ACCESS) if err != nil { return 0, 0, err } - defer CloseHandle(Handle(fd[i])) + defer DuplicateHandle(parentProcess, fd[i], 0, nil, 0, false, DUPLICATE_CLOSE_SOURCE) } } - si := new(StartupInfo) + si := new(_STARTUPINFOEXW) + si.ProcThreadAttributeList, err = newProcThreadAttributeList(2) + if err != nil { + return 0, 0, err + } + defer deleteProcThreadAttributeList(si.ProcThreadAttributeList) si.Cb = uint32(unsafe.Sizeof(*si)) si.Flags = STARTF_USESTDHANDLES if sys.HideWindow { si.Flags |= STARTF_USESHOWWINDOW si.ShowWindow = SW_HIDE } + if sys.ParentProcess != 0 { + err = updateProcThreadAttribute(si.ProcThreadAttributeList, 0, _PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, unsafe.Pointer(&sys.ParentProcess), unsafe.Sizeof(sys.ParentProcess), nil, nil) + if err != nil { + return 0, 0, err + } + } si.StdInput = fd[0] si.StdOutput = fd[1] si.StdErr = fd[2] - pi := new(ProcessInformation) + fd = append(fd, sys.AdditionalInheritedHandles...) - flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT + // On Windows 7, console handles aren't real handles, so don't pass them + // through to PROC_THREAD_ATTRIBUTE_HANDLE_LIST. + for i := range fd { + if isLegacyWin7ConsoleHandle(fd[i]) { + fd[i] = 0 + } + } + + // The presence of a NULL handle in the list is enough to cause PROC_THREAD_ATTRIBUTE_HANDLE_LIST + // to treat the entire list as empty, so remove NULL handles. + j := 0 + for i := range fd { + if fd[i] != 0 { + fd[j] = fd[i] + j++ + } + } + fd = fd[:j] + + // Do not accidentally inherit more than these handles. + if len(fd) > 0 { + err = updateProcThreadAttribute(si.ProcThreadAttributeList, 0, _PROC_THREAD_ATTRIBUTE_HANDLE_LIST, unsafe.Pointer(&fd[0]), uintptr(len(fd))*unsafe.Sizeof(fd[0]), nil, nil) + if err != nil { + return 0, 0, err + } + } + + pi := new(ProcessInformation) + flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT | _EXTENDED_STARTUPINFO_PRESENT if sys.Token != 0 { - err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, !sys.NoInheritHandles, flags, createEnvBlock(attr.Env), dirp, si, pi) + err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, len(fd) > 0 && !sys.NoInheritHandles, flags, createEnvBlock(attr.Env), dirp, &si.StartupInfo, pi) } else { - err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, !sys.NoInheritHandles, flags, createEnvBlock(attr.Env), dirp, si, pi) + err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, len(fd) > 0 && !sys.NoInheritHandles, flags, createEnvBlock(attr.Env), dirp, &si.StartupInfo, pi) } if err != nil { return 0, 0, err } defer CloseHandle(Handle(pi.Thread)) + runtime.KeepAlive(fd) + runtime.KeepAlive(sys) return int(pi.ProcessId), uintptr(pi.Process), nil } diff --git a/libgo/go/syscall/exec_windows_test.go b/libgo/go/syscall/exec_windows_test.go index eda1d36..8b8f330 100644 --- a/libgo/go/syscall/exec_windows_test.go +++ b/libgo/go/syscall/exec_windows_test.go @@ -5,8 +5,13 @@ package syscall_test import ( + "fmt" + "os" + "os/exec" + "path/filepath" "syscall" "testing" + "time" ) func TestEscapeArg(t *testing.T) { @@ -41,3 +46,70 @@ func TestEscapeArg(t *testing.T) { } } } + +func TestChangingProcessParent(t *testing.T) { + if os.Getenv("GO_WANT_HELPER_PROCESS") == "parent" { + // in parent process + + // Parent does nothing. It is just used as a parent of a child process. + time.Sleep(time.Minute) + os.Exit(0) + } + + if os.Getenv("GO_WANT_HELPER_PROCESS") == "child" { + // in child process + dumpPath := os.Getenv("GO_WANT_HELPER_PROCESS_FILE") + if dumpPath == "" { + fmt.Fprintf(os.Stderr, "Dump file path cannot be blank.") + os.Exit(1) + } + err := os.WriteFile(dumpPath, []byte(fmt.Sprintf("%d", os.Getppid())), 0644) + if err != nil { + fmt.Fprintf(os.Stderr, "Error writing dump file: %v", err) + os.Exit(2) + } + os.Exit(0) + } + + // run parent process + + parent := exec.Command(os.Args[0], "-test.run=TestChangingProcessParent") + parent.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=parent") + err := parent.Start() + if err != nil { + t.Fatal(err) + } + defer func() { + parent.Process.Kill() + parent.Wait() + }() + + // run child process + + const _PROCESS_CREATE_PROCESS = 0x0080 + const _PROCESS_DUP_HANDLE = 0x0040 + childDumpPath := filepath.Join(t.TempDir(), "ppid.txt") + ph, err := syscall.OpenProcess(_PROCESS_CREATE_PROCESS|_PROCESS_DUP_HANDLE|syscall.PROCESS_QUERY_INFORMATION, + false, uint32(parent.Process.Pid)) + if err != nil { + t.Fatal(err) + } + defer syscall.CloseHandle(ph) + + child := exec.Command(os.Args[0], "-test.run=TestChangingProcessParent") + child.Env = append(os.Environ(), + "GO_WANT_HELPER_PROCESS=child", + "GO_WANT_HELPER_PROCESS_FILE="+childDumpPath) + child.SysProcAttr = &syscall.SysProcAttr{ParentProcess: ph} + childOutput, err := child.CombinedOutput() + if err != nil { + t.Errorf("child failed: %v: %v", err, string(childOutput)) + } + childOutput, err = os.ReadFile(childDumpPath) + if err != nil { + t.Fatalf("reading child output failed: %v", err) + } + if got, want := string(childOutput), fmt.Sprintf("%d", parent.Process.Pid); got != want { + t.Fatalf("child output: want %q, got %q", want, got) + } +} diff --git a/libgo/go/syscall/export_test.go b/libgo/go/syscall/export_test.go deleted file mode 100644 index 55c09e6..0000000 --- a/libgo/go/syscall/export_test.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package syscall - -var Itoa = itoa diff --git a/libgo/go/syscall/export_unix_test.go b/libgo/go/syscall/export_unix_test.go index 1b78756..b051e36 100644 --- a/libgo/go/syscall/export_unix_test.go +++ b/libgo/go/syscall/export_unix_test.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build dragonfly freebsd hurd linux netbsd openbsd solaris +//go:build dragonfly || freebsd || hurd || linux || netbsd || openbsd +// +build dragonfly freebsd hurd linux netbsd openbsd package syscall diff --git a/libgo/go/syscall/export_windows_test.go b/libgo/go/syscall/export_windows_test.go new file mode 100644 index 0000000..a72a1ee --- /dev/null +++ b/libgo/go/syscall/export_windows_test.go @@ -0,0 +1,11 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package syscall + +var NewProcThreadAttributeList = newProcThreadAttributeList +var UpdateProcThreadAttribute = updateProcThreadAttribute +var DeleteProcThreadAttributeList = deleteProcThreadAttributeList + +const PROC_THREAD_ATTRIBUTE_HANDLE_LIST = _PROC_THREAD_ATTRIBUTE_HANDLE_LIST diff --git a/libgo/go/syscall/forkpipe.go b/libgo/go/syscall/forkpipe.go index d9999cb..79cbdf4 100644 --- a/libgo/go/syscall/forkpipe.go +++ b/libgo/go/syscall/forkpipe.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly solaris +//go:build aix || darwin || solaris +// +build aix darwin solaris package syscall diff --git a/libgo/go/syscall/forkpipe2.go b/libgo/go/syscall/forkpipe2.go index 747afd6..bdffdcd 100644 --- a/libgo/go/syscall/forkpipe2.go +++ b/libgo/go/syscall/forkpipe2.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build freebsd hurd netbsd openbsd +//go:build dragonfly || freebsd || hurd || netbsd || openbsd +// +build dragonfly freebsd hurd netbsd openbsd package syscall diff --git a/libgo/go/syscall/fs_js.go b/libgo/go/syscall/fs_js.go index 673feea..0170516 100644 --- a/libgo/go/syscall/fs_js.go +++ b/libgo/go/syscall/fs_js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package syscall diff --git a/libgo/go/syscall/getdirentries_test.go b/libgo/go/syscall/getdirentries_test.go index 66bb8ac..814e656 100644 --- a/libgo/go/syscall/getdirentries_test.go +++ b/libgo/go/syscall/getdirentries_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || freebsd || netbsd || openbsd // +build darwin freebsd netbsd openbsd package syscall_test @@ -28,11 +29,7 @@ func testGetdirentries(t *testing.T, count int) { if count > 100 && testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" { t.Skip("skipping in -short mode") } - d, err := os.MkdirTemp("", "getdirentries-test") - if err != nil { - t.Fatalf("Tempdir: %v", err) - } - defer os.RemoveAll(d) + d := t.TempDir() var names []string for i := 0; i < count; i++ { names = append(names, fmt.Sprintf("file%03d", i)) diff --git a/libgo/go/syscall/libcall_glibc.go b/libgo/go/syscall/libcall_glibc.go index a32d696..f021123 100644 --- a/libgo/go/syscall/libcall_glibc.go +++ b/libgo/go/syscall/libcall_glibc.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build hurd || linux // +build hurd linux // glibc library calls. @@ -9,6 +10,7 @@ package syscall import ( + "internal/itoa" "internal/race" "unsafe" ) @@ -28,7 +30,7 @@ func Futimesat(dirfd int, path string, tv []Timeval) (err error) { func Futimes(fd int, tv []Timeval) (err error) { // Believe it or not, this is the best we can do on GNU/Linux // (and is what glibc does). - return Utimes("/proc/self/fd/"+itoa(fd), tv) + return Utimes("/proc/self/fd/"+itoa.Itoa(fd), tv) } //sys accept4(fd int, sa *RawSockaddrAny, len *Socklen_t, flags int) (nfd int, err error) diff --git a/libgo/go/syscall/mkasm.go b/libgo/go/syscall/mkasm.go index 2ebaf8d..e0ec466 100644 --- a/libgo/go/syscall/mkasm.go +++ b/libgo/go/syscall/mkasm.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // mkasm.go generates assembly trampolines to call library routines from Go. diff --git a/libgo/go/syscall/mmap_unix_test.go b/libgo/go/syscall/mmap_unix_test.go index df179c2..f4eb54d 100644 --- a/libgo/go/syscall/mmap_unix_test.go +++ b/libgo/go/syscall/mmap_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd package syscall_test diff --git a/libgo/go/syscall/msan0.go b/libgo/go/syscall/msan0.go index ff10be9..8509702 100644 --- a/libgo/go/syscall/msan0.go +++ b/libgo/go/syscall/msan0.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !msan // +build !msan package syscall diff --git a/libgo/go/syscall/net_js.go b/libgo/go/syscall/net_js.go index 25f171b..ed46202 100644 --- a/libgo/go/syscall/net_js.go +++ b/libgo/go/syscall/net_js.go @@ -5,6 +5,7 @@ // js/wasm uses fake networking directly implemented in the net package. // This file only exists to make the compiler happy. +//go:build js && wasm // +build js,wasm package syscall diff --git a/libgo/go/syscall/route_bsd.go b/libgo/go/syscall/route_bsd.go index 0c32594..0dc5fc0 100644 --- a/libgo/go/syscall/route_bsd.go +++ b/libgo/go/syscall/route_bsd.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || netbsd || openbsd // +build darwin dragonfly freebsd netbsd openbsd package syscall diff --git a/libgo/go/syscall/route_freebsd_32bit.go b/libgo/go/syscall/route_freebsd_32bit.go index aed8682..412833a 100644 --- a/libgo/go/syscall/route_freebsd_32bit.go +++ b/libgo/go/syscall/route_freebsd_32bit.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (freebsd && 386) || (freebsd && arm) // +build freebsd,386 freebsd,arm package syscall diff --git a/libgo/go/syscall/route_freebsd_64bit.go b/libgo/go/syscall/route_freebsd_64bit.go index e70ba3d..5300bed 100644 --- a/libgo/go/syscall/route_freebsd_64bit.go +++ b/libgo/go/syscall/route_freebsd_64bit.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build (freebsd && amd64) || (freebsd && arm64) // +build freebsd,amd64 freebsd,arm64 package syscall diff --git a/libgo/go/syscall/setuidgid_32_linux.go b/libgo/go/syscall/setuidgid_32_linux.go index 1fe7120..4e657c8 100644 --- a/libgo/go/syscall/setuidgid_32_linux.go +++ b/libgo/go/syscall/setuidgid_32_linux.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux && (386 || arm) // +build linux // +build 386 arm diff --git a/libgo/go/syscall/setuidgid_linux.go b/libgo/go/syscall/setuidgid_linux.go index 22fa334..c15090f 100644 --- a/libgo/go/syscall/setuidgid_linux.go +++ b/libgo/go/syscall/setuidgid_linux.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux -// +build !386,!arm +//go:build linux && !386 && !arm +// +build linux,!386,!arm package syscall diff --git a/libgo/go/syscall/sockcmsg_unix.go b/libgo/go/syscall/sockcmsg_unix.go index 6530bea..aaeecdb 100644 --- a/libgo/go/syscall/sockcmsg_unix.go +++ b/libgo/go/syscall/sockcmsg_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris // Socket control messages diff --git a/libgo/go/syscall/sockcmsg_unix_other.go b/libgo/go/syscall/sockcmsg_unix_other.go index f5deeb4..0b75b18 100644 --- a/libgo/go/syscall/sockcmsg_unix_other.go +++ b/libgo/go/syscall/sockcmsg_unix_other.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin freebsd hurd linux netbsd openbsd solaris package syscall diff --git a/libgo/go/syscall/str.go b/libgo/go/syscall/str.go deleted file mode 100644 index 2ddf04b..0000000 --- a/libgo/go/syscall/str.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package syscall - -func itoa(val int) string { // do it here rather than with fmt to avoid dependency - if val < 0 { - return "-" + uitoa(uint(-val)) - } - return uitoa(uint(val)) -} - -func uitoa(val uint) string { - var buf [32]byte // big enough for int64 - i := len(buf) - 1 - for val >= 10 { - buf[i] = byte(val%10 + '0') - i-- - val /= 10 - } - buf[i] = byte(val + '0') - return string(buf[i:]) -} diff --git a/libgo/go/syscall/syscall_darwin.go b/libgo/go/syscall/syscall_darwin.go index 2847d2b..f732161 100644 --- a/libgo/go/syscall/syscall_darwin.go +++ b/libgo/go/syscall/syscall_darwin.go @@ -4,7 +4,10 @@ package syscall -import "unsafe" +import ( + "internal/abi" + "unsafe" +) func direntIno(buf []byte) (uint64, bool) { return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino)) diff --git a/libgo/go/syscall/syscall_freebsd_test.go b/libgo/go/syscall/syscall_freebsd_test.go index 3ccfe5d..89c7959 100644 --- a/libgo/go/syscall/syscall_freebsd_test.go +++ b/libgo/go/syscall/syscall_freebsd_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build freebsd // +build freebsd package syscall_test diff --git a/libgo/go/syscall/syscall_js.go b/libgo/go/syscall/syscall_js.go index 0ab8c3f..ed70d62 100644 --- a/libgo/go/syscall/syscall_js.go +++ b/libgo/go/syscall/syscall_js.go @@ -2,11 +2,13 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package syscall import ( + "internal/itoa" "internal/oserror" "sync" "unsafe" @@ -59,7 +61,7 @@ func (e Errno) Error() string { return s } } - return "errno " + itoa(int(e)) + return "errno " + itoa.Itoa(int(e)) } func (e Errno) Is(target error) bool { @@ -105,7 +107,7 @@ func (s Signal) String() string { return str } } - return "signal " + itoa(int(s)) + return "signal " + itoa.Itoa(int(s)) } var signals = [...]string{} diff --git a/libgo/go/syscall/syscall_linux_386.go b/libgo/go/syscall/syscall_linux_386.go index 5a9f6d9..5ad0772 100644 --- a/libgo/go/syscall/syscall_linux_386.go +++ b/libgo/go/syscall/syscall_linux_386.go @@ -20,6 +20,4 @@ func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) { return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs))) } -func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) { - panic("not implemented") -} +func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) diff --git a/libgo/go/syscall/syscall_linux_mipsx.go b/libgo/go/syscall/syscall_linux_mipsx.go index 1a15218..1df7a5f 100644 --- a/libgo/go/syscall/syscall_linux_mipsx.go +++ b/libgo/go/syscall/syscall_linux_mipsx.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux && (mips || mipsle || mips64 || mips64le || mips64p32 || mips64p32le) // +build linux // +build mips mipsle mips64 mips64le mips64p32 mips64p32le @@ -25,6 +26,4 @@ func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) { return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs))) } -func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) { - panic("not implemented") -} +func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) diff --git a/libgo/go/syscall/syscall_linux_test.go b/libgo/go/syscall/syscall_linux_test.go index 28b4eb4..fd826e9 100644 --- a/libgo/go/syscall/syscall_linux_test.go +++ b/libgo/go/syscall/syscall_linux_test.go @@ -14,6 +14,7 @@ import ( "os/signal" "path/filepath" "runtime" + "sort" "strconv" "strings" "syscall" @@ -587,11 +588,23 @@ func compareStatus(filter, expect string) error { // "Pid:\t". } if strings.HasPrefix(line, filter) { - if line != expected { - return fmt.Errorf("%q got:%q want:%q (bad) [pid=%d file:'%s' %v]\n", tf, line, expected, pid, string(d), expectedProc) + if line == expected { + foundAThread = true + break } - foundAThread = true - break + if filter == "Groups:" && strings.HasPrefix(line, "Groups:\t") { + // https://github.com/golang/go/issues/46145 + // Containers don't reliably output this line in sorted order so manually sort and compare that. + a := strings.Split(line[8:], " ") + sort.Strings(a) + got := strings.Join(a, " ") + if got == expected[8:] { + foundAThread = true + break + } + + } + return fmt.Errorf("%q got:%q want:%q (bad) [pid=%d file:'%s' %v]\n", tf, line, expected, pid, string(d), expectedProc) } } } diff --git a/libgo/go/syscall/syscall_ptrace_test.go b/libgo/go/syscall/syscall_ptrace_test.go index 6b7f54d..45729d9 100644 --- a/libgo/go/syscall/syscall_ptrace_test.go +++ b/libgo/go/syscall/syscall_ptrace_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd // +build darwin dragonfly freebsd linux netbsd openbsd package syscall_test diff --git a/libgo/go/syscall/syscall_test.go b/libgo/go/syscall/syscall_test.go index 5390f8a..b2b9463 100644 --- a/libgo/go/syscall/syscall_test.go +++ b/libgo/go/syscall/syscall_test.go @@ -5,7 +5,6 @@ package syscall_test import ( - "fmt" "internal/testenv" "os" "runtime" @@ -33,22 +32,6 @@ func TestEnv(t *testing.T) { testSetGetenv(t, "TESTENV", "") } -func TestItoa(t *testing.T) { - // Make most negative integer: 0x8000... - i := 1 - for i<<1 != 0 { - i <<= 1 - } - if i >= 0 { - t.Fatal("bad math") - } - s := syscall.Itoa(i) - f := fmt.Sprint(i) - if s != f { - t.Fatalf("itoa(%d) = %s, want %s", i, s, f) - } -} - // Check that permuting child process fds doesn't interfere with // reporting of fork/exec status. See Issue 14979. func TestExecErrPermutedFds(t *testing.T) { diff --git a/libgo/go/syscall/syscall_unix.go b/libgo/go/syscall/syscall_unix.go index db6b3aa..730cbfa 100644 --- a/libgo/go/syscall/syscall_unix.go +++ b/libgo/go/syscall/syscall_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris package syscall diff --git a/libgo/go/syscall/syscall_unix_test.go b/libgo/go/syscall/syscall_unix_test.go index e4b4171..d3d4673 100644 --- a/libgo/go/syscall/syscall_unix_test.go +++ b/libgo/go/syscall/syscall_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package syscall_test @@ -80,16 +81,12 @@ func TestFcntlFlock(t *testing.T) { } if os.Getenv("GO_WANT_HELPER_PROCESS") == "" { // parent - tempDir, err := os.MkdirTemp("", "TestFcntlFlock") - if err != nil { - t.Fatalf("Failed to create temp dir: %v", err) - } + tempDir := t.TempDir() name := filepath.Join(tempDir, "TestFcntlFlock") fd, err := syscall.Open(name, syscall.O_CREAT|syscall.O_RDWR|syscall.O_CLOEXEC, 0) if err != nil { t.Fatalf("Open failed: %v", err) } - defer os.RemoveAll(tempDir) defer syscall.Close(fd) if err := syscall.Ftruncate(fd, 1<<20); err != nil { t.Fatalf("Ftruncate(1<<20) failed: %v", err) @@ -158,18 +155,12 @@ func TestPassFD(t *testing.T) { } - tempDir, err := os.MkdirTemp("", "TestPassFD") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tempDir) + tempDir := t.TempDir() fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0) if err != nil { t.Fatalf("Socketpair: %v", err) } - defer syscall.Close(fds[0]) - defer syscall.Close(fds[1]) writeFile := os.NewFile(uintptr(fds[0]), "child-writes") readFile := os.NewFile(uintptr(fds[1]), "parent-reads") defer writeFile.Close() diff --git a/libgo/go/syscall/tables_js.go b/libgo/go/syscall/tables_js.go index a7c4f8c..64d9584 100644 --- a/libgo/go/syscall/tables_js.go +++ b/libgo/go/syscall/tables_js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package syscall diff --git a/libgo/go/syscall/time_fake.go b/libgo/go/syscall/time_fake.go index 5dec57a..cf88aeb 100644 --- a/libgo/go/syscall/time_fake.go +++ b/libgo/go/syscall/time_fake.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build faketime // +build faketime package syscall diff --git a/libgo/go/syscall/time_nofake.go b/libgo/go/syscall/time_nofake.go index c94cef8..5eaa2da 100644 --- a/libgo/go/syscall/time_nofake.go +++ b/libgo/go/syscall/time_nofake.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !faketime // +build !faketime package syscall diff --git a/libgo/go/syscall/timestruct.go b/libgo/go/syscall/timestruct.go index 42a743e..f22c282 100644 --- a/libgo/go/syscall/timestruct.go +++ b/libgo/go/syscall/timestruct.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package syscall diff --git a/libgo/go/syscall/types_windows_arm64.go b/libgo/go/syscall/types_windows_arm64.go new file mode 100644 index 0000000..7d45ddb --- /dev/null +++ b/libgo/go/syscall/types_windows_arm64.go @@ -0,0 +1,22 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package syscall + +type WSAData struct { + Version uint16 + HighVersion uint16 + MaxSockets uint16 + MaxUdpDg uint16 + VendorInfo *byte + Description [WSADESCRIPTION_LEN + 1]byte + SystemStatus [WSASYS_STATUS_LEN + 1]byte +} + +type Servent struct { + Name *byte + Aliases **byte + Proto *byte + Port uint16 +} diff --git a/libgo/go/testing/benchmark.go b/libgo/go/testing/benchmark.go index a8f75e9..15b4426 100644 --- a/libgo/go/testing/benchmark.go +++ b/libgo/go/testing/benchmark.go @@ -238,12 +238,15 @@ func (b *B) run1() bool { } // Only print the output if we know we are not going to proceed. // Otherwise it is printed in processBench. - if atomic.LoadInt32(&b.hasSub) != 0 || b.finished { + b.mu.RLock() + finished := b.finished + b.mu.RUnlock() + if atomic.LoadInt32(&b.hasSub) != 0 || finished { tag := "BENCH" if b.skipped { tag = "SKIP" } - if b.chatty != nil && (len(b.output) > 0 || b.finished) { + if b.chatty != nil && (len(b.output) > 0 || finished) { b.trimOutput() fmt.Fprintf(b.w, "--- %s: %s\n%s", tag, b.name, b.output) } diff --git a/libgo/go/testing/benchmark_test.go b/libgo/go/testing/benchmark_test.go index 4c1cbd1..3b1dc82 100644 --- a/libgo/go/testing/benchmark_test.go +++ b/libgo/go/testing/benchmark_test.go @@ -102,6 +102,30 @@ func TestRunParallelFail(t *testing.T) { }) } +func TestRunParallelFatal(t *testing.T) { + testing.Benchmark(func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + if b.N > 1 { + b.Fatal("error") + } + } + }) + }) +} + +func TestRunParallelSkipNow(t *testing.T) { + testing.Benchmark(func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + if b.N > 1 { + b.SkipNow() + } + } + }) + }) +} + func ExampleB_RunParallel() { // Parallel benchmark for text/template.Template.Execute on a single object. testing.Benchmark(func(b *testing.B) { diff --git a/libgo/go/testing/fstest/mapfs.go b/libgo/go/testing/fstest/mapfs.go index a5d4a23fa..9fef2f4 100644 --- a/libgo/go/testing/fstest/mapfs.go +++ b/libgo/go/testing/fstest/mapfs.go @@ -223,12 +223,12 @@ func (d *mapDir) Read(b []byte) (int, error) { func (d *mapDir) ReadDir(count int) ([]fs.DirEntry, error) { n := len(d.entry) - d.offset - if count > 0 && n > count { - n = count - } if n == 0 && count > 0 { return nil, io.EOF } + if count > 0 && n > count { + n = count + } list := make([]fs.DirEntry, n) for i := range list { list[i] = &d.entry[d.offset+i] diff --git a/libgo/go/testing/fstest/testfs.go b/libgo/go/testing/fstest/testfs.go index 8fc8aca..5c4f30a 100644 --- a/libgo/go/testing/fstest/testfs.go +++ b/libgo/go/testing/fstest/testfs.go @@ -10,7 +10,6 @@ import ( "fmt" "io" "io/fs" - "io/ioutil" "path" "reflect" "sort" @@ -23,7 +22,7 @@ import ( // opening and checking that each file behaves correctly. // It also checks that the file system contains at least the expected files. // As a special case, if no expected files are listed, fsys must be empty. -// Otherwise, fsys must only contain at least the listed files: it can also contain others. +// Otherwise, fsys must contain at least the listed files; it can also contain others. // The contents of fsys must not change concurrently with TestFS. // // If TestFS finds any misbehaviors, it returns an error reporting all of them. @@ -303,7 +302,7 @@ func (t *fsTester) checkGlob(dir string, list []fs.DirEntry) { for i, e := range elem { var pattern []rune for j, r := range e { - if r == '*' || r == '?' || r == '\\' || r == '[' { + if r == '*' || r == '?' || r == '\\' || r == '[' || r == '-' { pattern = append(pattern, '\\', r) continue } @@ -514,7 +513,7 @@ func (t *fsTester) checkFile(file string) { return } - data, err := ioutil.ReadAll(f) + data, err := io.ReadAll(f) if err != nil { f.Close() t.errorf("%s: Open+ReadAll: %v", file, err) @@ -538,6 +537,18 @@ func (t *fsTester) checkFile(file string) { } t.checkFileRead(file, "ReadAll vs fsys.ReadFile", data, data2) + // Modify the data and check it again. Modifying the + // returned byte slice should not affect the next call. + for i := range data2 { + data2[i]++ + } + data2, err = fsys.ReadFile(file) + if err != nil { + t.errorf("%s: second call to fsys.ReadFile: %v", file, err) + return + } + t.checkFileRead(file, "Readall vs second fsys.ReadFile", data, data2) + t.checkBadPath(file, "ReadFile", func(name string) error { _, err := fsys.ReadFile(name); return err }) } diff --git a/libgo/go/testing/fstest/testfs_test.go b/libgo/go/testing/fstest/testfs_test.go index 5b8813c..aefb4b3 100644 --- a/libgo/go/testing/fstest/testfs_test.go +++ b/libgo/go/testing/fstest/testfs_test.go @@ -29,3 +29,12 @@ func TestSymlink(t *testing.T) { t.Fatal(err) } } + +func TestDash(t *testing.T) { + m := MapFS{ + "a-b/a": {Data: []byte("a-b/a")}, + } + if err := TestFS(m, "a-b/a"); err != nil { + t.Error(err) + } +} diff --git a/libgo/go/testing/run_example.go b/libgo/go/testing/run_example.go index 4dc83f7..d9e342d 100644 --- a/libgo/go/testing/run_example.go +++ b/libgo/go/testing/run_example.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js // TODO(@musiol, @odeke-em): re-unify this entire file back into diff --git a/libgo/go/testing/run_example_js.go b/libgo/go/testing/run_example_js.go index 1d4164b..d914633 100644 --- a/libgo/go/testing/run_example_js.go +++ b/libgo/go/testing/run_example_js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js // +build js package testing diff --git a/libgo/go/testing/sub_test.go b/libgo/go/testing/sub_test.go index 5b226f8..6c7d83a 100644 --- a/libgo/go/testing/sub_test.go +++ b/libgo/go/testing/sub_test.go @@ -822,7 +822,7 @@ func TestLogAfterComplete(t *T) { c2 <- fmt.Sprintf("subtest panic with unexpected value %v", p) return } - const want = "Log in goroutine after TestLateLog has completed" + const want = "Log in goroutine after TestLateLog has completed: log after test" if !strings.Contains(s, want) { c2 <- fmt.Sprintf("subtest panic %q does not contain %q", s, want) } diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go index 143d81c..4c823dc 100644 --- a/libgo/go/testing/testing.go +++ b/libgo/go/testing/testing.go @@ -190,7 +190,7 @@ // } // } // -// The race detector kills the program if it exceeds 8192 concurrent goroutines, +// The race detector kills the program if it exceeds 8128 concurrent goroutines, // so use care when running parallel tests with the -race flag set. // // Run does not return until parallel subtests have completed, providing a way @@ -208,14 +208,14 @@ // // Main // -// It is sometimes necessary for a test program to do extra setup or teardown -// before or after testing. It is also sometimes necessary for a test to control +// It is sometimes necessary for a test or benchmark program to do extra setup or teardown +// before or after it executes. It is also sometimes necessary to control // which code runs on the main thread. To support these and other cases, // if a test file contains a function: // // func TestMain(m *testing.M) // -// then the generated test will call TestMain(m) instead of running the tests +// then the generated test will call TestMain(m) instead of running the tests or benchmarks // directly. TestMain runs in the main goroutine and can do whatever setup // and teardown is necessary around a call to m.Run. m.Run will return an exit // code that may be passed to os.Exit. If TestMain returns, the test wrapper @@ -233,6 +233,8 @@ // os.Exit(m.Run()) // } // +// TestMain is a low-level primitive and should not be necessary for casual +// testing needs, where ordinary test functions suffice. package testing import ( @@ -242,6 +244,7 @@ import ( "fmt" "internal/race" "io" + "math/rand" "os" "runtime" "runtime/debug" @@ -251,6 +254,8 @@ import ( "sync" "sync/atomic" "time" + "unicode" + "unicode/utf8" ) var initRan bool @@ -299,6 +304,7 @@ func Init() { cpuListStr = flag.String("test.cpu", "", "comma-separated `list` of cpu counts to run each test with") parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "run at most `n` tests in parallel") testlog = flag.String("test.testlogfile", "", "write test action log to `file` (for use only by cmd/go)") + shuffle = flag.String("test.shuffle", "off", "randomize the execution order of tests and benchmarks") initBenchmarkFlags() } @@ -325,6 +331,7 @@ var ( timeout *time.Duration cpuListStr *string parallel *int + shuffle *string testlog *string haveExamples bool // are there examples? @@ -388,17 +395,17 @@ type common struct { w io.Writer // For flushToParent. ran bool // Test or benchmark (or one of its subtests) was executed. failed bool // Test or benchmark has failed. - skipped bool // Test of benchmark has been skipped. + skipped bool // Test or benchmark has been skipped. done bool // Test is finished and all subtests have completed. helperPCs map[uintptr]struct{} // functions to be skipped when writing file/line info helperNames map[string]struct{} // helperPCs converted to function names cleanups []func() // optional functions to be called at the end of the test cleanupName string // Name of the cleanup function. cleanupPc []uintptr // The stack trace at the point where Cleanup was called. + finished bool // Test function has completed. chatty *chattyPrinter // A copy of chattyPrinter, if the chatty flag is set. bench bool // Whether the current test is a benchmark. - finished bool // Test function has completed. hasSub int32 // Written atomically. raceErrors int // Number of races detected during test. runner string // Function name of tRunner running the test. @@ -639,6 +646,7 @@ type TB interface { Log(args ...interface{}) Logf(format string, args ...interface{}) Name() string + Setenv(key, value string) Skip(args ...interface{}) SkipNow() Skipf(format string, args ...interface{}) @@ -666,12 +674,17 @@ var _ TB = (*B)(nil) type T struct { common isParallel bool + isEnvSet bool context *testContext // For running tests and subtests. } func (c *common) private() {} -// Name returns the name of the running test or benchmark. +// Name returns the name of the running (sub-) test or benchmark. +// +// The name will include the name of the test along with the names of +// any nested sub-tests. If two sibling sub-tests have the same name, +// Name will append a suffix to guarantee the returned name is unique. func (c *common) Name() string { return c.name } @@ -737,7 +750,9 @@ func (c *common) FailNow() { // it would run on a test failure. Because we send on c.signal during // a top-of-stack deferred function now, we know that the send // only happens after any other stacked defers have completed. + c.mu.Lock() c.finished = true + c.mu.Unlock() runtime.Goexit() } @@ -761,7 +776,7 @@ func (c *common) logDepth(s string, depth int) { return } } - panic("Log in goroutine after " + c.name + " has completed") + panic("Log in goroutine after " + c.name + " has completed: " + s) } else { if c.chatty != nil { if c.bench { @@ -872,15 +887,11 @@ func (c *common) Skipf(format string, args ...interface{}) { // other goroutines created during the test. Calling SkipNow does not stop // those other goroutines. func (c *common) SkipNow() { - c.skip() - c.finished = true - runtime.Goexit() -} - -func (c *common) skip() { c.mu.Lock() - defer c.mu.Unlock() c.skipped = true + c.finished = true + c.mu.Unlock() + runtime.Goexit() } // Skipped reports whether the test was skipped. @@ -911,7 +922,7 @@ func (c *common) Helper() { } } -// Cleanup registers a function to be called when the test and all its +// Cleanup registers a function to be called when the test (or subtest) and all its // subtests complete. Cleanup functions will be called in last added, // first called order. func (c *common) Cleanup(f func()) { @@ -942,11 +953,6 @@ func (c *common) Cleanup(f func()) { c.cleanups = append(c.cleanups, fn) } -var tempDirReplacer struct { - sync.Once - r *strings.Replacer -} - // TempDir returns a temporary directory for the test to use. // The directory is automatically removed by Cleanup when the test and // all its subtests complete. @@ -970,13 +976,26 @@ func (c *common) TempDir() string { if nonExistent { c.Helper() - // os.MkdirTemp doesn't like path separators in its pattern, - // so mangle the name to accommodate subtests. - tempDirReplacer.Do(func() { - tempDirReplacer.r = strings.NewReplacer("/", "_", "\\", "_", ":", "_") - }) - pattern := tempDirReplacer.r.Replace(c.Name()) - + // Drop unusual characters (such as path separators or + // characters interacting with globs) from the directory name to + // avoid surprising os.MkdirTemp behavior. + mapper := func(r rune) rune { + if r < utf8.RuneSelf { + const allowed = "!#$%&()+,-.=@^_{}~ " + if '0' <= r && r <= '9' || + 'a' <= r && r <= 'z' || + 'A' <= r && r <= 'Z' { + return r + } + if strings.ContainsRune(allowed, r) { + return r + } + } else if unicode.IsLetter(r) || unicode.IsNumber(r) { + return r + } + return -1 + } + pattern := strings.Map(mapper, c.Name()) c.tempDir, c.tempDirErr = os.MkdirTemp("", pattern) if c.tempDirErr == nil { c.Cleanup(func() { @@ -999,6 +1018,29 @@ func (c *common) TempDir() string { return dir } +// Setenv calls os.Setenv(key, value) and uses Cleanup to +// restore the environment variable to its original value +// after the test. +// +// This cannot be used in parallel tests. +func (c *common) Setenv(key, value string) { + prevValue, ok := os.LookupEnv(key) + + if err := os.Setenv(key, value); err != nil { + c.Fatalf("cannot set environment variable: %v", err) + } + + if ok { + c.Cleanup(func() { + os.Setenv(key, prevValue) + }) + } else { + c.Cleanup(func() { + os.Unsetenv(key) + }) + } +} + // panicHanding is an argument to runCleanup. type panicHandling int @@ -1070,6 +1112,9 @@ func (t *T) Parallel() { if t.isParallel { panic("testing: t.Parallel called multiple times") } + if t.isEnvSet { + panic("testing: t.Parallel called after t.Setenv; cannot set environment variables in parallel tests") + } t.isParallel = true // We don't want to include the time we spend waiting for serial tests @@ -1103,6 +1148,21 @@ func (t *T) Parallel() { t.raceErrors += -race.Errors() } +// Setenv calls os.Setenv(key, value) and uses Cleanup to +// restore the environment variable to its original value +// after the test. +// +// This cannot be used in parallel tests. +func (t *T) Setenv(key, value string) { + if t.isParallel { + panic("testing: t.Setenv called after t.Parallel; cannot set environment variables in parallel tests") + } + + t.isEnvSet = true + + t.common.Setenv(key, value) +} + // InternalTest is an internal type but exported because it is cross-package; // it is part of the implementation of the "go test" command. type InternalTest struct { @@ -1132,10 +1192,16 @@ func tRunner(t *T, fn func(t *T)) { err := recover() signal := true - if !t.finished && err == nil { + t.mu.RLock() + finished := t.finished + t.mu.RUnlock() + if !finished && err == nil { err = errNilPanicOrGoexit for p := t.parent; p != nil; p = p.parent { - if p.finished { + p.mu.RLock() + finished = p.finished + p.mu.RUnlock() + if finished { t.Errorf("%v: subtest may have called FailNow on a parent test", err) err = nil signal = false @@ -1229,7 +1295,9 @@ func tRunner(t *T, fn func(t *T)) { fn(t) // code beyond here will not be executed when FailNow is invoked + t.mu.Lock() t.finished = true + t.mu.Unlock() } // Run runs f as a subtest of t called name. It runs f in a separate goroutine @@ -1252,7 +1320,7 @@ func (t *T) Run(name string, f func(t *T)) bool { t = &T{ common: common{ barrier: make(chan bool), - signal: make(chan bool), + signal: make(chan bool, 1), name: testName, parent: &t.common, level: t.level + 1, @@ -1444,6 +1512,25 @@ func (m *M) Run() (code int) { return } + if *shuffle != "off" { + var n int64 + var err error + if *shuffle == "on" { + n = time.Now().UnixNano() + } else { + n, err = strconv.ParseInt(*shuffle, 10, 64) + if err != nil { + fmt.Fprintln(os.Stderr, `testing: -shuffle should be "off", "on", or a valid integer:`, err) + m.exitCode = 2 + return + } + } + fmt.Println("-test.shuffle", n) + rng := rand.New(rand.NewSource(n)) + rng.Shuffle(len(m.tests), func(i, j int) { m.tests[i], m.tests[j] = m.tests[j], m.tests[i] }) + rng.Shuffle(len(m.benchmarks), func(i, j int) { m.benchmarks[i], m.benchmarks[j] = m.benchmarks[j], m.benchmarks[i] }) + } + parseCpuList() m.before() @@ -1533,7 +1620,7 @@ func runTests(matchString func(pat, str string) (bool, error), tests []InternalT ctx.deadline = deadline t := &T{ common: common{ - signal: make(chan bool), + signal: make(chan bool, 1), barrier: make(chan bool), w: os.Stdout, }, @@ -1546,11 +1633,12 @@ func runTests(matchString func(pat, str string) (bool, error), tests []InternalT for _, test := range tests { t.Run(test.Name, test.F) } - // Run catching the signal rather than the tRunner as a separate - // goroutine to avoid adding a goroutine during the sequential - // phase as this pollutes the stacktrace output when aborting. - go func() { <-t.signal }() }) + select { + case <-t.signal: + default: + panic("internal error: tRunner exited without sending on t.signal") + } ok = ok && !t.Failed() ran = ran || t.ran } diff --git a/libgo/go/testing/testing_test.go b/libgo/go/testing/testing_test.go index 0f09698..08ae239 100644 --- a/libgo/go/testing/testing_test.go +++ b/libgo/go/testing/testing_test.go @@ -58,6 +58,9 @@ func TestTempDir(t *testing.T) { t.Run("test:subtest", testTempDir) t.Run("test/..", testTempDir) t.Run("../test", testTempDir) + t.Run("test[]", testTempDir) + t.Run("test*", testTempDir) + t.Run("äöüéè", testTempDir) } func testTempDir(t *testing.T) { @@ -74,7 +77,7 @@ func testTempDir(t *testing.T) { if err != nil { t.Fatal(err) } - t.Errorf("directory %q stil exists: %v, isDir=%v", dir, fi, fi.IsDir()) + t.Errorf("directory %q still exists: %v, isDir=%v", dir, fi, fi.IsDir()) default: if !t.Failed() { t.Fatal("never received dir channel") @@ -108,4 +111,92 @@ func testTempDir(t *testing.T) { if len(files) > 0 { t.Errorf("unexpected %d files in TempDir: %v", len(files), files) } + + glob := filepath.Join(dir, "*.txt") + if _, err := filepath.Glob(glob); err != nil { + t.Error(err) + } +} + +func TestSetenv(t *testing.T) { + tests := []struct { + name string + key string + initialValueExists bool + initialValue string + newValue string + }{ + { + name: "initial value exists", + key: "GO_TEST_KEY_1", + initialValueExists: true, + initialValue: "111", + newValue: "222", + }, + { + name: "initial value exists but empty", + key: "GO_TEST_KEY_2", + initialValueExists: true, + initialValue: "", + newValue: "222", + }, + { + name: "initial value is not exists", + key: "GO_TEST_KEY_3", + initialValueExists: false, + initialValue: "", + newValue: "222", + }, + } + + for _, test := range tests { + if test.initialValueExists { + if err := os.Setenv(test.key, test.initialValue); err != nil { + t.Fatalf("unable to set env: got %v", err) + } + } else { + os.Unsetenv(test.key) + } + + t.Run(test.name, func(t *testing.T) { + t.Setenv(test.key, test.newValue) + if os.Getenv(test.key) != test.newValue { + t.Fatalf("unexpected value after t.Setenv: got %s, want %s", os.Getenv(test.key), test.newValue) + } + }) + + got, exists := os.LookupEnv(test.key) + if got != test.initialValue { + t.Fatalf("unexpected value after t.Setenv cleanup: got %s, want %s", got, test.initialValue) + } + if exists != test.initialValueExists { + t.Fatalf("unexpected value after t.Setenv cleanup: got %t, want %t", exists, test.initialValueExists) + } + } +} + +func TestSetenvWithParallelAfterSetenv(t *testing.T) { + defer func() { + want := "testing: t.Parallel called after t.Setenv; cannot set environment variables in parallel tests" + if got := recover(); got != want { + t.Fatalf("expected panic; got %#v want %q", got, want) + } + }() + + t.Setenv("GO_TEST_KEY_1", "value") + + t.Parallel() +} + +func TestSetenvWithParallelBeforeSetenv(t *testing.T) { + defer func() { + want := "testing: t.Setenv called after t.Parallel; cannot set environment variables in parallel tests" + if got := recover(); got != want { + t.Fatalf("expected panic; got %#v want %q", got, want) + } + }() + + t.Parallel() + + t.Setenv("GO_TEST_KEY_1", "value") } diff --git a/libgo/go/text/scanner/scanner.go b/libgo/go/text/scanner/scanner.go index e0847a7..c5fc4ff 100644 --- a/libgo/go/text/scanner/scanner.go +++ b/libgo/go/text/scanner/scanner.go @@ -23,7 +23,7 @@ import ( "unicode/utf8" ) -// A source position is represented by a Position value. +// Position is a value that represents a source position. // A position is valid if Line > 0. type Position struct { Filename string // filename, if any diff --git a/libgo/go/text/template/exec.go b/libgo/go/text/template/exec.go index ab84805..545820d 100644 --- a/libgo/go/text/template/exec.go +++ b/libgo/go/text/template/exec.go @@ -181,10 +181,7 @@ func errRecover(errp *error) { // A template may be executed safely in parallel, although if parallel // executions share a Writer the output may be interleaved. func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error { - var tmpl *Template - if t.common != nil { - tmpl = t.tmpl[name] - } + tmpl := t.Lookup(name) if tmpl == nil { return fmt.Errorf("template: no template %q associated with template %q", name, t.name) } @@ -232,6 +229,8 @@ func (t *Template) DefinedTemplates() string { return "" } var b strings.Builder + t.muTmpl.RLock() + defer t.muTmpl.RUnlock() for name, tmpl := range t.tmpl { if tmpl.Tree == nil || tmpl.Root == nil { continue @@ -403,7 +402,7 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) { func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) { s.at(t) - tmpl := s.tmpl.tmpl[t.Name] + tmpl := s.tmpl.Lookup(t.Name) if tmpl == nil { s.errorf("template %q not defined", t.Name) } @@ -617,7 +616,7 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, tField, ok := receiver.Type().FieldByName(fieldName) if ok { field := receiver.FieldByIndex(tField.Index) - if tField.PkgPath != "" { // field is unexported + if !tField.IsExported() { s.errorf("%s is an unexported field of struct type %s", fieldName, typ) } // If it's a function, we must call it. @@ -729,7 +728,7 @@ func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, a // error to the caller. if err != nil { s.at(node) - s.errorf("error calling %s: %v", name, err) + s.errorf("error calling %s: %w", name, err) } if v.Type() == reflectValueType { v = v.Interface().(reflect.Value) diff --git a/libgo/go/text/template/exec_test.go b/libgo/go/text/template/exec_test.go index c821c05..d64f690 100644 --- a/libgo/go/text/template/exec_test.go +++ b/libgo/go/text/template/exec_test.go @@ -12,6 +12,7 @@ import ( "io" "reflect" "strings" + "sync" "testing" ) @@ -902,6 +903,28 @@ func TestExecError(t *testing.T) { } } +type CustomError struct{} + +func (*CustomError) Error() string { return "heyo !" } + +// Check that a custom error can be returned. +func TestExecError_CustomError(t *testing.T) { + failingFunc := func() (string, error) { + return "", &CustomError{} + } + tmpl := Must(New("top").Funcs(FuncMap{ + "err": failingFunc, + }).Parse("{{ err }}")) + + var b bytes.Buffer + err := tmpl.Execute(&b, nil) + + var e *CustomError + if !errors.As(err, &e) { + t.Fatalf("expected custom error; got %s", err) + } +} + func TestJSEscaping(t *testing.T) { testCases := []struct { in, exp string @@ -1178,8 +1201,11 @@ var cmpTests = []cmpTest{ {"eq .Ptr .NilPtr", "false", true}, {"eq .NilPtr .NilPtr", "true", true}, {"eq .Iface1 .Iface1", "true", true}, - {"eq .Iface1 .Iface2", "false", true}, - {"eq .Iface2 .Iface2", "true", true}, + {"eq .Iface1 .NilIface", "false", true}, + {"eq .NilIface .NilIface", "true", true}, + {"eq .NilIface .Iface1", "false", true}, + {"eq .NilIface 0", "false", true}, + {"eq 0 .NilIface", "false", true}, // Errors {"eq `xy` 1", "", false}, // Different types. {"eq 2 2.0", "", false}, // Different types. @@ -1194,12 +1220,12 @@ var cmpTests = []cmpTest{ func TestComparison(t *testing.T) { b := new(bytes.Buffer) var cmpStruct = struct { - Uthree, Ufour uint - NegOne, Three int - Ptr, NilPtr *int - Map map[int]int - V1, V2 V - Iface1, Iface2 fmt.Stringer + Uthree, Ufour uint + NegOne, Three int + Ptr, NilPtr *int + Map map[int]int + V1, V2 V + Iface1, NilIface fmt.Stringer }{ Uthree: 3, Ufour: 4, @@ -1710,3 +1736,40 @@ func TestIssue43065(t *testing.T) { t.Errorf("%s", err) } } + +// Issue 39807: data race in html/template & text/template +func TestIssue39807(t *testing.T) { + var wg sync.WaitGroup + + tplFoo, err := New("foo").Parse(`{{ template "bar" . }}`) + if err != nil { + t.Error(err) + } + + tplBar, err := New("bar").Parse("bar") + if err != nil { + t.Error(err) + } + + gofuncs := 10 + numTemplates := 10 + + for i := 1; i <= gofuncs; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for j := 0; j < numTemplates; j++ { + _, err := tplFoo.AddParseTree(tplBar.Name(), tplBar.Tree) + if err != nil { + t.Error(err) + } + err = tplFoo.Execute(io.Discard, nil) + if err != nil { + t.Error(err) + } + } + }() + } + + wg.Wait() +} diff --git a/libgo/go/text/template/funcs.go b/libgo/go/text/template/funcs.go index 1b6940a..fff833e 100644 --- a/libgo/go/text/template/funcs.go +++ b/libgo/go/text/template/funcs.go @@ -23,6 +23,9 @@ import ( // return value evaluates to non-nil during execution, execution terminates and // Execute returns that error. // +// Errors returned by Execute wrap the underlying error; call errors.As to +// uncover them. +// // When template execution invokes a function with an argument list, that list // must be assignable to the function's parameter types. Functions meant to // apply to arguments of arbitrary type can use parameters of type interface{} or @@ -344,7 +347,7 @@ func call(fn reflect.Value, args ...reflect.Value) (reflect.Value, error) { var err error if argv[i], err = prepareArg(arg, argType); err != nil { - return reflect.Value{}, fmt.Errorf("arg %d: %s", i, err) + return reflect.Value{}, fmt.Errorf("arg %d: %w", i, err) } } return safeCall(fn, argv) @@ -475,7 +478,9 @@ func eq(arg1 reflect.Value, arg2 ...reflect.Value) (bool, error) { case k1 == uintKind && k2 == intKind: truth = arg.Int() >= 0 && arg1.Uint() == uint64(arg.Int()) default: - return false, errBadComparison + if arg1 != zero && arg != zero { + return false, errBadComparison + } } } else { switch k1 { @@ -492,7 +497,7 @@ func eq(arg1 reflect.Value, arg2 ...reflect.Value) (bool, error) { case uintKind: truth = arg1.Uint() == arg.Uint() default: - if arg == zero { + if arg == zero || arg1 == zero { truth = arg1 == arg } else { if t2 := arg.Type(); !t2.Comparable() { diff --git a/libgo/go/text/template/link_test.go b/libgo/go/text/template/link_test.go index 9dc70df..e1d3136 100644 --- a/libgo/go/text/template/link_test.go +++ b/libgo/go/text/template/link_test.go @@ -39,11 +39,7 @@ func main() { t.Used() } ` - td, err := os.MkdirTemp("", "text_template_TestDeadCodeElimination") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(td) + td := t.TempDir() if err := os.WriteFile(filepath.Join(td, "x.go"), []byte(prog), 0644); err != nil { t.Fatal(err) diff --git a/libgo/go/text/template/parse/parse.go b/libgo/go/text/template/parse/parse.go index 5e6e512..1a63961 100644 --- a/libgo/go/text/template/parse/parse.go +++ b/libgo/go/text/template/parse/parse.go @@ -39,6 +39,7 @@ type Mode uint const ( ParseComments Mode = 1 << iota // parse comments and add them to AST + SkipFuncCheck // do not check that functions are defined ) // Copy returns a copy of the Tree. Any parsing state is discarded. @@ -689,7 +690,8 @@ func (t *Tree) operand() Node { func (t *Tree) term() Node { switch token := t.nextNonSpace(); token.typ { case itemIdentifier: - if !t.hasFunction(token.val) { + checkFunc := t.Mode&SkipFuncCheck == 0 + if checkFunc && !t.hasFunction(token.val) { t.errorf("function %q not defined", token.val) } return NewIdentifier(token.val).SetTree(t).SetPos(token.pos) diff --git a/libgo/go/text/template/parse/parse_test.go b/libgo/go/text/template/parse/parse_test.go index 220f984..9b1be27 100644 --- a/libgo/go/text/template/parse/parse_test.go +++ b/libgo/go/text/template/parse/parse_test.go @@ -379,6 +379,22 @@ func TestParseWithComments(t *testing.T) { } } +func TestSkipFuncCheck(t *testing.T) { + oldTextFormat := textFormat + textFormat = "%q" + defer func() { textFormat = oldTextFormat }() + tr := New("skip func check") + tr.Mode = SkipFuncCheck + tmpl, err := tr.Parse("{{fn 1 2}}", "", "", make(map[string]*Tree)) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + expected := "{{fn 1 2}}" + if result := tmpl.Root.String(); result != expected { + t.Errorf("got\n\t%v\nexpected\n\t%v", result, expected) + } +} + type isEmptyTest struct { name string input string diff --git a/libgo/go/text/template/template.go b/libgo/go/text/template/template.go index ec26eb4..fd74d45 100644 --- a/libgo/go/text/template/template.go +++ b/libgo/go/text/template/template.go @@ -13,6 +13,7 @@ import ( // common holds the information shared by related templates. type common struct { tmpl map[string]*Template // Map from name to defined templates. + muTmpl sync.RWMutex // protects tmpl option option // We use two maps, one for parsing and one for execution. // This separation makes the API cleaner since it doesn't @@ -88,6 +89,8 @@ func (t *Template) Clone() (*Template, error) { if t.common == nil { return nt, nil } + t.muTmpl.RLock() + defer t.muTmpl.RUnlock() for k, v := range t.tmpl { if k == t.name { nt.tmpl[t.name] = nt @@ -124,6 +127,8 @@ func (t *Template) copy(c *common) *Template { // its definition. If it has been defined and already has that name, the existing // definition is replaced; otherwise a new template is created, defined, and returned. func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) { + t.muTmpl.Lock() + defer t.muTmpl.Unlock() t.init() nt := t if name != t.name { @@ -142,6 +147,8 @@ func (t *Template) Templates() []*Template { return nil } // Return a slice so we don't expose the map. + t.muTmpl.RLock() + defer t.muTmpl.RUnlock() m := make([]*Template, 0, len(t.tmpl)) for _, v := range t.tmpl { m = append(m, v) @@ -182,6 +189,8 @@ func (t *Template) Lookup(name string) *Template { if t.common == nil { return nil } + t.muTmpl.RLock() + defer t.muTmpl.RUnlock() return t.tmpl[name] } diff --git a/libgo/go/time/embed.go b/libgo/go/time/embed.go index cb4fdac..34490c8 100644 --- a/libgo/go/time/embed.go +++ b/libgo/go/time/embed.go @@ -5,6 +5,7 @@ // This file is used with build tag timetzdata to embed tzdata into // the binary. +//go:build timetzdata // +build timetzdata package time diff --git a/libgo/go/time/export_test.go b/libgo/go/time/export_test.go index f4a8cd9..9baad60 100644 --- a/libgo/go/time/export_test.go +++ b/libgo/go/time/export_test.go @@ -51,6 +51,7 @@ const ( RuleJulian = RuleKind(ruleJulian) RuleDOY = RuleKind(ruleDOY) RuleMonthWeekDay = RuleKind(ruleMonthWeekDay) + UnixToInternal = unixToInternal ) type Rule struct { @@ -128,3 +129,5 @@ var StdChunkNames = map[int]string{ stdFracSecond9 | 8<<stdArgShift: ".99999999", stdFracSecond9 | 9<<stdArgShift: ".999999999", } + +var Quote = quote diff --git a/libgo/go/time/format.go b/libgo/go/time/format.go index f11fb7e..bb173a2 100644 --- a/libgo/go/time/format.go +++ b/libgo/go/time/format.go @@ -7,70 +7,89 @@ package time import "errors" // These are predefined layouts for use in Time.Format and time.Parse. -// The reference time used in the layouts is the specific time: -// Mon Jan 2 15:04:05 MST 2006 -// which is Unix time 1136239445. Since MST is GMT-0700, -// the reference time can be thought of as +// The reference time used in these layouts is the specific time stamp: // 01/02 03:04:05PM '06 -0700 -// To define your own format, write down what the reference time would look -// like formatted your way; see the values of constants like ANSIC, -// StampMicro or Kitchen for examples. The model is to demonstrate what the -// reference time looks like so that the Format and Parse methods can apply -// the same transformation to a general time value. +// (January 2, 15:04:05, 2006, in time zone seven hours west of GMT). +// That value is recorded as the constant named Layout, listed below. As a Unix +// time, this is 1136239445. Since MST is GMT-0700, the reference would be +// printed by the Unix date command as: +// Mon Jan 2 15:04:05 MST 2006 +// It is a regrettable historic error that the date uses the American convention +// of putting the numerical month before the day. // -// Some valid layouts are invalid time values for time.Parse, due to formats -// such as _ for space padding and Z for zone information. +// The example for Time.Format demonstrates the working of the layout string +// in detail and is a good reference. // -// Within the format string, an underscore _ represents a space that may be -// replaced by a digit if the following number (a day) has two digits; for -// compatibility with fixed-width Unix time formats. +// Note that the RFC822, RFC850, and RFC1123 formats should be applied +// only to local times. Applying them to UTC times will use "UTC" as the +// time zone abbreviation, while strictly speaking those RFCs require the +// use of "GMT" in that case. +// In general RFC1123Z should be used instead of RFC1123 for servers +// that insist on that format, and RFC3339 should be preferred for new protocols. +// RFC3339, RFC822, RFC822Z, RFC1123, and RFC1123Z are useful for formatting; +// when used with time.Parse they do not accept all the time formats +// permitted by the RFCs and they do accept time formats not formally defined. +// The RFC3339Nano format removes trailing zeros from the seconds field +// and thus may not sort correctly once formatted. // -// A decimal point followed by one or more zeros represents a fractional -// second, printed to the given number of decimal places. A decimal point -// followed by one or more nines represents a fractional second, printed to -// the given number of decimal places, with trailing zeros removed. -// When parsing (only), the input may contain a fractional second -// field immediately after the seconds field, even if the layout does not -// signify its presence. In that case a decimal point followed by a maximal -// series of digits is parsed as a fractional second. +// Most programs can use one of the defined constants as the layout passed to +// Format or Parse. The rest of this comment can be ignored unless you are +// creating a custom layout string. +// +// To define your own format, write down what the reference time would look like +// formatted your way; see the values of constants like ANSIC, StampMicro or +// Kitchen for examples. The model is to demonstrate what the reference time +// looks like so that the Format and Parse methods can apply the same +// transformation to a general time value. +// +// Here is a summary of the components of a layout string. Each element shows by +// example the formatting of an element of the reference time. Only these values +// are recognized. Text in the layout string that is not recognized as part of +// the reference time is echoed verbatim during Format and expected to appear +// verbatim in the input to Parse. +// +// Year: "2006" "06" +// Month: "Jan" "January" +// Textual day of the week: "Mon" "Monday" +// Numeric day of the month: "2" "_2" "02" +// Numeric day of the year: "__2" "002" +// Hour: "15" "3" "03" (PM or AM) +// Minute: "4" "04" +// Second: "5" "05" +// AM/PM mark: "PM" // // Numeric time zone offsets format as follows: -// -0700 ±hhmm -// -07:00 ±hh:mm -// -07 ±hh +// "-0700" ±hhmm +// "-07:00" ±hh:mm +// "-07" ±hh // Replacing the sign in the format with a Z triggers // the ISO 8601 behavior of printing Z instead of an // offset for the UTC zone. Thus: -// Z0700 Z or ±hhmm -// Z07:00 Z or ±hh:mm -// Z07 Z or ±hh +// "Z0700" Z or ±hhmm +// "Z07:00" Z or ±hh:mm +// "Z07" Z or ±hh // -// The recognized day of week formats are "Mon" and "Monday". -// The recognized month formats are "Jan" and "January". +// Within the format string, the underscores in "_2" and "__2" represent spaces +// that may be replaced by digits if the following number has multiple digits, +// for compatibility with fixed-width Unix time formats. A leading zero represents +// a zero-padded value. // -// The formats 2, _2, and 02 are unpadded, space-padded, and zero-padded -// day of month. The formats __2 and 002 are space-padded and zero-padded +// The formats and 002 are space-padded and zero-padded // three-character day of year; there is no unpadded day of year format. // -// Text in the format string that is not recognized as part of the reference -// time is echoed verbatim during Format and expected to appear verbatim -// in the input to Parse. +// A decimal point followed by one or more zeros represents a fractional +// second, printed to the given number of decimal places. +// Either a comma or decimal point followed by one or more nines represents +// a fractional second, printed to the given number of decimal places, with +// trailing zeros removed. +// For example "15:04:05,000" or "15:04:05.000" formats or parses with +// millisecond precision. // -// The executable example for Time.Format demonstrates the working -// of the layout string in detail and is a good reference. +// Some valid layouts are invalid time values for time.Parse, due to formats +// such as _ for space padding and Z for zone information. // -// Note that the RFC822, RFC850, and RFC1123 formats should be applied -// only to local times. Applying them to UTC times will use "UTC" as the -// time zone abbreviation, while strictly speaking those RFCs require the -// use of "GMT" in that case. -// In general RFC1123Z should be used instead of RFC1123 for servers -// that insist on that format, and RFC3339 should be preferred for new protocols. -// RFC3339, RFC822, RFC822Z, RFC1123, and RFC1123Z are useful for formatting; -// when used with time.Parse they do not accept all the time formats -// permitted by the RFCs and they do accept time formats not formally defined. -// The RFC3339Nano format removes trailing zeros from the seconds field -// and thus may not sort correctly once formatted. const ( + Layout = "01/02 03:04:05PM '06 -0700" // The reference time, in numerical order. ANSIC = "Mon Jan _2 15:04:05 2006" UnixDate = "Mon Jan _2 15:04:05 MST 2006" RubyDate = "Mon Jan 02 15:04:05 -0700 2006" @@ -261,7 +280,7 @@ func nextStdChunk(layout string) (prefix string, std int, suffix string) { return layout[0:i], stdISO8601ShortTZ, layout[i+3:] } - case '.': // .000 or .999 - repeated digits for fractional seconds. + case '.', ',': // ,000, or .000, or ,999, or .999 - repeated digits for fractional seconds. if i+1 < len(layout) && (layout[i+1] == '0' || layout[i+1] == '9') { ch := layout[i+1] j := i + 1 @@ -476,22 +495,66 @@ func (t Time) String() string { return s } -// Format returns a textual representation of the time value formatted -// according to layout, which defines the format by showing how the reference -// time, defined to be -// Mon Jan 2 15:04:05 -0700 MST 2006 -// would be displayed if it were the value; it serves as an example of the -// desired output. The same display rules will then be applied to the time -// value. -// -// A fractional second is represented by adding a period and zeros -// to the end of the seconds section of layout string, as in "15:04:05.000" -// to format a time stamp with millisecond precision. +// GoString implements fmt.GoStringer and formats t to be printed in Go source +// code. +func (t Time) GoString() string { + buf := []byte("time.Date(") + buf = appendInt(buf, t.Year(), 0) + month := t.Month() + if January <= month && month <= December { + buf = append(buf, ", time."...) + buf = append(buf, t.Month().String()...) + } else { + // It's difficult to construct a time.Time with a date outside the + // standard range but we might as well try to handle the case. + buf = appendInt(buf, int(month), 0) + } + buf = append(buf, ", "...) + buf = appendInt(buf, t.Day(), 0) + buf = append(buf, ", "...) + buf = appendInt(buf, t.Hour(), 0) + buf = append(buf, ", "...) + buf = appendInt(buf, t.Minute(), 0) + buf = append(buf, ", "...) + buf = appendInt(buf, t.Second(), 0) + buf = append(buf, ", "...) + buf = appendInt(buf, t.Nanosecond(), 0) + buf = append(buf, ", "...) + switch loc := t.Location(); loc { + case UTC, nil: + buf = append(buf, "time.UTC"...) + case Local: + buf = append(buf, "time.Local"...) + default: + // there are several options for how we could display this, none of + // which are great: + // + // - use Location(loc.name), which is not technically valid syntax + // - use LoadLocation(loc.name), which will cause a syntax error when + // embedded and also would require us to escape the string without + // importing fmt or strconv + // - try to use FixedZone, which would also require escaping the name + // and would represent e.g. "America/Los_Angeles" daylight saving time + // shifts inaccurately + // - use the pointer format, which is no worse than you'd get with the + // old fmt.Sprintf("%#v", t) format. + // + // Of these, Location(loc.name) is the least disruptive. This is an edge + // case we hope not to hit too often. + buf = append(buf, `time.Location(`...) + buf = append(buf, []byte(quote(loc.name))...) + buf = append(buf, `)`...) + } + buf = append(buf, ')') + return string(buf) +} + +// Format returns a textual representation of the time value formatted according +// to the layout defined by the argument. See the documentation for the +// constant called Layout to see how to represent the layout format. // -// Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard -// and convenient representations of the reference time. For more information -// about the formats and the definition of the reference time, see the -// documentation for ANSIC and the other constants defined by this package. +// The executable example for Time.Format demonstrates the working +// of the layout string in detail and is a good reference. func (t Time) Format(layout string) string { const bufSize = 64 var b []byte @@ -686,8 +749,48 @@ type ParseError struct { Message string } +// These are borrowed from unicode/utf8 and strconv and replicate behavior in +// that package, since we can't take a dependency on either. +const ( + lowerhex = "0123456789abcdef" + runeSelf = 0x80 + runeError = '\uFFFD' +) + func quote(s string) string { - return "\"" + s + "\"" + buf := make([]byte, 1, len(s)+2) // slice will be at least len(s) + quotes + buf[0] = '"' + for i, c := range s { + if c >= runeSelf || c < ' ' { + // This means you are asking us to parse a time.Duration or + // time.Location with unprintable or non-ASCII characters in it. + // We don't expect to hit this case very often. We could try to + // reproduce strconv.Quote's behavior with full fidelity but + // given how rarely we expect to hit these edge cases, speed and + // conciseness are better. + var width int + if c == runeError { + width = 1 + if i+2 < len(s) && s[i:i+3] == string(runeError) { + width = 3 + } + } else { + width = len(string(c)) + } + for j := 0; j < width; j++ { + buf = append(buf, `\x`...) + buf = append(buf, lowerhex[s[i+j]>>4]) + buf = append(buf, lowerhex[s[i+j]&0xF]) + } + } else { + if c == '"' || c == '\\' { + buf = append(buf, '\\') + } + buf = append(buf, string(c)...) + } + } + buf = append(buf, '"') + return string(buf) } // Error returns the string representation of a ParseError. @@ -771,21 +874,19 @@ func skip(value, prefix string) (string, error) { } // Parse parses a formatted string and returns the time value it represents. -// The layout defines the format by showing how the reference time, -// defined to be -// Mon Jan 2 15:04:05 -0700 MST 2006 -// would be interpreted if it were the value; it serves as an example of -// the input format. The same interpretation will then be made to the -// input string. +// See the documentation for the constant called Layout to see how to +// represent the format. The second argument must be parseable using +// the format string (layout) provided as the first argument. // -// Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard -// and convenient representations of the reference time. For more information -// about the formats and the definition of the reference time, see the -// documentation for ANSIC and the other constants defined by this package. -// Also, the executable example for Time.Format demonstrates the working -// of the layout string in detail and is a good reference. +// The example for Time.Format demonstrates the working of the layout string +// in detail and is a good reference. +// +// When parsing (only), the input may contain a fractional second +// field immediately after the seconds field, even if the layout does not +// signify its presence. In that case either a comma or a decimal point +// followed by a maximal series of digits is parsed as a fractional second. // -// Elements omitted from the value are assumed to be zero or, when +// Elements omitted from the layout are assumed to be zero or, when // zero is impossible, one, so parsing "3:04pm" returns the time // corresponding to Jan 1, year 0, 15:04:00 UTC (note that because the year is // 0, this time is before the zero Time). @@ -795,6 +896,8 @@ func skip(value, prefix string) (string, error) { // For layouts specifying the two-digit year 06, a value NN >= 69 will be treated // as 19NN and a value NN < 69 will be treated as 20NN. // +// The remainder of this comment describes the handling of time zones. +// // In the absence of a time zone indicator, Parse returns a time in UTC. // // When parsing a time with a zone offset like -0700, if the offset corresponds @@ -940,7 +1043,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) } // Special case: do we have a fractional second but no // fractional second in the format? - if len(value) >= 2 && value[0] == '.' && isDigit(value, 1) { + if len(value) >= 2 && commaOrPeriod(value[0]) && isDigit(value, 1) { _, std, _ = nextStdChunk(layout) std &= stdMask if std == stdFracSecond0 || std == stdFracSecond9 { @@ -1070,7 +1173,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) value = value[ndigit:] case stdFracSecond9: - if len(value) < 2 || value[0] != '.' || value[1] < '0' || '9' < value[1] { + if len(value) < 2 || !commaOrPeriod(value[0]) || value[1] < '0' || '9' < value[1] { // Fractional second omitted. break } @@ -1152,7 +1255,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) // Look for local zone with the given offset. // If that zone was in effect at the given time, use it. - name, offset, _, _ := local.lookup(t.unixSec()) + name, offset, _, _, _ := local.lookup(t.unixSec()) if offset == zoneOffset && (zoneName == "" || name == zoneName) { t.setLoc(local) return t, nil @@ -1279,8 +1382,12 @@ func parseSignedOffset(value string) int { return len(value) - len(rem) } +func commaOrPeriod(b byte) bool { + return b == '.' || b == ',' +} + func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) { - if value[0] != '.' { + if !commaOrPeriod(value[0]) { err = errBad return } diff --git a/libgo/go/time/format_test.go b/libgo/go/time/format_test.go index 676117c..eda5fde 100644 --- a/libgo/go/time/format_test.go +++ b/libgo/go/time/format_test.go @@ -129,6 +129,31 @@ func TestFormat(t *testing.T) { } } +var goStringTests = []struct { + in Time + want string +}{ + {Date(2009, February, 5, 5, 0, 57, 12345600, UTC), + "time.Date(2009, time.February, 5, 5, 0, 57, 12345600, time.UTC)"}, + {Date(2009, February, 5, 5, 0, 57, 12345600, Local), + "time.Date(2009, time.February, 5, 5, 0, 57, 12345600, time.Local)"}, + {Date(2009, February, 5, 5, 0, 57, 12345600, FixedZone("Europe/Berlin", 3*60*60)), + `time.Date(2009, time.February, 5, 5, 0, 57, 12345600, time.Location("Europe/Berlin"))`, + }, + {Date(2009, February, 5, 5, 0, 57, 12345600, FixedZone("Non-ASCII character ⏰", 3*60*60)), + `time.Date(2009, time.February, 5, 5, 0, 57, 12345600, time.Location("Non-ASCII character \xe2\x8f\xb0"))`, + }, +} + +func TestGoString(t *testing.T) { + // The numeric time represents Thu Feb 4 21:00:57.012345600 PST 2009 + for _, tt := range goStringTests { + if tt.in.GoString() != tt.want { + t.Errorf("GoString (%q): got %q want %q", tt.in, tt.in.GoString(), tt.want) + } + } +} + // issue 12440. func TestFormatSingleDigits(t *testing.T) { time := Date(2001, 2, 3, 4, 5, 6, 700000000, UTC) @@ -207,9 +232,13 @@ var parseTests = []ParseTest{ {"ANSIC", ANSIC, "THU FEB 4 21:00:57 2010", false, true, 1, 0}, {"ANSIC", ANSIC, "thu feb 4 21:00:57 2010", false, true, 1, 0}, // Fractional seconds. - {"millisecond", "Mon Jan _2 15:04:05.000 2006", "Thu Feb 4 21:00:57.012 2010", false, true, 1, 3}, - {"microsecond", "Mon Jan _2 15:04:05.000000 2006", "Thu Feb 4 21:00:57.012345 2010", false, true, 1, 6}, - {"nanosecond", "Mon Jan _2 15:04:05.000000000 2006", "Thu Feb 4 21:00:57.012345678 2010", false, true, 1, 9}, + {"millisecond:: dot separator", "Mon Jan _2 15:04:05.000 2006", "Thu Feb 4 21:00:57.012 2010", false, true, 1, 3}, + {"microsecond:: dot separator", "Mon Jan _2 15:04:05.000000 2006", "Thu Feb 4 21:00:57.012345 2010", false, true, 1, 6}, + {"nanosecond:: dot separator", "Mon Jan _2 15:04:05.000000000 2006", "Thu Feb 4 21:00:57.012345678 2010", false, true, 1, 9}, + {"millisecond:: comma separator", "Mon Jan _2 15:04:05,000 2006", "Thu Feb 4 21:00:57.012 2010", false, true, 1, 3}, + {"microsecond:: comma separator", "Mon Jan _2 15:04:05,000000 2006", "Thu Feb 4 21:00:57.012345 2010", false, true, 1, 6}, + {"nanosecond:: comma separator", "Mon Jan _2 15:04:05,000000000 2006", "Thu Feb 4 21:00:57.012345678 2010", false, true, 1, 9}, + // Leading zeros in other places should not be taken as fractional seconds. {"zero1", "2006.01.02.15.04.05.0", "2010.02.04.21.00.57.0", false, false, 1, 1}, {"zero2", "2006.01.02.15.04.05.00", "2010.02.04.21.00.57.01", false, false, 1, 2}, @@ -222,12 +251,20 @@ var parseTests = []ParseTest{ // Accept any number of fractional second digits (including none) for .999... // In Go 1, .999... was completely ignored in the format, meaning the first two // cases would succeed, but the next four would not. Go 1.1 accepts all six. + // decimal "." separator. {"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0}, {"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0}, {"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4}, {"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4}, {"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9}, {"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9}, + // comma "," separator. + {"", "2006-01-02 15:04:05,9999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0}, + {"", "2006-01-02 15:04:05,999999999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0}, + {"", "2006-01-02 15:04:05,9999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4}, + {"", "2006-01-02 15:04:05,999999999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4}, + {"", "2006-01-02 15:04:05,9999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9}, + {"", "2006-01-02 15:04:05,999999999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9}, // issue 4502. {"", StampNano, "Feb 4 21:00:57.012345678", false, false, -1, 9}, @@ -553,6 +590,10 @@ var parseErrorTests = []ParseErrorTest{ // invalid or mismatched day-of-year {"Jan _2 002 2006", "Feb 4 034 2006", "day-of-year does not match day"}, {"Jan _2 002 2006", "Feb 4 004 2006", "day-of-year does not match month"}, + + // issue 45391. + {`"2006-01-02T15:04:05Z07:00"`, "0", `parsing time "0" as "\"2006-01-02T15:04:05Z07:00\"": cannot parse "0" as "\""`}, + {RFC3339, "\"", `parsing time "\"" as "2006-01-02T15:04:05Z07:00": cannot parse "\"" as "2006"`}, } func TestParseErrors(t *testing.T) { @@ -772,3 +813,24 @@ func TestParseYday(t *testing.T) { } } } + +// Issue 45391. +func TestQuote(t *testing.T) { + tests := []struct { + s, want string + }{ + {`"`, `"\""`}, + {`abc"xyz"`, `"abc\"xyz\""`}, + {"", `""`}, + {"abc", `"abc"`}, + {`☺`, `"\xe2\x98\xba"`}, + {`☺ hello ☺ hello`, `"\xe2\x98\xba hello \xe2\x98\xba hello"`}, + {"\x04", `"\x04"`}, + } + for _, tt := range tests { + if q := Quote(tt.s); q != tt.want { + t.Errorf("Quote(%q) = got %q, want %q", tt.s, q, tt.want) + } + } + +} diff --git a/libgo/go/time/genzabbrs.go b/libgo/go/time/genzabbrs.go index 9825e70..9fd2f2b 100644 --- a/libgo/go/time/genzabbrs.go +++ b/libgo/go/time/genzabbrs.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // diff --git a/libgo/go/time/internal_test.go b/libgo/go/time/internal_test.go index 362ce49..93942d2 100644 --- a/libgo/go/time/internal_test.go +++ b/libgo/go/time/internal_test.go @@ -67,4 +67,6 @@ func CheckRuntimeTimerPeriodOverflow() { var ( MinMonoTime = Time{wall: 1 << 63, ext: -1 << 63, loc: UTC} MaxMonoTime = Time{wall: 1 << 63, ext: 1<<63 - 1, loc: UTC} + + NotMonoNegativeTime = Time{wall: 0, ext: -1<<63 + 50} ) diff --git a/libgo/go/time/sleep_test.go b/libgo/go/time/sleep_test.go index fb66e70..2c8db0a 100644 --- a/libgo/go/time/sleep_test.go +++ b/libgo/go/time/sleep_test.go @@ -528,6 +528,40 @@ func TestZeroTimer(t *testing.T) { } } +// Test that rapidly moving a timer earlier doesn't cause it to get dropped. +// Issue 47329. +func TestTimerModifiedEarlier(t *testing.T) { + past := Until(Unix(0, 0)) + count := 1000 + fail := 0 + for i := 0; i < count; i++ { + timer := NewTimer(Hour) + for j := 0; j < 10; j++ { + if !timer.Stop() { + <-timer.C + } + timer.Reset(past) + } + + deadline := NewTimer(10 * Second) + defer deadline.Stop() + now := Now() + select { + case <-timer.C: + if since := Since(now); since > 8*Second { + t.Errorf("timer took too long (%v)", since) + fail++ + } + case <-deadline.C: + t.Error("deadline expired") + } + } + + if fail > 0 { + t.Errorf("%d failures", fail) + } +} + // Benchmark timer latency when the thread that creates the timer is busy with // other work and the timers must be serviced by other threads. // https://golang.org/issue/38860 diff --git a/libgo/go/time/sys_plan9.go b/libgo/go/time/sys_plan9.go index b7fba08..4dc55e4 100644 --- a/libgo/go/time/sys_plan9.go +++ b/libgo/go/time/sys_plan9.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build plan9 // +build plan9 package time diff --git a/libgo/go/time/sys_unix.go b/libgo/go/time/sys_unix.go index ec98d6e..b9f8c76 100644 --- a/libgo/go/time/sys_unix.go +++ b/libgo/go/time/sys_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd hurd js,wasm linux netbsd openbsd solaris package time diff --git a/libgo/go/time/testdata/2020b_Europe_Berlin b/libgo/go/time/testdata/2020b_Europe_Berlin Binary files differnew file mode 100644 index 0000000..465546b --- /dev/null +++ b/libgo/go/time/testdata/2020b_Europe_Berlin diff --git a/libgo/go/time/testdata/2021a_America_Nuuk b/libgo/go/time/testdata/2021a_America_Nuuk Binary files differnew file mode 100644 index 0000000..4ddc99d --- /dev/null +++ b/libgo/go/time/testdata/2021a_America_Nuuk diff --git a/libgo/go/time/testdata/2021a_Asia_Gaza b/libgo/go/time/testdata/2021a_Asia_Gaza Binary files differnew file mode 100644 index 0000000..58e9fdf --- /dev/null +++ b/libgo/go/time/testdata/2021a_Asia_Gaza diff --git a/libgo/go/time/testdata/2021a_Europe_Dublin b/libgo/go/time/testdata/2021a_Europe_Dublin Binary files differnew file mode 100644 index 0000000..4a45ea8 --- /dev/null +++ b/libgo/go/time/testdata/2021a_Europe_Dublin diff --git a/libgo/go/time/tick_test.go b/libgo/go/time/tick_test.go index 9a1cdf9..b5d0a18 100644 --- a/libgo/go/time/tick_test.go +++ b/libgo/go/time/tick_test.go @@ -52,9 +52,14 @@ func TestTicker(t *testing.T) { t1 := Now() dt := t1.Sub(t0) target := 3 * delta * Duration(count/2) - slop := target * 2 / 10 + slop := target * 3 / 10 if dt < target-slop || dt > target+slop { - errs = append(errs, fmt.Sprintf("%d %s ticks took %s, expected [%s,%s]", count, delta, dt, target-slop, target+slop)) + errs = append(errs, fmt.Sprintf("%d %s ticks then %d %s ticks took %s, expected [%s,%s]", count/2, delta, count/2, delta*2, dt, target-slop, target+slop)) + if dt > target+slop { + // System may be overloaded; sleep a bit + // in the hopes it will recover. + Sleep(Second / 2) + } continue } // Now test that the ticker stopped. diff --git a/libgo/go/time/time.go b/libgo/go/time/time.go index 8ae6230..4ecc3d8 100644 --- a/libgo/go/time/time.go +++ b/libgo/go/time/time.go @@ -189,8 +189,15 @@ func (t *Time) addSec(d int64) { t.stripMono() } - // TODO: Check for overflow. - t.ext += d + // Check if the sum of t.ext and d overflows and handle it properly. + sum := t.ext + d + if (sum > t.ext) == (d > 0) { + t.ext = sum + } else if d > 0 { + t.ext = 1<<63 - 1 + } else { + t.ext = -(1<<63 - 1) + } } // setLoc sets the location associated with the time. @@ -440,7 +447,7 @@ func (t Time) abs() uint64 { if l.cacheZone != nil && l.cacheStart <= sec && sec < l.cacheEnd { sec += int64(l.cacheZone.offset) } else { - _, offset, _, _ := l.lookup(sec) + _, offset, _, _, _ := l.lookup(sec) sec += int64(offset) } } @@ -461,7 +468,7 @@ func (t Time) locabs() (name string, offset int, abs uint64) { name = l.cacheZone.name offset = l.cacheZone.offset } else { - name, offset, _, _ = l.lookup(sec) + name, offset, _, _, _ = l.lookup(sec) } sec += int64(offset) } else { @@ -1114,7 +1121,7 @@ func (t Time) Location() *Location { // Zone computes the time zone in effect at time t, returning the abbreviated // name of the zone (such as "CET") and its offset in seconds east of UTC. func (t Time) Zone() (name string, offset int) { - name, offset, _, _ = t.loc.lookup(t.unixSec()) + name, offset, _, _, _ = t.loc.lookup(t.unixSec()) return } @@ -1128,6 +1135,24 @@ func (t Time) Unix() int64 { return t.unixSec() } +// UnixMilli returns t as a Unix time, the number of milliseconds elapsed since +// January 1, 1970 UTC. The result is undefined if the Unix time in +// milliseconds cannot be represented by an int64 (a date more than 292 million +// years before or after 1970). The result does not depend on the +// location associated with t. +func (t Time) UnixMilli() int64 { + return t.unixSec()*1e3 + int64(t.nsec())/1e6 +} + +// UnixMicro returns t as a Unix time, the number of microseconds elapsed since +// January 1, 1970 UTC. The result is undefined if the Unix time in +// microseconds cannot be represented by an int64 (a date before year -290307 or +// after year 294246). The result does not depend on the location associated +// with t. +func (t Time) UnixMicro() int64 { + return t.unixSec()*1e6 + int64(t.nsec())/1e3 +} + // UnixNano returns t as a Unix time, the number of nanoseconds elapsed // since January 1, 1970 UTC. The result is undefined if the Unix time // in nanoseconds cannot be represented by an int64 (a date before the year @@ -1212,7 +1237,7 @@ func (t *Time) UnmarshalBinary(data []byte) error { if offset == -1*60 { t.setLoc(&utcLoc) - } else if _, localoff, _, _ := Local.lookup(t.unixSec()); offset == localoff { + } else if _, localoff, _, _, _ := Local.lookup(t.unixSec()); offset == localoff { t.setLoc(Local) } else { t.setLoc(FixedZone("", offset)) @@ -1302,6 +1327,24 @@ func Unix(sec int64, nsec int64) Time { return unixTime(sec, int32(nsec)) } +// UnixMilli returns the local Time corresponding to the given Unix time, +// msec milliseconds since January 1, 1970 UTC. +func UnixMilli(msec int64) Time { + return Unix(msec/1e3, (msec%1e3)*1e6) +} + +// UnixMicro returns the local Time corresponding to the given Unix time, +// usec microseconds since January 1, 1970 UTC. +func UnixMicro(usec int64) Time { + return Unix(usec/1e6, (usec%1e6)*1e3) +} + +// IsDST reports whether the time in the configured location is in Daylight Savings Time. +func (t Time) IsDST() bool { + _, _, _, _, isDST := t.loc.lookup(t.Unix()) + return isDST +} + func isLeap(year int) bool { return year%4 == 0 && (year%100 != 0 || year%400 == 0) } @@ -1377,13 +1420,13 @@ func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) T // The lookup function expects UTC, so we pass t in the // hope that it will not be too close to a zone transition, // and then adjust if it is. - _, offset, start, end := loc.lookup(unix) + _, offset, start, end, _ := loc.lookup(unix) if offset != 0 { switch utc := unix - int64(offset); { case utc < start: - _, offset, _, _ = loc.lookup(start - 1) + _, offset, _, _, _ = loc.lookup(start - 1) case utc >= end: - _, offset, _, _ = loc.lookup(end) + _, offset, _, _, _ = loc.lookup(end) } unix -= int64(offset) } diff --git a/libgo/go/time/time_test.go b/libgo/go/time/time_test.go index 154198a..cea5f2d 100644 --- a/libgo/go/time/time_test.go +++ b/libgo/go/time/time_test.go @@ -202,6 +202,28 @@ func TestNanosecondsToUTCAndBack(t *testing.T) { } } +func TestUnixMilli(t *testing.T) { + f := func(msec int64) bool { + t := UnixMilli(msec) + return t.UnixMilli() == msec + } + cfg := &quick.Config{MaxCount: 10000} + if err := quick.Check(f, cfg); err != nil { + t.Fatal(err) + } +} + +func TestUnixMicro(t *testing.T) { + f := func(usec int64) bool { + t := UnixMicro(usec) + return t.UnixMicro() == usec + } + cfg := &quick.Config{MaxCount: 10000} + if err := quick.Check(f, cfg); err != nil { + t.Fatal(err) + } +} + // The time routines provide no way to get absolute time // (seconds since zero), but we need it to compute the right // answer for bizarre roundings like "to the nearest 3 ns". @@ -895,6 +917,11 @@ var parseDurationErrorTests = []struct { {".s", `".s"`}, {"+.s", `"+.s"`}, {"1d", `"1d"`}, + {"\x85\x85", `"\x85\x85"`}, + {"\xffff", `"\xffff"`}, + {"hello \xffff world", `"hello \xffff world"`}, + {"\uFFFD", `"\xef\xbf\xbd"`}, // utf8.RuneError + {"\uFFFD hello \uFFFD world", `"\xef\xbf\xbd hello \xef\xbf\xbd world"`}, // utf8.RuneError // overflow {"9223372036854775810ns", `"9223372036854775810ns"`}, {"9223372036854775808ns", `"9223372036854775808ns"`}, @@ -959,6 +986,8 @@ var mallocTest = []struct { }{ {0, `time.Now()`, func() { t = Now() }}, {0, `time.Now().UnixNano()`, func() { u = Now().UnixNano() }}, + {0, `time.Now().UnixMilli()`, func() { u = Now().UnixMilli() }}, + {0, `time.Now().UnixMicro()`, func() { u = Now().UnixMicro() }}, } func TestCountMallocs(t *testing.T) { @@ -1249,6 +1278,8 @@ var defaultLocTests = []struct { {"Unix", func(t1, t2 Time) bool { return t1.Unix() == t2.Unix() }}, {"UnixNano", func(t1, t2 Time) bool { return t1.UnixNano() == t2.UnixNano() }}, + {"UnixMilli", func(t1, t2 Time) bool { return t1.UnixMilli() == t2.UnixMilli() }}, + {"UnixMicro", func(t1, t2 Time) bool { return t1.UnixMicro() == t2.UnixMicro() }}, {"MarshalBinary", func(t1, t2 Time) bool { a1, b1 := t1.MarshalBinary() @@ -1301,6 +1332,18 @@ func BenchmarkNowUnixNano(b *testing.B) { } } +func BenchmarkNowUnixMilli(b *testing.B) { + for i := 0; i < b.N; i++ { + u = Now().UnixMilli() + } +} + +func BenchmarkNowUnixMicro(b *testing.B) { + for i := 0; i < b.N; i++ { + u = Now().UnixMicro() + } +} + func BenchmarkFormat(b *testing.B) { t := Unix(1265346057, 0) for i := 0; i < b.N; i++ { @@ -1465,3 +1508,64 @@ func TestConcurrentTimerResetStop(t *testing.T) { } wg.Wait() } + +func TestTimeIsDST(t *testing.T) { + ForceZipFileForTesting(true) + defer ForceZipFileForTesting(false) + + tzWithDST, err := LoadLocation("Australia/Sydney") + if err != nil { + t.Fatalf("could not load tz 'Australia/Sydney': %v", err) + } + tzWithoutDST, err := LoadLocation("Australia/Brisbane") + if err != nil { + t.Fatalf("could not load tz 'Australia/Brisbane': %v", err) + } + tzFixed := FixedZone("FIXED_TIME", 12345) + + tests := [...]struct { + time Time + want bool + }{ + 0: {Date(2009, 1, 1, 12, 0, 0, 0, UTC), false}, + 1: {Date(2009, 6, 1, 12, 0, 0, 0, UTC), false}, + 2: {Date(2009, 1, 1, 12, 0, 0, 0, tzWithDST), true}, + 3: {Date(2009, 6, 1, 12, 0, 0, 0, tzWithDST), false}, + 4: {Date(2009, 1, 1, 12, 0, 0, 0, tzWithoutDST), false}, + 5: {Date(2009, 6, 1, 12, 0, 0, 0, tzWithoutDST), false}, + 6: {Date(2009, 1, 1, 12, 0, 0, 0, tzFixed), false}, + 7: {Date(2009, 6, 1, 12, 0, 0, 0, tzFixed), false}, + } + + for i, tt := range tests { + got := tt.time.IsDST() + if got != tt.want { + t.Errorf("#%d:: (%#v).IsDST()=%t, want %t", i, tt.time.Format(RFC3339), got, tt.want) + } + } +} + +func TestTimeAddSecOverflow(t *testing.T) { + // Test it with positive delta. + var maxInt64 int64 = 1<<63 - 1 + timeExt := maxInt64 - UnixToInternal - 50 + notMonoTime := Unix(timeExt, 0) + for i := int64(0); i < 100; i++ { + sec := notMonoTime.Unix() + notMonoTime = notMonoTime.Add(Duration(i * 1e9)) + if newSec := notMonoTime.Unix(); newSec != sec+i && newSec+UnixToInternal != maxInt64 { + t.Fatalf("time ext: %d overflows with positive delta, overflow threshold: %d", newSec, maxInt64) + } + } + + // Test it with negative delta. + maxInt64 = -maxInt64 + notMonoTime = NotMonoNegativeTime + for i := int64(0); i > -100; i-- { + sec := notMonoTime.Unix() + notMonoTime = notMonoTime.Add(Duration(i * 1e9)) + if newSec := notMonoTime.Unix(); newSec != sec+i && newSec+UnixToInternal != maxInt64 { + t.Fatalf("time ext: %d overflows with positive delta, overflow threshold: %d", newSec, maxInt64) + } + } +} diff --git a/libgo/go/time/tzdata/generate_zipdata.go b/libgo/go/time/tzdata/generate_zipdata.go index 21357fb..64b5b1b 100644 --- a/libgo/go/time/tzdata/generate_zipdata.go +++ b/libgo/go/time/tzdata/generate_zipdata.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ignore // +build ignore // This program generates zipdata.go from $GOROOT/lib/time/zoneinfo.zip. diff --git a/libgo/go/time/zoneinfo.go b/libgo/go/time/zoneinfo.go index 5705233..57aed03f 100644 --- a/libgo/go/time/zoneinfo.go +++ b/libgo/go/time/zoneinfo.go @@ -121,7 +121,7 @@ func FixedZone(name string, offset int) *Location { // the start and end times bracketing sec when that zone is in effect, // the offset in seconds east of UTC (such as -5*60*60), and whether // the daylight savings is being observed at that time. -func (l *Location) lookup(sec int64) (name string, offset int, start, end int64) { +func (l *Location) lookup(sec int64) (name string, offset int, start, end int64, isDST bool) { l = l.get() if len(l.zone) == 0 { @@ -129,6 +129,7 @@ func (l *Location) lookup(sec int64) (name string, offset int, start, end int64) offset = 0 start = alpha end = omega + isDST = false return } @@ -137,6 +138,7 @@ func (l *Location) lookup(sec int64) (name string, offset int, start, end int64) offset = zone.offset start = l.cacheStart end = l.cacheEnd + isDST = zone.isDST return } @@ -150,6 +152,7 @@ func (l *Location) lookup(sec int64) (name string, offset int, start, end int64) } else { end = omega } + isDST = zone.isDST return } @@ -174,12 +177,13 @@ func (l *Location) lookup(sec int64) (name string, offset int, start, end int64) offset = zone.offset start = tx[lo].when // end = maintained during the search + isDST = zone.isDST // 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 { - return ename, eoffset, estart, eend + if ename, eoffset, estart, eend, eisDST, ok := tzset(l.extend, end, sec); ok { + return ename, eoffset, estart, eend, eisDST } } @@ -592,7 +596,7 @@ func (l *Location) lookupName(name string, unix int64) (offset int, ok bool) { for i := range l.zone { zone := &l.zone[i] if zone.name == name { - nam, offset, _, _ := l.lookup(unix - int64(zone.offset)) + nam, offset, _, _, _ := l.lookup(unix - int64(zone.offset)) if nam == zone.name { return offset, true } diff --git a/libgo/go/time/zoneinfo_ios.go b/libgo/go/time/zoneinfo_ios.go index 0f1e933..044691e 100644 --- a/libgo/go/time/zoneinfo_ios.go +++ b/libgo/go/time/zoneinfo_ios.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build ios // +build ios package time diff --git a/libgo/go/time/zoneinfo_js.go b/libgo/go/time/zoneinfo_js.go index 2d76a57..8245614 100644 --- a/libgo/go/time/zoneinfo_js.go +++ b/libgo/go/time/zoneinfo_js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js && wasm // +build js,wasm package time diff --git a/libgo/go/time/zoneinfo_test.go b/libgo/go/time/zoneinfo_test.go index a9b4f07..54dae17 100644 --- a/libgo/go/time/zoneinfo_test.go +++ b/libgo/go/time/zoneinfo_test.go @@ -25,8 +25,7 @@ func TestEnvVarUsage(t *testing.T) { const testZoneinfo = "foo.zip" const env = "ZONEINFO" - defer os.Setenv(env, os.Getenv(env)) - os.Setenv(env, testZoneinfo) + t.Setenv(env, testZoneinfo) // Result isn't important, we're testing the side effect of this command time.LoadLocation("Asia/Jerusalem") @@ -50,8 +49,7 @@ func TestBadLocationErrMsg(t *testing.T) { func TestLoadLocationValidatesNames(t *testing.T) { time.ResetZoneinfoForTesting() const env = "ZONEINFO" - defer os.Setenv(env, os.Getenv(env)) - os.Setenv(env, "") + t.Setenv(env, "") bad := []string{ "/usr/foo/Foo", @@ -191,7 +189,7 @@ func TestMalformedTZData(t *testing.T) { var slimTests = []struct { zoneName string - tzData string + fileName string date func(*time.Location) time.Time wantName string wantOffset int @@ -199,7 +197,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", + fileName: "2020b_Europe_Berlin", date: func(loc *time.Location) time.Time { return time.Date(2020, time.October, 29, 15, 30, 0, 0, loc) }, wantName: "CET", wantOffset: 3600, @@ -207,7 +205,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", + fileName: "2021a_America_Nuuk", date: func(loc *time.Location) time.Time { return time.Date(2020, time.October, 29, 15, 30, 0, 0, loc) }, wantName: "-03", wantOffset: -10800, @@ -215,7 +213,7 @@ 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", + fileName: "2021a_Asia_Gaza", date: func(loc *time.Location) time.Time { return time.Date(2020, time.October, 29, 15, 30, 0, 0, loc) }, wantName: "EET", wantOffset: 7200, @@ -223,7 +221,7 @@ var slimTests = []struct { { // 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", + fileName: "2021a_Europe_Dublin", date: func(loc *time.Location) time.Time { return time.Date(2021, time.April, 2, 11, 12, 13, 0, loc) }, wantName: "IST", wantOffset: 3600, @@ -232,9 +230,15 @@ var slimTests = []struct { func TestLoadLocationFromTZDataSlim(t *testing.T) { for _, test := range slimTests { - reference, err := time.LoadLocationFromTZData(test.zoneName, []byte(test.tzData)) + tzData, err := os.ReadFile("testdata/" + test.fileName) if err != nil { - t.Fatal(err) + t.Error(err) + continue + } + reference, err := time.LoadLocationFromTZData(test.zoneName, tzData) + if err != nil { + t.Error(err) + continue } d := test.date(reference) diff --git a/libgo/go/time/zoneinfo_unix.go b/libgo/go/time/zoneinfo_unix.go index 926f309..6e2c08d 100644 --- a/libgo/go/time/zoneinfo_unix.go +++ b/libgo/go/time/zoneinfo_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || (darwin && !ios) || dragonfly || freebsd || hurd || (linux && !android) || netbsd || openbsd || solaris // +build aix darwin,!ios dragonfly freebsd hurd linux,!android netbsd openbsd solaris // Parse "zoneinfo" time zone file. diff --git a/libgo/go/time/zoneinfo_unix_test.go b/libgo/go/time/zoneinfo_unix_test.go index f290ae7..b75b374 100644 --- a/libgo/go/time/zoneinfo_unix_test.go +++ b/libgo/go/time/zoneinfo_unix_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build aix || (darwin && !ios) || dragonfly || freebsd || (linux && !android) || netbsd || openbsd || solaris // +build aix darwin,!ios dragonfly freebsd linux,!android netbsd openbsd solaris package time_test diff --git a/libgo/go/unicode/letter.go b/libgo/go/unicode/letter.go index a57566f..268e457 100644 --- a/libgo/go/unicode/letter.go +++ b/libgo/go/unicode/letter.go @@ -154,7 +154,8 @@ func is32(ranges []Range32, r uint32) bool { // Is reports whether the rune is in the specified table of ranges. func Is(rangeTab *RangeTable, r rune) bool { r16 := rangeTab.R16 - if len(r16) > 0 && r <= rune(r16[len(r16)-1].Hi) { + // Compare as uint32 to correctly handle negative runes. + if len(r16) > 0 && uint32(r) <= uint32(r16[len(r16)-1].Hi) { return is16(r16, uint16(r)) } r32 := rangeTab.R32 @@ -166,7 +167,8 @@ func Is(rangeTab *RangeTable, r rune) bool { func isExcludingLatin(rangeTab *RangeTable, r rune) bool { r16 := rangeTab.R16 - if off := rangeTab.LatinOffset; len(r16) > off && r <= rune(r16[len(r16)-1].Hi) { + // Compare as uint32 to correctly handle negative runes. + if off := rangeTab.LatinOffset; len(r16) > off && uint32(r) <= uint32(r16[len(r16)-1].Hi) { return is16(r16[off:], uint16(r)) } r32 := rangeTab.R32 diff --git a/libgo/go/unicode/letter_test.go b/libgo/go/unicode/letter_test.go index 19ee535..a91e3a3 100644 --- a/libgo/go/unicode/letter_test.go +++ b/libgo/go/unicode/letter_test.go @@ -563,3 +563,82 @@ func TestSpecialCaseNoMapping(t *testing.T) { t.Errorf("got %q; want %q", got, want) } } + +func TestNegativeRune(t *testing.T) { + // Issue 43254 + // These tests cover negative rune handling by testing values which, + // when cast to uint8 or uint16, look like a particular valid rune. + // This package has Latin-1-specific optimizations, so we test all of + // Latin-1 and representative non-Latin-1 values in the character + // categories covered by IsGraphic, etc. + nonLatin1 := []uint32{ + // Lu: LATIN CAPITAL LETTER A WITH MACRON + 0x0100, + // Ll: LATIN SMALL LETTER A WITH MACRON + 0x0101, + // Lt: LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON + 0x01C5, + // M: COMBINING GRAVE ACCENT + 0x0300, + // Nd: ARABIC-INDIC DIGIT ZERO + 0x0660, + // P: GREEK QUESTION MARK + 0x037E, + // S: MODIFIER LETTER LEFT ARROWHEAD + 0x02C2, + // Z: OGHAM SPACE MARK + 0x1680, + } + for i := 0; i < MaxLatin1+len(nonLatin1); i++ { + base := uint32(i) + if i >= MaxLatin1 { + base = nonLatin1[i-MaxLatin1] + } + + // Note r is negative, but uint8(r) == uint8(base) and + // uint16(r) == uint16(base). + r := rune(base - 1<<31) + if Is(Letter, r) { + t.Errorf("Is(Letter, 0x%x - 1<<31) = true, want false", base) + } + if IsControl(r) { + t.Errorf("IsControl(0x%x - 1<<31) = true, want false", base) + } + if IsDigit(r) { + t.Errorf("IsDigit(0x%x - 1<<31) = true, want false", base) + } + if IsGraphic(r) { + t.Errorf("IsGraphic(0x%x - 1<<31) = true, want false", base) + } + if IsLetter(r) { + t.Errorf("IsLetter(0x%x - 1<<31) = true, want false", base) + } + if IsLower(r) { + t.Errorf("IsLower(0x%x - 1<<31) = true, want false", base) + } + if IsMark(r) { + t.Errorf("IsMark(0x%x - 1<<31) = true, want false", base) + } + if IsNumber(r) { + t.Errorf("IsNumber(0x%x - 1<<31) = true, want false", base) + } + if IsPrint(r) { + t.Errorf("IsPrint(0x%x - 1<<31) = true, want false", base) + } + if IsPunct(r) { + t.Errorf("IsPunct(0x%x - 1<<31) = true, want false", base) + } + if IsSpace(r) { + t.Errorf("IsSpace(0x%x - 1<<31) = true, want false", base) + } + if IsSymbol(r) { + t.Errorf("IsSymbol(0x%x - 1<<31) = true, want false", base) + } + if IsTitle(r) { + t.Errorf("IsTitle(0x%x - 1<<31) = true, want false", base) + } + if IsUpper(r) { + t.Errorf("IsUpper(0x%x - 1<<31) = true, want false", base) + } + } +} diff --git a/libgo/go/vendor/modules.txt b/libgo/go/vendor/modules.txt index b18d366..ff01db5 100644 --- a/libgo/go/vendor/modules.txt +++ b/libgo/go/vendor/modules.txt @@ -1,5 +1,5 @@ -# golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 -## explicit +# golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e +## explicit; go 1.17 golang.org/x/crypto/chacha20 golang.org/x/crypto/chacha20poly1305 golang.org/x/crypto/cryptobyte @@ -8,8 +8,8 @@ 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-20210428183300-3f4a416c7d3b -## explicit +# golang.org/x/net v0.0.0-20210510120150-4163338589ed +## explicit; go 1.17 golang.org/x/net/dns/dnsmessage golang.org/x/net/http/httpguts golang.org/x/net/http/httpproxy @@ -18,11 +18,11 @@ golang.org/x/net/idna golang.org/x/net/lif golang.org/x/net/nettest golang.org/x/net/route -# golang.org/x/sys v0.0.0-20201204225414-ed752295db88 -## explicit +# golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 +## explicit; go 1.17 golang.org/x/sys/cpu -# golang.org/x/text v0.3.4 -## explicit +# golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f +## explicit; go 1.17 golang.org/x/text/secure/bidirule golang.org/x/text/transform golang.org/x/text/unicode/bidi |